Commit 853bfe7a by Calen Pennington

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]
parent 18e16100
......@@ -4,7 +4,7 @@ Tests for the force_publish management command
import mock
from django.core.management import call_command, CommandError
from xmodule.modulestore import ModuleStoreEnum
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 contentstore.management.commands.force_publish import Command
from contentstore.management.commands.utils import get_course_versions
......@@ -62,7 +62,19 @@ class TestForcePublish(SharedModuleStoreTestCase):
with self.assertRaisesRegexp(CommandError, errstring):
call_command('force_publish', unicode(course.id))
@SharedModuleStoreTestCase.modifies_courseware
class TestForcePublishModifications(ModuleStoreTestCase):
"""
Tests for the force_publish management command that modify the courseware
during the test.
"""
def setUp(self):
super(TestForcePublishModifications, self).setUp()
self.course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
self.test_user_id = ModuleStoreEnum.UserID.test
self.command = Command()
def test_force_publish(self):
"""
Test 'force_publish' command
......
......@@ -88,8 +88,9 @@ class ContentStoreTestCase(ModuleStoreTestCase):
class AuthTestCase(ContentStoreTestCase):
"""Check that various permissions-related things work"""
CREATE_USER = False
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
def setUp(self):
super(AuthTestCase, self).setUp()
......
......@@ -46,6 +46,8 @@ MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {})
class EmbargoCheckAccessApiTests(ModuleStoreTestCase):
"""Test the embargo API calls to determine whether a user has access. """
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
def setUp(self):
super(EmbargoCheckAccessApiTests, self).setUp()
self.course = CourseFactory.create()
......@@ -239,16 +241,13 @@ class EmbargoMessageUrlApiTests(UrlResetMixin, ModuleStoreTestCase):
"""Test the embargo API calls for retrieving the blocking message URLs. """
URLCONF_MODULES = ['embargo']
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
@patch.dict(settings.FEATURES, {'EMBARGO': True})
def setUp(self):
super(EmbargoMessageUrlApiTests, self).setUp()
self.course = CourseFactory.create()
def tearDown(self):
super(EmbargoMessageUrlApiTests, self).tearDown()
cache.clear()
@ddt.data(
('enrollment', '/embargo/blocked-message/enrollment/embargo/'),
('courseware', '/embargo/blocked-message/courseware/embargo/')
......
......@@ -8,9 +8,14 @@ from embargo.models import (
Country, CountryAccessRule, CourseAccessRuleHistory
)
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
class EmbargoModelsTest(TestCase):
class EmbargoModelsTest(CacheIsolationTestCase):
"""Test each of the 3 models in embargo.models"""
ENABLED_CACHES = ['default']
def test_course_embargo(self):
course_id = CourseLocator('abc', '123', 'doremi')
# Test that course is not authorized by default
......@@ -101,9 +106,11 @@ class EmbargoModelsTest(TestCase):
self.assertFalse('1.2.0.0' in cblacklist)
class RestrictedCourseTest(TestCase):
class RestrictedCourseTest(CacheIsolationTestCase):
"""Test RestrictedCourse model. """
ENABLED_CACHES = ['default']
def test_unicode_values(self):
course_id = CourseLocator('abc', '123', 'doremi')
restricted_course = RestrictedCourse.objects.create(course_key=course_id)
......@@ -162,8 +169,9 @@ class CountryTest(TestCase):
self.assertEquals(unicode(country), "New Zealand (NZ)")
class CountryAccessRuleTest(TestCase):
class CountryAccessRuleTest(CacheIsolationTestCase):
"""Test CountryAccessRule model. """
ENABLED_CACHES = ['default']
def test_unicode_values(self):
course_id = CourseLocator('abc', '123', 'doremi')
......
......@@ -10,11 +10,12 @@ import ddt
from util.testing import UrlResetMixin
from embargo import messages
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@ddt.ddt
class CourseAccessMessageViewTest(UrlResetMixin, TestCase):
class CourseAccessMessageViewTest(CacheIsolationTestCase, UrlResetMixin):
"""Tests for the courseware access message view.
These end-points serve static content.
......@@ -32,6 +33,8 @@ class CourseAccessMessageViewTest(UrlResetMixin, TestCase):
"""
ENABLED_CACHES = ['default']
URLCONF_MODULES = ['embargo']
@patch.dict(settings.FEATURES, {'EMBARGO': True})
......
......@@ -15,22 +15,24 @@ from course_modes.models import CourseMode
from enrollment import api
from enrollment.errors import EnrollmentApiLoadError, EnrollmentNotFoundError, CourseModeNotFoundError
from enrollment.tests import fake_data_api
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
@ddt.ddt
@override_settings(ENROLLMENT_DATA_API="enrollment.tests.fake_data_api")
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class EnrollmentTest(TestCase):
class EnrollmentTest(CacheIsolationTestCase):
"""
Test student enrollment, especially with different course modes.
"""
USERNAME = "Bob"
COURSE_ID = "some/great/course"
ENABLED_CACHES = ['default']
def setUp(self):
super(EnrollmentTest, self).setUp()
fake_data_api.reset()
cache.clear()
@ddt.data(
# Default (no course modes in the database)
......
......@@ -141,6 +141,8 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase):
OTHER_USERNAME = "Jane"
OTHER_EMAIL = "jane@example.com"
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
def setUp(self):
""" Create a course and user, then log in. """
super(EnrollmentTest, self).setUp()
......
......@@ -23,11 +23,12 @@ from mock import patch
from nose.plugins.attrib import attr
from urllib import urlencode
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from student.views import create_account, change_enrollment
from student.models import UserProfile, CourseEnrollment
from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore import ModuleStoreEnum
......@@ -76,11 +77,14 @@ def gen_all_identities():
@attr('shard_3')
@ddt
@override_settings(SESSION_ENGINE='django.contrib.sessions.backends.cache')
class ShibSPTest(SharedModuleStoreTestCase):
class ShibSPTest(CacheIsolationTestCase):
"""
Tests for the Shibboleth SP, which communicates via request.META
(Apache environment variables set by mod_shib)
"""
ENABLED_CACHES = ['default']
request_factory = RequestFactory()
def setUp(self):
......@@ -377,8 +381,23 @@ class ShibSPTest(SharedModuleStoreTestCase):
self.assertEqual(profile.name, request2.session['ExternalAuthMap'].external_name)
self.assertEqual(profile.name, identity.get('displayName').decode('utf-8'))
@ddt
@override_settings(SESSION_ENGINE='django.contrib.sessions.backends.cache')
class ShibSPTestModifiedCourseware(ModuleStoreTestCase):
"""
Tests for the Shibboleth SP which modify the courseware
"""
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
request_factory = RequestFactory()
def setUp(self):
super(ShibSPTestModifiedCourseware, self).setUp()
self.test_user_id = ModuleStoreEnum.UserID.test
@unittest.skipUnless(settings.FEATURES.get('AUTH_USE_SHIB'), "AUTH_USE_SHIB not set")
@SharedModuleStoreTestCase.modifies_courseware
@data(None, "", "shib:https://idp.stanford.edu/")
def test_course_specific_login_and_reg(self, domain):
"""
......@@ -457,7 +476,6 @@ class ShibSPTest(SharedModuleStoreTestCase):
'&enrollment_action=enroll')
@unittest.skipUnless(settings.FEATURES.get('AUTH_USE_SHIB'), "AUTH_USE_SHIB not set")
@SharedModuleStoreTestCase.modifies_courseware
def test_enrollment_limit_by_domain(self):
"""
Tests that the enrollmentDomain setting is properly limiting enrollment to those who have
......@@ -525,7 +543,6 @@ class ShibSPTest(SharedModuleStoreTestCase):
self.assertFalse(CourseEnrollment.is_enrolled(student, course.id))
@unittest.skipUnless(settings.FEATURES.get('AUTH_USE_SHIB'), "AUTH_USE_SHIB not set")
@SharedModuleStoreTestCase.modifies_courseware
def test_shib_login_enrollment(self):
"""
A functionality test that a student with an existing shib login
......
......@@ -17,6 +17,7 @@ from mock import patch
from social.apps.django_app.default.models import UserSocialAuth
from external_auth.models import ExternalAuthMap
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from student.tests.factories import UserFactory, RegistrationFactory, UserProfileFactory
from student.views import login_oauth_token
from third_party_auth.tests.utils import (
......@@ -28,11 +29,13 @@ from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
class LoginTest(TestCase):
class LoginTest(CacheIsolationTestCase):
'''
Test student.views.login_user() view
'''
ENABLED_CACHES = ['default']
def setUp(self):
super(LoginTest, self).setUp()
# Create one user and save it to the database
......
......@@ -158,7 +158,7 @@ class RegisterFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, SharedModuleStore
"""Test rendering of the registration form. """
URLCONF_MODULES = ['lms.urls']
@classmethod
def setUpClass(cls):
super(RegisterFormTest, cls).setUpClass()
......
......@@ -19,6 +19,7 @@ from django.utils.http import urlsafe_base64_encode, base36_to_int, int_to_base3
from mock import Mock, patch
import ddt
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from student.views import password_reset, password_reset_confirm_wrapper, SETTING_CHANGE_INITIATED
from student.tests.factories import UserFactory
from student.tests.test_email import mock_render_to_string
......@@ -28,11 +29,13 @@ from .test_microsite import fake_microsite_get_value
@ddt.ddt
class ResetPasswordTests(EventTestMixin, TestCase):
class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
""" Tests that clicking reset password sends email, and doesn't activate the user
"""
request_factory = RequestFactory()
ENABLED_CACHES = ['default']
def setUp(self):
super(ResetPasswordTests, self).setUp('student.views.tracker')
self.user = UserFactory.create()
......
......@@ -7,14 +7,17 @@ from django.test import TestCase
from student.models import UserProfile
from student.tests.factories import UserFactory
from django.core.cache import cache
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
@ddt.ddt
class UserProfilePropertiesTest(TestCase):
class UserProfilePropertiesTest(CacheIsolationTestCase):
"""Unit tests for age, gender_display, and level_of_education_display properties ."""
password = "test"
ENABLED_CACHES = ['default']
def setUp(self):
super(UserProfilePropertiesTest, self).setUp()
self.user = UserFactory.create(password=self.password)
......
......@@ -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',
......@@ -4018,6 +3997,114 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
@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):
"""
Test data dumps for issued certificates.
......
......@@ -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',
......
......@@ -40,6 +40,8 @@ class BookmarksTestsBase(ModuleStoreTestCase):
STORE_TYPE = ModuleStoreEnum.Type.mongo
TEST_PASSWORD = 'test'
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
def setUp(self):
super(BookmarksTestsBase, self).setUp()
......
......@@ -16,6 +16,8 @@ class CourseStructureApiTests(ModuleStoreTestCase):
"""
MOCK_CACHE = "openedx.core.djangoapps.content.course_structures.api.v0.api.cache"
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
def setUp(self):
"""
Test setup
......
......@@ -16,16 +16,20 @@ from openedx.core.djangoapps.credentials.utils import (
)
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from student.tests.factories import UserFactory
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@attr('shard_2')
class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin, CredentialsDataMixin,
ProgramsDataMixin, TestCase):
ProgramsDataMixin, CacheIsolationTestCase):
""" Tests covering the retrieval of user credentials from the Credentials
service.
"""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestCredentialsRetrieval, self).setUp()
......
......@@ -55,6 +55,8 @@ class CreditApiTestBase(ModuleStoreTestCase):
Base class for test cases of the credit API.
"""
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
PROVIDER_ID = "hogwarts"
PROVIDER_NAME = "Hogwarts School of Witchcraft and Wizardry"
PROVIDER_URL = "https://credit.example.com/request"
......
......@@ -31,6 +31,7 @@ class ReverificationPartitionTest(ModuleStoreTestCase):
SUBMITTED = "submitted"
APPROVED = "approved"
DENIED = "denied"
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
def setUp(self):
super(ReverificationPartitionTest, self).setUp()
......
......@@ -17,6 +17,7 @@ from openedx.core.djangoapps.programs import utils
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests import factories
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from student.tests.factories import UserFactory, CourseEnrollmentFactory
......@@ -26,8 +27,11 @@ UTILS_MODULE = 'openedx.core.djangoapps.programs.utils'
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@attr('shard_2')
class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin,
CredentialsApiConfigMixin, TestCase):
CredentialsApiConfigMixin, CacheIsolationTestCase):
"""Tests covering the retrieval of programs from the Programs service."""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestProgramRetrieval, self).setUp()
......
......@@ -25,6 +25,7 @@ from student.tests.factories import UserFactory
from student.models import UserProfile, LanguageProficiency, PendingEmailChange
from openedx.core.djangoapps.user_api.accounts import ACCOUNT_VISIBILITY_PREF_KEY
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from .. import PRIVATE_VISIBILITY, ALL_USERS_VISIBILITY
TEST_PROFILE_IMAGE_UPLOADED_AT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=UTC)
......@@ -121,10 +122,13 @@ class UserAPITestCase(APITestCase):
clear=True
)
@attr('shard_2')
class TestAccountAPI(UserAPITestCase):
class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase):
"""
Unit tests for the Account API.
"""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestAccountAPI, self).setUp()
......@@ -244,7 +248,7 @@ class TestAccountAPI(UserAPITestCase):
"""
self.different_client.login(username=self.different_user.username, password=self.test_password)
self.create_mock_profile(self.user)
with self.assertNumQueries(11):
with self.assertNumQueries(14):
response = self.send_get(self.different_client)
self._verify_full_shareable_account_response(response, account_privacy=ALL_USERS_VISIBILITY)
......@@ -259,7 +263,7 @@ class TestAccountAPI(UserAPITestCase):
"""
self.different_client.login(username=self.different_user.username, password=self.test_password)
self.create_mock_profile(self.user)
with self.assertNumQueries(11):
with self.assertNumQueries(14):
response = self.send_get(self.different_client)
self._verify_private_account_response(response, account_privacy=PRIVATE_VISIBILITY)
......@@ -307,11 +311,11 @@ class TestAccountAPI(UserAPITestCase):
Test that a client (logged in) can get her own account information (using default legacy profile information,
as created by the test UserFactory).
"""
def verify_get_own_information():
def verify_get_own_information(queries):
"""
Internal helper to perform the actual assertions
"""
with self.assertNumQueries(9):
with self.assertNumQueries(queries):
response = self.send_get(self.client)
data = response.data
self.assertEqual(17, len(data))
......@@ -333,12 +337,12 @@ class TestAccountAPI(UserAPITestCase):
self.assertEqual(False, data["accomplishments_shared"])
self.client.login(username=self.user.username, password=self.test_password)
verify_get_own_information()
verify_get_own_information(12)
# Now make sure that the user can get the same information, even if not active
self.user.is_active = False
self.user.save()
verify_get_own_information()
verify_get_own_information(9)
def test_get_account_empty_string(self):
"""
......@@ -352,7 +356,7 @@ class TestAccountAPI(UserAPITestCase):
legacy_profile.save()
self.client.login(username=self.user.username, password=self.test_password)
with self.assertNumQueries(9):
with self.assertNumQueries(12):
response = self.send_get(self.client)
for empty_field in ("level_of_education", "gender", "country", "bio"):
self.assertIsNone(response.data[empty_field])
......
......@@ -20,6 +20,7 @@ from social.apps.django_app.default.models import UserSocialAuth
from django_comment_common import models
from openedx.core.lib.api.test_utils import ApiTestCase, TEST_API_KEY
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from student.tests.factories import UserFactory
from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin
from third_party_auth.tests.utils import (
......@@ -334,12 +335,14 @@ class UserViewSetTest(UserApiTestCase):
)
class UserPreferenceViewSetTest(UserApiTestCase):
class UserPreferenceViewSetTest(CacheIsolationTestCase, UserApiTestCase):
"""
Test cases covering the User Preference DRF view class and its various behaviors
"""
LIST_URI = USER_PREFERENCE_LIST_URI
ENABLED_CACHES = ['default']
def setUp(self):
super(UserPreferenceViewSetTest, self).setUp()
self.detail_uri = self.get_uri_for_pref(self.prefs[0])
......@@ -1725,12 +1728,16 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase):
@httpretty.activate
@ddt.ddt
class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin):
class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTestCase):
"""
Tests for the User API registration endpoint with 3rd party authentication.
"""
CREATE_USER = False
ENABLED_CACHES = ['default']
__test__ = False
def setUp(self):
super(ThirdPartyRegistrationTestMixin, self).setUp()
self.url = reverse('user_api_registration')
......@@ -1847,6 +1854,8 @@ class TestFacebookRegistrationView(
ThirdPartyRegistrationTestMixin, ThirdPartyOAuthTestMixinFacebook, TransactionTestCase
):
"""Tests the User API registration endpoint with Facebook authentication."""
__test__ = True
def test_social_auth_exception(self):
"""
According to the do_auth method in social.backends.facebook.py,
......@@ -1863,6 +1872,8 @@ class TestGoogleRegistrationView(
ThirdPartyRegistrationTestMixin, ThirdPartyOAuthTestMixinGoogle, TransactionTestCase
):
"""Tests the User API registration endpoint with Google authentication."""
__test__ = True
pass
......
from django.core.cache import caches
from django.test import TestCase, override_settings
from django.conf import settings
from django.contrib import sites
from request_cache.middleware import RequestCache
class CacheIsolationMixin(object):
"""
This class can be used to enable specific django caches for
specific the TestCase that it's mixed into.
Usage:
Use the ENABLED_CACHES to list the names of caches that should
be enabled in the context of this TestCase. These caches will
use a loc_mem_cache with the default settings.
Set the class variable CACHES to explicitly specify the cache settings
that should be overridden. This class will insert those values into
django.conf.settings, and will reset all named caches before each
test.
If both CACHES and ENABLED_CACHES are not None, raises an error.
"""
CACHES = None
ENABLED_CACHES = None
__settings_override = None
@classmethod
def start_cache_isolation(cls):
"""
Start cache isolation by overriding the settings.CACHES and
flushing the cache.
"""
cache_settings = None
if cls.CACHES is not None and cls.ENABLED_CACHES is not None:
raise Exception(
"Use either CACHES or ENABLED_CACHES, but not both"
)
if cls.CACHES is not None:
cache_settings = cls.CACHES
elif cls.ENABLED_CACHES is not None:
cache_settings = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
cache_settings.update({
cache_name: {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': cache_name,
'KEY_FUNCTION': 'util.memcache.safe_key',
} for cache_name in cls.ENABLED_CACHES
})
if cache_settings is None:
return
cls.__settings_override = override_settings(CACHES=cache_settings)
cls.__settings_override.__enter__()
# Start with empty caches
cls.clear_caches()
@classmethod
def end_cache_isolation(cls):
"""
End cache isolation by flushing the cache and then returning
settings.CACHES to its original state.
"""
# Make sure that cache contents don't leak out after the isolation is ended
cls.clear_caches()
if cls.__settings_override is not None:
cls.__settings_override.__exit__(None, None, None)
cls.__settings_override = None
@classmethod
def clear_caches(cls):
"""
Clear all of the caches defined in settings.CACHES.
"""
# N.B. As of 2016-04-20, Django won't return any caches
# from django.core.cache.caches.all() that haven't been
# accessed using caches[name] previously, so we loop
# over our list of overridden caches, instead.
for cache in settings.CACHES:
caches[cache].clear()
# The sites framework caches in a module-level dictionary.
# Clear that.
sites.models.SITE_CACHE.clear()
RequestCache.clear_request_cache()
class CacheIsolationTestCase(CacheIsolationMixin, TestCase):
"""
A TestCase that isolates caches (as described in
:py:class:`CacheIsolationMixin`) at class setup, and flushes the cache
between every test.
"""
@classmethod
def setUpClass(cls):
super(CacheIsolationTestCase, cls).setUpClass()
cls.start_cache_isolation()
@classmethod
def tearDownClass(cls):
cls.end_cache_isolation()
super(CacheIsolationTestCase, cls).tearDownClass()
def setUp(self):
super(CacheIsolationTestCase, self).setUp()
self.clear_caches()
self.addCleanup(self.clear_caches)
......@@ -15,6 +15,7 @@ from openedx.core.djangoapps.credentials.models import CredentialsApiConfig
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin, CredentialsDataMixin
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from openedx.core.lib.edx_api_utils import get_edx_api_data
from student.tests.factories import UserFactory
......@@ -24,8 +25,11 @@ LOGGER_NAME = 'openedx.core.lib.edx_api_utils'
@attr('shard_2')
class TestApiDataRetrieval(CredentialsApiConfigMixin, CredentialsDataMixin, ProgramsApiConfigMixin, ProgramsDataMixin,
TestCase):
CacheIsolationTestCase):
"""Test utility for API data retrieval."""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestApiDataRetrieval, self).setUp()
ClientFactory(name=CredentialsApiConfig.OAUTH2_CLIENT_NAME, client_type=CONFIDENTIAL)
......
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