Add a TestCase mixin for enabling caches in tests
By default, disable all caching in tests, to preserve test independence. In order to enable caching, inherit from CacheSetupMixin, and specify which cache configuration is needed. [EV-32]
This commit is contained in:
@@ -44,6 +44,8 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
Test that errors from sending email are handled properly.
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(TestEmailErrors, self).setUp()
|
||||
course_title = u"ẗëṡẗ title イ乇丂イ ᄊ乇丂丂ムg乇 キo尺 ムレレ тэѕт мэѕѕаБэ"
|
||||
|
||||
@@ -52,6 +52,8 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
|
||||
# TEST_DATA must be overridden by subclasses
|
||||
TEST_DATA = None
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Create a test client, course, and user.
|
||||
|
||||
@@ -68,6 +68,8 @@ from lms.djangoapps.ccx.tests.utils import (
|
||||
from lms.djangoapps.ccx.utils import is_email
|
||||
from lms.djangoapps.ccx.views import get_date
|
||||
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
def intercept_renderer(path, context):
|
||||
"""
|
||||
@@ -184,10 +186,6 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
|
||||
Tests for Custom Courses views.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCoachDashboard, cls).setUpClass()
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up tests
|
||||
@@ -206,31 +204,6 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
|
||||
allow_access(self.course, instructor, 'instructor')
|
||||
self.assertTrue(CourseInstructorRole(self.course.id).has_user(instructor))
|
||||
|
||||
def assert_elements_in_schedule(self, url, n_chapters=2, n_sequentials=4, n_verticals=8):
|
||||
"""
|
||||
Helper function to count visible elements in the schedule
|
||||
"""
|
||||
response = self.client.get(url)
|
||||
# the schedule contains chapters
|
||||
chapters = json.loads(response.mako_context['schedule']) # pylint: disable=no-member
|
||||
sequentials = flatten([chapter.get('children', []) for chapter in chapters])
|
||||
verticals = flatten([sequential.get('children', []) for sequential in sequentials])
|
||||
# check that the numbers of nodes at different level are the expected ones
|
||||
self.assertEqual(n_chapters, len(chapters))
|
||||
self.assertEqual(n_sequentials, len(sequentials))
|
||||
self.assertEqual(n_verticals, len(verticals))
|
||||
# extract the locations of all the nodes
|
||||
all_elements = chapters + sequentials + verticals
|
||||
return [elem['location'] for elem in all_elements if 'location' in elem]
|
||||
|
||||
def hide_node(self, node):
|
||||
"""
|
||||
Helper function to set the node `visible_to_staff_only` property
|
||||
to True and save the change
|
||||
"""
|
||||
node.visible_to_staff_only = True
|
||||
self.mstore.update_item(node, self.coach.id)
|
||||
|
||||
def test_not_a_coach(self):
|
||||
"""
|
||||
User is not a coach, should get Forbidden response.
|
||||
@@ -352,43 +325,6 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
|
||||
self.assertEqual(get_date(ccx, unit, 'start', parent_node=subsection), self.mooc_start)
|
||||
self.assertEqual(get_date(ccx, unit, 'due', parent_node=subsection), self.mooc_due)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
@patch('ccx.views.render_to_response', intercept_renderer)
|
||||
@patch('ccx.views.TODAY')
|
||||
def test_get_ccx_schedule(self, today):
|
||||
"""
|
||||
Gets CCX schedule and checks number of blocks in it.
|
||||
Hides nodes at a different depth and checks that these nodes
|
||||
are not in the schedule.
|
||||
"""
|
||||
today.return_value = datetime.datetime(2014, 11, 25, tzinfo=pytz.UTC)
|
||||
self.make_coach()
|
||||
ccx = self.make_ccx()
|
||||
url = reverse(
|
||||
'ccx_coach_dashboard',
|
||||
kwargs={
|
||||
'course_id': CCXLocator.from_course_locator(
|
||||
self.course.id, ccx.id)
|
||||
}
|
||||
)
|
||||
# all the elements are visible
|
||||
self.assert_elements_in_schedule(url)
|
||||
# hide a vertical
|
||||
vertical = self.verticals[0]
|
||||
self.hide_node(vertical)
|
||||
locations = self.assert_elements_in_schedule(url, n_verticals=7)
|
||||
self.assertNotIn(unicode(vertical.location), locations)
|
||||
# hide a sequential
|
||||
sequential = self.sequentials[0]
|
||||
self.hide_node(sequential)
|
||||
locations = self.assert_elements_in_schedule(url, n_sequentials=3, n_verticals=6)
|
||||
self.assertNotIn(unicode(sequential.location), locations)
|
||||
# hide a chapter
|
||||
chapter = self.chapters[0]
|
||||
self.hide_node(chapter)
|
||||
locations = self.assert_elements_in_schedule(url, n_chapters=1, n_sequentials=2, n_verticals=4)
|
||||
self.assertNotIn(unicode(chapter.location), locations)
|
||||
|
||||
@patch('ccx.views.render_to_response', intercept_renderer)
|
||||
@patch('ccx.views.TODAY')
|
||||
def test_edit_schedule(self, today):
|
||||
@@ -842,6 +778,134 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
|
||||
)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class TestCoachDashboardSchedule(CcxTestCase, LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
"""
|
||||
Tests of the CCX Coach Dashboard which need to modify the course content.
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_inheritance_cache', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(TestCoachDashboardSchedule, self).setUp()
|
||||
self.course = course = CourseFactory.create()
|
||||
|
||||
# Create a course outline
|
||||
self.mooc_start = start = datetime.datetime(
|
||||
2010, 5, 12, 2, 42, tzinfo=pytz.UTC
|
||||
)
|
||||
self.mooc_due = due = datetime.datetime(
|
||||
2010, 7, 7, 0, 0, tzinfo=pytz.UTC
|
||||
)
|
||||
|
||||
self.chapters = [
|
||||
ItemFactory.create(start=start, parent=course) for _ in xrange(2)
|
||||
]
|
||||
self.sequentials = flatten([
|
||||
[
|
||||
ItemFactory.create(parent=chapter) for _ in xrange(2)
|
||||
] for chapter in self.chapters
|
||||
])
|
||||
self.verticals = flatten([
|
||||
[
|
||||
ItemFactory.create(
|
||||
start=start, due=due, parent=sequential, graded=True, format='Homework', category=u'vertical'
|
||||
) for _ in xrange(2)
|
||||
] for sequential in self.sequentials
|
||||
])
|
||||
|
||||
# Trying to wrap the whole thing in a bulk operation fails because it
|
||||
# doesn't find the parents. But we can at least wrap this part...
|
||||
with self.store.bulk_operations(course.id, emit_signals=False):
|
||||
blocks = flatten([ # pylint: disable=unused-variable
|
||||
[
|
||||
ItemFactory.create(parent=vertical) for _ in xrange(2)
|
||||
] for vertical in self.verticals
|
||||
])
|
||||
|
||||
# Create instructor account
|
||||
self.coach = UserFactory.create()
|
||||
# create an instance of modulestore
|
||||
self.mstore = modulestore()
|
||||
|
||||
# Login with the instructor account
|
||||
self.client.login(username=self.coach.username, password="test")
|
||||
|
||||
# adding staff to master course.
|
||||
staff = UserFactory()
|
||||
allow_access(self.course, staff, 'staff')
|
||||
self.assertTrue(CourseStaffRole(self.course.id).has_user(staff))
|
||||
|
||||
# adding instructor to master course.
|
||||
instructor = UserFactory()
|
||||
allow_access(self.course, instructor, 'instructor')
|
||||
self.assertTrue(CourseInstructorRole(self.course.id).has_user(instructor))
|
||||
|
||||
self.assertTrue(modulestore().has_course(self.course.id))
|
||||
|
||||
def assert_elements_in_schedule(self, url, n_chapters=2, n_sequentials=4, n_verticals=8):
|
||||
"""
|
||||
Helper function to count visible elements in the schedule
|
||||
"""
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# the schedule contains chapters
|
||||
chapters = json.loads(response.mako_context['schedule']) # pylint: disable=no-member
|
||||
sequentials = flatten([chapter.get('children', []) for chapter in chapters])
|
||||
verticals = flatten([sequential.get('children', []) for sequential in sequentials])
|
||||
# check that the numbers of nodes at different level are the expected ones
|
||||
self.assertEqual(n_chapters, len(chapters))
|
||||
self.assertEqual(n_sequentials, len(sequentials))
|
||||
self.assertEqual(n_verticals, len(verticals))
|
||||
# extract the locations of all the nodes
|
||||
all_elements = chapters + sequentials + verticals
|
||||
return [elem['location'] for elem in all_elements if 'location' in elem]
|
||||
|
||||
def hide_node(self, node):
|
||||
"""
|
||||
Helper function to set the node `visible_to_staff_only` property
|
||||
to True and save the change
|
||||
"""
|
||||
node.visible_to_staff_only = True
|
||||
self.mstore.update_item(node, self.coach.id)
|
||||
|
||||
@patch('ccx.views.render_to_response', intercept_renderer)
|
||||
@patch('ccx.views.TODAY')
|
||||
def test_get_ccx_schedule(self, today):
|
||||
"""
|
||||
Gets CCX schedule and checks number of blocks in it.
|
||||
Hides nodes at a different depth and checks that these nodes
|
||||
are not in the schedule.
|
||||
"""
|
||||
today.return_value = datetime.datetime(2014, 11, 25, tzinfo=pytz.UTC)
|
||||
self.make_coach()
|
||||
ccx = self.make_ccx()
|
||||
url = reverse(
|
||||
'ccx_coach_dashboard',
|
||||
kwargs={
|
||||
'course_id': CCXLocator.from_course_locator(
|
||||
self.course.id, ccx.id)
|
||||
}
|
||||
)
|
||||
# all the elements are visible
|
||||
self.assert_elements_in_schedule(url)
|
||||
# hide a vertical
|
||||
vertical = self.verticals[0]
|
||||
self.hide_node(vertical)
|
||||
locations = self.assert_elements_in_schedule(url, n_verticals=7)
|
||||
self.assertNotIn(unicode(vertical.location), locations)
|
||||
# hide a sequential
|
||||
sequential = self.sequentials[0]
|
||||
self.hide_node(sequential)
|
||||
locations = self.assert_elements_in_schedule(url, n_sequentials=3, n_verticals=6)
|
||||
self.assertNotIn(unicode(sequential.location), locations)
|
||||
# hide a chapter
|
||||
chapter = self.chapters[0]
|
||||
self.hide_node(chapter)
|
||||
locations = self.assert_elements_in_schedule(url, n_chapters=1, n_sequentials=2, n_verticals=4)
|
||||
self.assertNotIn(unicode(chapter.location), locations)
|
||||
|
||||
|
||||
GET_CHILDREN = XModuleMixin.get_children
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ from django.test.client import Client
|
||||
from django.test.utils import override_settings
|
||||
from nose.plugins.attrib import attr
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
|
||||
from certificates.api import get_certificate_url
|
||||
from certificates.models import (
|
||||
@@ -38,7 +39,7 @@ FEATURES_WITH_CUSTOM_CERTS_ENABLED.update(FEATURES_WITH_CERTS_ENABLED)
|
||||
|
||||
@attr('shard_1')
|
||||
@ddt.ddt
|
||||
class UpdateExampleCertificateViewTest(TestCase):
|
||||
class UpdateExampleCertificateViewTest(CacheIsolationTestCase):
|
||||
"""Tests for the XQueue callback that updates example certificates. """
|
||||
|
||||
COURSE_KEY = CourseLocator(org='test', course='test', run='test')
|
||||
@@ -48,6 +49,8 @@ class UpdateExampleCertificateViewTest(TestCase):
|
||||
DOWNLOAD_URL = 'http://www.example.com'
|
||||
ERROR_REASON = 'Kaboom!'
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
def setUp(self):
|
||||
super(UpdateExampleCertificateViewTest, self).setUp()
|
||||
self.cert_set = ExampleCertificateSet.objects.create(course_key=self.COURSE_KEY)
|
||||
|
||||
@@ -144,13 +144,24 @@ class TestGetCourseList(CourseListTestMixin, SharedModuleStoreTestCase):
|
||||
with self.assertRaises(PermissionDenied):
|
||||
self._make_api_call(anonuser, self.staff_user)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
|
||||
class TestGetCourseListMultipleCourses(CourseListTestMixin, ModuleStoreTestCase):
|
||||
"""
|
||||
Test the behavior of the `list_courses` api function (with tests that
|
||||
modify the courseware).
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetCourseListMultipleCourses, self).setUp()
|
||||
self.course = self.create_course()
|
||||
self.staff_user = self.create_user("staff", is_staff=True)
|
||||
self.honor_user = self.create_user("honor", is_staff=False)
|
||||
|
||||
def test_multiple_courses(self):
|
||||
self.create_course(course='second')
|
||||
courses = self._make_api_call(self.honor_user, self.honor_user)
|
||||
self.assertEqual(len(courses), 2)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
def test_filter_by_org(self):
|
||||
"""Verify that courses are filtered by the provided org key."""
|
||||
# Create a second course to be filtered out of queries.
|
||||
@@ -173,7 +184,6 @@ class TestGetCourseList(CourseListTestMixin, SharedModuleStoreTestCase):
|
||||
all(course.org == self.course.org for course in filtered_courses)
|
||||
)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
def test_filter(self):
|
||||
# Create a second course to be filtered out of queries.
|
||||
alternate_course = self.create_course(course='mobile', mobile_available=True)
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.core.urlresolvers import reverse
|
||||
from django.test import RequestFactory
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase, ModuleStoreTestCase
|
||||
from .mixins import CourseApiFactoryMixin, TEST_PASSWORD
|
||||
from ..views import CourseDetailView
|
||||
|
||||
@@ -91,7 +91,24 @@ class CourseListViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase):
|
||||
response_to_missing_username = self.verify_response(expected_status_code=200)
|
||||
self.assertIsNotNone(response_to_missing_username.data) # pylint: disable=no-member
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
def test_not_logged_in(self):
|
||||
self.client.logout()
|
||||
self.verify_response()
|
||||
|
||||
|
||||
class CourseListViewTestCaseMultipleCourses(CourseApiTestViewMixin, ModuleStoreTestCase):
|
||||
"""
|
||||
Test responses returned from CourseListView (with tests that modify the
|
||||
courseware).
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(CourseListViewTestCaseMultipleCourses, self).setUp()
|
||||
self.course = self.create_course()
|
||||
self.url = reverse('course-list')
|
||||
self.staff_user = self.create_user(username='staff', is_staff=True)
|
||||
self.honor_user = self.create_user(username='honor', is_staff=False)
|
||||
|
||||
def test_filter_by_org(self):
|
||||
"""Verify that CourseOverviews are filtered by the provided org key."""
|
||||
self.setup_user(self.staff_user)
|
||||
@@ -116,7 +133,6 @@ class CourseListViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase):
|
||||
all(course['org'] == self.course.org for course in filtered_response.data['results']) # pylint: disable=no-member
|
||||
)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
def test_filter(self):
|
||||
self.setup_user(self.staff_user)
|
||||
|
||||
@@ -139,10 +155,6 @@ class CourseListViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase):
|
||||
"testing course_api.views.CourseListView with filter_={}".format(filter_),
|
||||
)
|
||||
|
||||
def test_not_logged_in(self):
|
||||
self.client.logout()
|
||||
self.verify_response()
|
||||
|
||||
|
||||
class CourseDetailViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
@@ -15,6 +15,8 @@ class TestGenerateCourseBlocks(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests generate course blocks management command.
|
||||
"""
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Create courses in modulestore.
|
||||
|
||||
@@ -15,6 +15,7 @@ class CourseBlocksSignalTest(EnableTransformerRegistryMixin, ModuleStoreTestCase
|
||||
"""
|
||||
Tests for the Course Blocks signal
|
||||
"""
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(CourseBlocksSignalTest, self).setUp()
|
||||
|
||||
@@ -36,6 +36,8 @@ class CourseStructureTestCase(TransformerRegistryTestMixin, ModuleStoreTestCase)
|
||||
"""
|
||||
Helper for test cases that need to build course structures.
|
||||
"""
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Create users.
|
||||
|
||||
@@ -36,6 +36,7 @@ class CourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
"""
|
||||
Tests for the Course Info page
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CourseInfoTestCase, cls).setUpClass()
|
||||
@@ -263,6 +264,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
|
||||
"""
|
||||
Tests for the info page of self-paced courses.
|
||||
"""
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -151,6 +151,8 @@ class TestMaxScoresCache(SharedModuleStoreTestCase):
|
||||
Tests for the MaxScoresCache
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMaxScoresCache, cls).setUpClass()
|
||||
|
||||
@@ -127,6 +127,8 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase, Probl
|
||||
COURSE_SLUG = "100"
|
||||
COURSE_NAME = "test_course"
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(TestSubmittingProblems, self).setUp()
|
||||
|
||||
|
||||
@@ -970,6 +970,8 @@ class ProgressPageTests(ModuleStoreTestCase):
|
||||
Tests that verify that the progress page works correctly.
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_modulestore_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(ProgressPageTests, self).setUp()
|
||||
self.request_factory = RequestFactory()
|
||||
|
||||
@@ -51,6 +51,8 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
TEST_BRANCH_COURSE = SlashSeparatedCourseKey('MITx', 'edx4edx_branch', 'edx4edx')
|
||||
GIT_REPO_DIR = settings.GIT_REPO_DIR
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def assertCommandFailureRegexp(self, regex, *args):
|
||||
"""
|
||||
Convenience function for testing command failures
|
||||
|
||||
@@ -10,7 +10,6 @@ from django.test.client import RequestFactory
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.management import call_command
|
||||
from django.core.urlresolvers import reverse
|
||||
from request_cache.middleware import RequestCache
|
||||
from mock import patch, ANY, Mock
|
||||
from nose.tools import assert_true, assert_equal
|
||||
from nose.plugins.attrib import attr
|
||||
@@ -24,8 +23,9 @@ from django_comment_client.tests.utils import CohortedTestCase
|
||||
from django_comment_client.tests.unicode import UnicodeTestMixin
|
||||
from django_comment_common.models import Role
|
||||
from django_comment_common.utils import seed_permissions_roles, ThreadContext
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory, CourseAccessRoleFactory
|
||||
|
||||
from lms.djangoapps.teams.tests.factories import CourseTeamFactory, CourseTeamMembershipFactory
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory, CourseAccessRoleFactory
|
||||
from util.testing import UrlResetMixin
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
|
||||
@@ -351,17 +351,12 @@ class ViewsTestCaseMixin(object):
|
||||
class ViewsQueryCountTestCase(UrlResetMixin, ModuleStoreTestCase, MockRequestSetupMixin, ViewsTestCaseMixin):
|
||||
|
||||
CREATE_USER = False
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ViewsQueryCountTestCase, self).setUp()
|
||||
|
||||
def clear_caches(self):
|
||||
"""Clears caches so that query count numbers are accurate."""
|
||||
for cache in settings.CACHES:
|
||||
caches[cache].clear()
|
||||
RequestCache.clear_request_cache()
|
||||
|
||||
def count_queries(func): # pylint: disable=no-self-argument
|
||||
"""
|
||||
Decorates test methods to count mongo and SQL calls for a
|
||||
|
||||
@@ -51,7 +51,7 @@ from student.models import (
|
||||
)
|
||||
from student.tests.factories import UserFactory, CourseModeFactory, AdminFactory
|
||||
from student.roles import CourseBetaTesterRole, CourseSalesAdminRole, CourseFinanceAdminRole, CourseInstructorRole
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase, ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.fields import Date
|
||||
|
||||
@@ -3968,27 +3968,6 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
})
|
||||
self.assertEqual(response.status_code, 400, response.content)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
def test_reset_extension_to_deleted_date(self):
|
||||
"""
|
||||
Test that we can delete a due date extension after deleting the normal
|
||||
due date, without causing an error.
|
||||
"""
|
||||
self.test_change_due_date()
|
||||
self.week1.due = None
|
||||
self.week1 = self.store.update_item(self.week1, self.user1.id)
|
||||
# Now, week1's normal due date is deleted but the extension still exists.
|
||||
url = reverse('reset_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url, {
|
||||
'student': self.user1.username,
|
||||
'url': self.week1.location.to_deprecated_string(),
|
||||
})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(
|
||||
None,
|
||||
get_extended_due(self.course, self.week1, self.user1)
|
||||
)
|
||||
|
||||
def test_show_unit_extensions(self):
|
||||
self.test_change_due_date()
|
||||
url = reverse('show_unit_extensions',
|
||||
@@ -4017,6 +3996,114 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
self.user1.profile.name, self.user1.username)})
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class TestDueDateExtensionsDeletedDate(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
def setUp(self):
|
||||
"""
|
||||
Fixtures.
|
||||
"""
|
||||
super(TestDueDateExtensionsDeletedDate, self).setUp()
|
||||
|
||||
self.course = CourseFactory.create()
|
||||
self.due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc)
|
||||
|
||||
with self.store.bulk_operations(self.course.id, emit_signals=False):
|
||||
self.week1 = ItemFactory.create(due=self.due)
|
||||
self.week2 = ItemFactory.create(due=self.due)
|
||||
self.week3 = ItemFactory.create() # No due date
|
||||
self.course.children = [
|
||||
self.week1.location.to_deprecated_string(),
|
||||
self.week2.location.to_deprecated_string(),
|
||||
self.week3.location.to_deprecated_string()
|
||||
]
|
||||
self.homework = ItemFactory.create(
|
||||
parent_location=self.week1.location,
|
||||
due=self.due
|
||||
)
|
||||
self.week1.children = [self.homework.location.to_deprecated_string()]
|
||||
|
||||
user1 = UserFactory.create()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user1.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.week1.location).save()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user1.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.week2.location).save()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user1.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.week3.location).save()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user1.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.homework.location).save()
|
||||
|
||||
user2 = UserFactory.create()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user2.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.week1.location).save()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user2.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.homework.location).save()
|
||||
|
||||
user3 = UserFactory.create()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user3.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.week1.location).save()
|
||||
StudentModule(
|
||||
state='{}',
|
||||
student_id=user3.id,
|
||||
course_id=self.course.id,
|
||||
module_state_key=self.homework.location).save()
|
||||
|
||||
self.user1 = user1
|
||||
self.user2 = user2
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
self.client.login(username=self.instructor.username, password='test')
|
||||
|
||||
def test_reset_extension_to_deleted_date(self):
|
||||
"""
|
||||
Test that we can delete a due date extension after deleting the normal
|
||||
due date, without causing an error.
|
||||
"""
|
||||
|
||||
url = reverse('change_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url, {
|
||||
'student': self.user1.username,
|
||||
'url': self.week1.location.to_deprecated_string(),
|
||||
'due_datetime': '12/30/2013 00:00'
|
||||
})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(datetime.datetime(2013, 12, 30, 0, 0, tzinfo=utc),
|
||||
get_extended_due(self.course, self.week1, self.user1))
|
||||
|
||||
self.week1.due = None
|
||||
self.week1 = self.store.update_item(self.week1, self.user1.id)
|
||||
# Now, week1's normal due date is deleted but the extension still exists.
|
||||
url = reverse('reset_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url, {
|
||||
'student': self.user1.username,
|
||||
'url': self.week1.location.to_deprecated_string(),
|
||||
})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(
|
||||
None,
|
||||
get_extended_due(self.course, self.week1, self.user1)
|
||||
)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
@@ -1683,6 +1683,9 @@ class TestCertificateGeneration(InstructorTaskModuleTestCase):
|
||||
"""
|
||||
Test certificate generation task works.
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(TestCertificateGeneration, self).setUp()
|
||||
self.initialize_course()
|
||||
|
||||
@@ -10,18 +10,21 @@ import mock
|
||||
from pytz import UTC
|
||||
from mobile_api.middleware import AppVersionUpgrade
|
||||
from mobile_api.models import AppVersionConfig
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestAppVersionUpgradeMiddleware(TestCase):
|
||||
class TestAppVersionUpgradeMiddleware(CacheIsolationTestCase):
|
||||
"""
|
||||
Tests for version based app upgrade middleware
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
def setUp(self):
|
||||
super(TestAppVersionUpgradeMiddleware, self).setUp()
|
||||
self.middleware = AppVersionUpgrade()
|
||||
self.set_app_version_config()
|
||||
cache.clear()
|
||||
|
||||
def set_app_version_config(self):
|
||||
""" Creates configuration data for platform versions """
|
||||
|
||||
@@ -1707,6 +1707,9 @@ class RegistrationCodeRedemptionCourseEnrollment(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test suite for RegistrationCodeRedemption Course Enrollments
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RegistrationCodeRedemptionCourseEnrollment, cls).setUpClass()
|
||||
|
||||
@@ -22,6 +22,7 @@ from course_modes.models import CourseMode
|
||||
from openedx.core.djangoapps.user_api.accounts.api import activate_account, create_account
|
||||
from openedx.core.djangoapps.user_api.accounts import EMAIL_MAX_LENGTH
|
||||
from openedx.core.djangolib.js_utils import dump_js_escaped_json
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
from student.tests.factories import UserFactory
|
||||
from student_account.views import account_settings_context
|
||||
from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin
|
||||
@@ -31,7 +32,7 @@ from openedx.core.djangoapps.theming.test_util import with_edx_domain_context
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class StudentAccountUpdateTest(UrlResetMixin, TestCase):
|
||||
class StudentAccountUpdateTest(CacheIsolationTestCase, UrlResetMixin):
|
||||
""" Tests for the student account views that update the user's account information. """
|
||||
|
||||
USERNAME = u"heisenberg"
|
||||
@@ -64,6 +65,8 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase):
|
||||
|
||||
URLCONF_MODULES = ['student_accounts.urls']
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
def setUp(self):
|
||||
super(StudentAccountUpdateTest, self).setUp()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class SoftwareSecureFakeViewTest(UrlResetMixin, TestCase):
|
||||
"""
|
||||
Base class to test the fake software secure view.
|
||||
"""
|
||||
|
||||
|
||||
URLCONF_MODULES = ['verify_student.urls']
|
||||
|
||||
def setUp(self, **kwargs):
|
||||
|
||||
@@ -18,6 +18,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
|
||||
from lms.djangoapps.verify_student.models import (
|
||||
SoftwareSecurePhotoVerification,
|
||||
@@ -844,11 +845,13 @@ class SkippedReverificationTest(ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
|
||||
class VerificationDeadlineTest(TestCase):
|
||||
class VerificationDeadlineTest(CacheIsolationTestCase):
|
||||
"""
|
||||
Tests for the VerificationDeadline model.
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
def test_caching(self):
|
||||
deadlines = {
|
||||
CourseKey.from_string("edX/DemoX/Fall"): datetime.now(pytz.UTC),
|
||||
|
||||
@@ -203,9 +203,7 @@ CACHES = {
|
||||
# This is the cache used for most things.
|
||||
# In staging/prod envs, the sessions also live here.
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'LOCATION': 'edx_loc_mem_cache',
|
||||
'KEY_FUNCTION': 'util.memcache.safe_key',
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
},
|
||||
|
||||
# The general cache is what you get if you use our util.cache. It's used for
|
||||
@@ -215,20 +213,13 @@ CACHES = {
|
||||
# push process.
|
||||
'general': {
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
'KEY_PREFIX': 'general',
|
||||
'VERSION': 4,
|
||||
'KEY_FUNCTION': 'util.memcache.safe_key',
|
||||
},
|
||||
|
||||
'mongo_metadata_inheritance': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'LOCATION': os.path.join(tempfile.gettempdir(), 'mongo_metadata_inheritance'),
|
||||
'TIMEOUT': 300,
|
||||
'KEY_FUNCTION': 'util.memcache.safe_key',
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
},
|
||||
'loc_cache': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'LOCATION': 'edx_location_mem_cache',
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
},
|
||||
'course_structure_cache': {
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
|
||||
Reference in New Issue
Block a user