Better simulate a request happening in the LMS in FieldOverride performance tests
This commit is contained in:
@@ -3,18 +3,21 @@
|
||||
Performance tests for field overrides.
|
||||
"""
|
||||
import ddt
|
||||
import itertools
|
||||
import mock
|
||||
|
||||
from courseware.views import progress # pylint: disable=import-error
|
||||
from datetime import datetime
|
||||
from django.core.cache import cache
|
||||
from django.core.cache import get_cache
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from edxmako.middleware import MakoMiddleware # pylint: disable=import-error
|
||||
from nose.plugins.attrib import attr
|
||||
from pytz import UTC
|
||||
from request_cache.middleware import RequestCache
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import UserFactory # pylint: disable=import-error
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, \
|
||||
TEST_DATA_SPLIT_MODULESTORE, TEST_DATA_MONGO_MODULESTORE
|
||||
from xmodule.modulestore.tests.factories import check_mongo_calls, CourseFactory
|
||||
@@ -32,6 +35,11 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
|
||||
Base class for instrumenting SQL queries and Mongo reads for field override
|
||||
providers.
|
||||
"""
|
||||
__test__ = False
|
||||
|
||||
# TEST_DATA must be overridden by subclasses
|
||||
TEST_DATA = None
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Create a test client, course, and user.
|
||||
@@ -42,14 +50,14 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
|
||||
self.student = UserFactory.create()
|
||||
self.request = self.request_factory.get("foo")
|
||||
self.request.user = self.student
|
||||
self.course = None
|
||||
|
||||
MakoMiddleware().process_request(self.request)
|
||||
|
||||
# TEST_DATA must be overridden by subclasses, otherwise the test is
|
||||
# skipped.
|
||||
self.TEST_DATA = None
|
||||
|
||||
def setup_course(self, size):
|
||||
"""
|
||||
Build a gradable course where each node has `size` children.
|
||||
"""
|
||||
grading_policy = {
|
||||
"GRADER": [
|
||||
{
|
||||
@@ -113,50 +121,39 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
|
||||
"""
|
||||
self.setup_course(dataset_index + 1)
|
||||
|
||||
# Clear the cache before measuring
|
||||
# TODO: remove once django cache is disabled in tests
|
||||
cache.clear()
|
||||
with self.assertNumQueries(queries):
|
||||
with check_mongo_calls(reads):
|
||||
self.grade_course(self.course)
|
||||
# Switch to published-only mode to simulate the LMS
|
||||
with self.settings(MODULESTORE_BRANCH='published-only'):
|
||||
# Clear the cache before measuring
|
||||
# We clear the mongo_metadata_inheritance cache so that we can refill it
|
||||
# with published-only contents.
|
||||
get_cache('mongo_metadata_inheritance').clear()
|
||||
|
||||
def run_if_subclassed(self, test_type, dataset_index):
|
||||
"""
|
||||
Run the query/read instrumentation only if TEST_DATA has been
|
||||
overridden.
|
||||
"""
|
||||
if not self.TEST_DATA:
|
||||
self.skipTest(
|
||||
"Test not properly configured. TEST_DATA must be overridden "
|
||||
"by a subclass."
|
||||
)
|
||||
# Refill the metadata inheritance cache
|
||||
modulestore().get_course(self.course.id, depth=None)
|
||||
|
||||
queries, reads = self.TEST_DATA[test_type][dataset_index]
|
||||
self.instrument_course_progress_render(dataset_index, queries, reads)
|
||||
# We clear the request cache to simulate a new request in the LMS.
|
||||
RequestCache.clear_request_cache()
|
||||
|
||||
@ddt.data((0,), (1,), (2,))
|
||||
with self.assertNumQueries(queries):
|
||||
with check_mongo_calls(reads):
|
||||
self.grade_course(self.course)
|
||||
|
||||
@ddt.data(*itertools.product(('no_overrides', 'ccx'), range(3)))
|
||||
@ddt.unpack
|
||||
@override_settings(
|
||||
FIELD_OVERRIDE_PROVIDERS=(),
|
||||
)
|
||||
def test_instrument_without_field_override(self, dataset):
|
||||
def test_field_overrides(self, overrides, dataset_index):
|
||||
"""
|
||||
Test without any field overrides.
|
||||
"""
|
||||
self.run_if_subclassed('no_overrides', dataset)
|
||||
|
||||
@ddt.data((0,), (1,), (2,))
|
||||
@ddt.unpack
|
||||
@override_settings(
|
||||
FIELD_OVERRIDE_PROVIDERS=(
|
||||
'ccx.overrides.CustomCoursesForEdxOverrideProvider',
|
||||
),
|
||||
)
|
||||
def test_instrument_with_field_override(self, dataset):
|
||||
"""
|
||||
Test with the CCX field override enabled.
|
||||
"""
|
||||
self.run_if_subclassed('ccx', dataset)
|
||||
providers = {
|
||||
'no_overrides': (),
|
||||
'ccx': ('ccx.overrides.CustomCoursesForEdxOverrideProvider',)
|
||||
}
|
||||
with self.settings(FIELD_OVERRIDE_PROVIDERS=providers[overrides]):
|
||||
queries, reads = self.TEST_DATA[overrides][dataset_index]
|
||||
self.instrument_course_progress_render(dataset_index, queries, reads)
|
||||
|
||||
|
||||
class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
|
||||
@@ -164,21 +161,16 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
|
||||
Test cases for instrumenting field overrides against the Mongo modulestore.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_MODULESTORE
|
||||
__test__ = True
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set the modulestore and scaffold the test data.
|
||||
"""
|
||||
super(TestFieldOverrideMongoPerformance, self).setUp()
|
||||
|
||||
self.TEST_DATA = {
|
||||
'no_overrides': [
|
||||
(22, 6), (130, 6), (590, 6)
|
||||
],
|
||||
'ccx': [
|
||||
(22, 6), (130, 6), (590, 6)
|
||||
],
|
||||
}
|
||||
TEST_DATA = {
|
||||
'no_overrides': [
|
||||
(26, 7), (132, 7), (592, 7)
|
||||
],
|
||||
'ccx': [
|
||||
(24, 35), (132, 331), (592, 1507)
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
|
||||
@@ -186,18 +178,13 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
|
||||
Test cases for instrumenting field overrides against the Split modulestore.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
__test__ = True
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set the modulestore and scaffold the test data.
|
||||
"""
|
||||
super(TestFieldOverrideSplitPerformance, self).setUp()
|
||||
|
||||
self.TEST_DATA = {
|
||||
'no_overrides': [
|
||||
(22, 4), (130, 19), (590, 84)
|
||||
],
|
||||
'ccx': [
|
||||
(22, 4), (130, 19), (590, 84)
|
||||
]
|
||||
}
|
||||
TEST_DATA = {
|
||||
'no_overrides': [
|
||||
(24, 4), (132, 19), (592, 84)
|
||||
],
|
||||
'ccx': [
|
||||
(24, 4), (132, 19), (592, 84)
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user