Commit 5962c4eb by Calen Pennington

Better simulate a request happening in the LMS in FieldOverride performance tests

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