Commit 5962c4eb by Calen Pennington

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

parent 7da8eb1f
......@@ -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)
# We clear the request cache to simulate a new request in the LMS.
RequestCache.clear_request_cache()
queries, reads = self.TEST_DATA[test_type][dataset_index]
self.instrument_course_progress_render(dataset_index, queries, reads)
with self.assertNumQueries(queries):
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
@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
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__ = True
TEST_DATA = {
'no_overrides': [
(24, 4), (132, 19), (592, 84)
],
'ccx': [
(24, 4), (132, 19), (592, 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