diff --git a/common/djangoapps/util/tests/test_django_utils.py b/common/djangoapps/util/tests/test_django_utils.py new file mode 100644 index 0000000000..bd0dc846ef --- /dev/null +++ b/common/djangoapps/util/tests/test_django_utils.py @@ -0,0 +1,53 @@ +""" +THE TESTS IN THIS MODULE SHOULD BE RUN ON THE SAME PROCESS TO BE MEANINGFUL!!! + +The tests in this module look kind of goofy, but the idea is to make sure that +cache values can't leak between different TestCase classes and methods. The need +for this will go away whenever Django merges the fix to reset the caches between +tests (https://code.djangoproject.com/ticket/11505). +""" +from django.core.cache import caches + +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase + + +class CacheCheckMixin(object): + """Base mixin that does our cache check.""" + + def check_caches(self, key): + """Check that caches are empty, and add values.""" + for cache in caches.all(): + self.assertIsNone(cache.get(key)) + cache.set(key, "Not None") + + +class CacheModuleStoreTestCaseParent(ModuleStoreTestCase, CacheCheckMixin): + """Make sure that we're clearing cache values between tests.""" + + def test_cache_reset_1(self): + """Check to make sure cache is empty, and add values to it.""" + self.check_caches("mstc_cache_test_key") + + def test_cache_reset_2(self): + """Check to make sure cache is empty, and add values to it.""" + self.check_caches("mstc_cache_test_key") + + +class CacheModuleStoreTestCaseChild(CacheModuleStoreTestCaseParent): # pylint: disable=test-inherits-tests + """Make sure that we're clearing cache values between classes.""" + + +class CacheSharedModuleStoreTestCaseParent(SharedModuleStoreTestCase, CacheCheckMixin): + """Make sure that we're clearing cache values between tests.""" + + def test_cache_reset_1(self): + """Check to make sure cache is empty, and add values to it.""" + self.check_caches("smstc_cache_test_key") + + def test_cache_reset_2(self): + """Check to make sure cache is empty, and add values to it.""" + self.check_caches("smstc_cache_test_key") + + +class CacheSharedModuleStoreTestCaseChild(CacheSharedModuleStoreTestCaseParent): # pylint: disable=test-inherits-tests + """Make sure that we're clearing cache values between classes.""" diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 8d3224db2a..5ed4ce201e 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -7,6 +7,7 @@ from uuid import uuid4 from mock import patch +import django.core.cache from django.conf import settings from django.contrib.auth.models import User from django.test import TestCase @@ -215,6 +216,16 @@ TEST_DATA_SPLIT_MODULESTORE = mixed_store_config( ) +def clear_all_caches(): + """Clear all caches so that cache info doesn't leak across test cases.""" + # This will no longer be necessary when Django adds (in Django 1.10?): + # https://code.djangoproject.com/ticket/11505 + for cache in django.core.cache.caches.all(): + cache.clear() + + RequestCache().clear_request_cache() + + class SharedModuleStoreTestCase(TestCase): """ Subclass for any test case that uses a ModuleStore that can be shared @@ -268,7 +279,7 @@ class SharedModuleStoreTestCase(TestCase): @classmethod def tearDownClass(cls): drop_mongo_collections() # pylint: disable=no-value-for-parameter - RequestCache().clear_request_cache() + clear_all_caches() XMODULE_FACTORY_LOCK.disable() cls._settings_override.__exit__(None, None, None) @@ -280,6 +291,11 @@ class SharedModuleStoreTestCase(TestCase): OverrideFieldData.provider_classes = None super(SharedModuleStoreTestCase, self).setUp() + def tearDown(self): + """Reset caches.""" + clear_all_caches() + super(SharedModuleStoreTestCase, self).tearDown() + def reset(self): """ Manually run tearDownClass/setUpClass again. @@ -394,7 +410,7 @@ class ModuleStoreTestCase(TestCase): clear_existing_modulestores() self.addCleanup(drop_mongo_collections) - self.addCleanup(RequestCache().clear_request_cache) + self.addCleanup(clear_all_caches) # Enable XModuleFactories for the space of this test (and its setUp). self.addCleanup(XMODULE_FACTORY_LOCK.disable) diff --git a/lms/djangoapps/course_structure_api/v0/tests.py b/lms/djangoapps/course_structure_api/v0/tests.py index 08224e521a..726db58583 100644 --- a/lms/djangoapps/course_structure_api/v0/tests.py +++ b/lms/djangoapps/course_structure_api/v0/tests.py @@ -520,7 +520,7 @@ class CourseBlocksOrNavigationTestMixin(CourseDetailTestMixin, CourseViewTestsMi return 'course_structure_api:v0:' + self.block_navigation_view_type def test_get(self): - with check_mongo_calls(3): + with check_mongo_calls(4): response = super(CourseBlocksOrNavigationTestMixin, self).test_get() # verify root element diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 001af735a2..5914b83671 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -950,7 +950,7 @@ class ProgressPageTests(ModuleStoreTestCase): self.assertContains(resp, u"Download Your Certificate") @ddt.data( - *itertools.product(((38, 4, True), (38, 4, False)), (True, False)) + *itertools.product(((40, 4, True), (40, 4, False)), (True, False)) ) @ddt.unpack def test_query_counts(self, (sql_calls, mongo_calls, self_paced), self_paced_enabled): diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py index 1d7fbe2ca4..e50e756a05 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -1628,7 +1628,7 @@ class TestCertificateGeneration(InstructorTaskModuleTestCase): current_task.update_state = Mock() instructor_task = Mock() instructor_task.task_input = json.dumps({'students': None}) - with self.assertNumQueries(213): + with self.assertNumQueries(214): with patch('instructor_task.tasks_helper._get_current_task') as mock_current_task: mock_current_task.return_value = current_task with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_queue: diff --git a/openedx/core/djangoapps/bookmarks/tests/test_views.py b/openedx/core/djangoapps/bookmarks/tests/test_views.py index 2468422914..3583cac128 100644 --- a/openedx/core/djangoapps/bookmarks/tests/test_views.py +++ b/openedx/core/djangoapps/bookmarks/tests/test_views.py @@ -95,13 +95,11 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): if check_all_fields: query_parameters += '&fields=path,display_name' - with self.assertNumQueries(9): # 2 queries for bookmark table. - response = self.send_get( - client=self.client, - url=reverse('bookmarks'), - query_parameters=query_parameters, - ) - + response = self.send_get( + client=self.client, + url=reverse('bookmarks'), + query_parameters=query_parameters, + ) bookmarks_data = response.data['results'] self.assertEqual(len(bookmarks_data), len(bookmarks)) @@ -138,13 +136,11 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): page_size = 5 query_parameters = 'course_id={}&page_size={}'.format(urllib.quote(unicode(course.id)), page_size) - with self.assertNumQueries(9): # 2 queries for bookmark table. - response = self.send_get( - client=self.client, - url=reverse('bookmarks'), - query_parameters=query_parameters - ) - + response = self.send_get( + client=self.client, + url=reverse('bookmarks'), + query_parameters=query_parameters + ) bookmarks_data = response.data['results'] # Pagination assertions. @@ -171,15 +167,14 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): Test that requesting bookmarks with invalid data returns 0 records. """ # Invalid course id. - with self.assertNumQueries(7): # No queries for bookmark table. - response = self.send_get( - client=self.client, - url=reverse('bookmarks'), - query_parameters='course_id=invalid' - ) + response = self.send_get( + client=self.client, + url=reverse('bookmarks'), + query_parameters='course_id=invalid' + ) bookmarks_data = response.data['results'] - self.assertEqual(len(bookmarks_data), 0) + self.assertEqual(len(bookmarks_data), 0) self.assertFalse(mock_tracker.emit.called) # pylint: disable=maybe-no-member @patch('eventtracking.tracker.emit') @@ -188,12 +183,10 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): Test that requesting bookmarks returns all records for that user. """ # Without course id we would return all the bookmarks for that user. - - with self.assertNumQueries(9): # 2 queries for bookmark table. - response = self.send_get( - client=self.client, - url=reverse('bookmarks') - ) + response = self.send_get( + client=self.client, + url=reverse('bookmarks') + ) bookmarks_data = response.data['results'] self.assertEqual(len(bookmarks_data), 3) self.assert_bookmark_data_is_valid(self.other_bookmark_1, bookmarks_data[0]) @@ -214,32 +207,28 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): Test that an anonymous client (not logged in) cannot call GET or POST. """ query_parameters = 'course_id={}'.format(self.course_id) - with self.assertNumQueries(4): # No queries for bookmark table. - self.send_get( - client=self.anonymous_client, - url=reverse('bookmarks'), - query_parameters=query_parameters, - expected_status=401 - ) - - with self.assertNumQueries(4): # No queries for bookmark table. - self.send_post( - client=self.anonymous_client, - url=reverse('bookmarks'), - data={'usage_id': 'test'}, - expected_status=401 - ) + self.send_get( + client=self.anonymous_client, + url=reverse('bookmarks'), + query_parameters=query_parameters, + expected_status=401 + ) + self.send_post( + client=self.anonymous_client, + url=reverse('bookmarks'), + data={'usage_id': 'test'}, + expected_status=401 + ) def test_post_bookmark_successfully(self): """ Test that posting a bookmark successfully returns newly created data with 201 code. """ - with self.assertNumQueries(16): - response = self.send_post( - client=self.client, - url=reverse('bookmarks'), - data={'usage_id': unicode(self.vertical_3.location)} - ) + response = self.send_post( + client=self.client, + url=reverse('bookmarks'), + data={'usage_id': unicode(self.vertical_3.location)} + ) # Assert Newly created bookmark. self.assertEqual(response.data['id'], '%s,%s' % (self.user.username, unicode(self.vertical_3.location))) @@ -258,23 +247,21 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): 3) With empty request.data """ # Send usage_id with invalid format. - with self.assertNumQueries(7): # No queries for bookmark table. - response = self.send_post( - client=self.client, - url=reverse('bookmarks'), - data={'usage_id': 'invalid'}, - expected_status=400 - ) + response = self.send_post( + client=self.client, + url=reverse('bookmarks'), + data={'usage_id': 'invalid'}, + expected_status=400 + ) self.assertEqual(response.data['user_message'], u'An error has occurred. Please try again.') # Send data without usage_id. - with self.assertNumQueries(6): # No queries for bookmark table. - response = self.send_post( - client=self.client, - url=reverse('bookmarks'), - data={'course_id': 'invalid'}, - expected_status=400 - ) + response = self.send_post( + client=self.client, + url=reverse('bookmarks'), + data={'course_id': 'invalid'}, + expected_status=400 + ) self.assertEqual(response.data['user_message'], u'An error has occurred. Please try again.') self.assertEqual(response.data['developer_message'], u'Parameter usage_id not provided.') @@ -293,13 +280,12 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): """ Test that posting a bookmark for a block that does not exist returns a 400. """ - with self.assertNumQueries(7): # No queries for bookmark table. - response = self.send_post( - client=self.client, - url=reverse('bookmarks'), - data={'usage_id': 'i4x://arbi/100/html/340ef1771a094090ad260ec940d04a21'}, - expected_status=400 - ) + response = self.send_post( + client=self.client, + url=reverse('bookmarks'), + data={'usage_id': 'i4x://arbi/100/html/340ef1771a094090ad260ec940d04a21'}, + expected_status=400 + ) self.assertEqual( response.data['user_message'], u'An error has occurred. Please try again.' @@ -317,13 +303,12 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): max_bookmarks = settings.MAX_BOOKMARKS_PER_COURSE __, blocks, __ = self.create_course_with_bookmarks_count(max_bookmarks) - with self.assertNumQueries(8): # No queries for bookmark table. - response = self.send_post( - client=self.client, - url=reverse('bookmarks'), - data={'usage_id': unicode(blocks[-1].location)}, - expected_status=400 - ) + response = self.send_post( + client=self.client, + url=reverse('bookmarks'), + data={'usage_id': unicode(blocks[-1].location)}, + expected_status=400 + ) self.assertEqual( response.data['user_message'], u'You can create up to {0} bookmarks.' @@ -397,15 +382,14 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): """ Test that requesting bookmark returns data with 200 code. """ - with self.assertNumQueries(8): # 1 query for bookmark table. - response = self.send_get( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': self.user.username, 'usage_id': unicode(self.sequential_1.location)} - ), - query_parameters=query_params - ) + response = self.send_get( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': self.user.username, 'usage_id': unicode(self.sequential_1.location)} + ), + query_parameters=query_params + ) data = response.data self.assertIsNotNone(data) self.assert_bookmark_data_is_valid(self.bookmark_1, data, check_optional_fields=check_optional_fields) @@ -414,29 +398,27 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): """ Test that requesting bookmark that belongs to other user returns 404 status code. """ - with self.assertNumQueries(8): # No queries for bookmark table. - self.send_get( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': 'other', 'usage_id': unicode(self.vertical_1.location)} - ), - expected_status=404 - ) + self.send_get( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': 'other', 'usage_id': unicode(self.vertical_1.location)} + ), + expected_status=404 + ) def test_get_bookmark_that_does_not_exist(self): """ Test that requesting bookmark that does not exist returns 404 status code. """ - with self.assertNumQueries(8): # 1 query for bookmark table. - response = self.send_get( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': self.user.username, 'usage_id': 'i4x://arbi/100/html/340ef1771a0940'} - ), - expected_status=404 - ) + response = self.send_get( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': self.user.username, 'usage_id': 'i4x://arbi/100/html/340ef1771a0940'} + ), + expected_status=404 + ) self.assertEqual( response.data['user_message'], 'Bookmark with usage_id: i4x://arbi/100/html/340ef1771a0940 does not exist.' @@ -450,15 +432,14 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): """ Test that requesting bookmark with invalid usage id returns 400. """ - with self.assertNumQueries(7): # No queries for bookmark table. - response = self.send_get( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': self.user.username, 'usage_id': 'i4x'} - ), - expected_status=404 - ) + response = self.send_get( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': self.user.username, 'usage_id': 'i4x'} + ), + expected_status=404 + ) self.assertEqual(response.data['user_message'], u'Invalid usage_id: i4x.') def test_anonymous_access(self): @@ -466,19 +447,16 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): Test that an anonymous client (not logged in) cannot call GET or DELETE. """ url = reverse('bookmarks_detail', kwargs={'username': self.user.username, 'usage_id': 'i4x'}) - with self.assertNumQueries(7): # No queries for bookmark table. - self.send_get( - client=self.anonymous_client, - url=url, - expected_status=401 - ) - - with self.assertNumQueries(4): - self.send_delete( - client=self.anonymous_client, - url=url, - expected_status=401 - ) + self.send_get( + client=self.anonymous_client, + url=url, + expected_status=401 + ) + self.send_delete( + client=self.anonymous_client, + url=url, + expected_status=401 + ) def test_delete_bookmark_successfully(self): """ @@ -489,14 +467,13 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): bookmarks_data = response.data['results'] self.assertEqual(len(bookmarks_data), 2) - with self.assertNumQueries(9): # 2 queries for bookmark table. - self.send_delete( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': self.user.username, 'usage_id': unicode(self.sequential_1.location)} - ) + self.send_delete( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': self.user.username, 'usage_id': unicode(self.sequential_1.location)} ) + ) response = self.send_get(client=self.client, url=reverse('bookmarks'), query_parameters=query_parameters) bookmarks_data = response.data['results'] @@ -506,29 +483,27 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): """ Test that delete bookmark that belongs to other user returns 404. """ - with self.assertNumQueries(8): # No queries for bookmark table. - self.send_delete( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': 'other', 'usage_id': unicode(self.vertical_1.location)} - ), - expected_status=404 - ) + self.send_delete( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': 'other', 'usage_id': unicode(self.vertical_1.location)} + ), + expected_status=404 + ) def test_delete_bookmark_that_does_not_exist(self): """ Test that delete bookmark that does not exist returns 404. """ - with self.assertNumQueries(8): # 1 query for bookmark table. - response = self.send_delete( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': self.user.username, 'usage_id': 'i4x://arbi/100/html/340ef1771a0940'} - ), - expected_status=404 - ) + response = self.send_delete( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': self.user.username, 'usage_id': 'i4x://arbi/100/html/340ef1771a0940'} + ), + expected_status=404 + ) self.assertEqual( response.data['user_message'], u'Bookmark with usage_id: i4x://arbi/100/html/340ef1771a0940 does not exist.' @@ -542,15 +517,14 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): """ Test that delete bookmark with invalid usage id returns 400. """ - with self.assertNumQueries(7): # No queries for bookmark table. - response = self.send_delete( - client=self.client, - url=reverse( - 'bookmarks_detail', - kwargs={'username': self.user.username, 'usage_id': 'i4x'} - ), - expected_status=404 - ) + response = self.send_delete( + client=self.client, + url=reverse( + 'bookmarks_detail', + kwargs={'username': self.user.username, 'usage_id': 'i4x'} + ), + expected_status=404 + ) self.assertEqual(response.data['user_message'], u'Invalid usage_id: i4x.') def test_unsupported_methods(self): @@ -559,8 +533,5 @@ class BookmarksDetailViewTests(BookmarksViewsTestsBase): """ url = reverse('bookmarks_detail', kwargs={'username': self.user.username, 'usage_id': 'i4x'}) self.client.login(username=self.user.username, password=self.TEST_PASSWORD) - with self.assertNumQueries(8): # No queries for bookmark table. - self.assertEqual(405, self.client.put(url).status_code) - - with self.assertNumQueries(7): - self.assertEqual(405, self.client.post(url).status_code) + self.assertEqual(405, self.client.put(url).status_code) + self.assertEqual(405, self.client.post(url).status_code) diff --git a/openedx/core/djangoapps/content/course_overviews/tests.py b/openedx/core/djangoapps/content/course_overviews/tests.py index a87518ff2f..582b8fc8c1 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests.py +++ b/openedx/core/djangoapps/content/course_overviews/tests.py @@ -348,7 +348,7 @@ class CourseOverviewTestCase(ModuleStoreTestCase): course_overview = CourseOverview._create_from_course(course) # pylint: disable=protected-access self.assertEqual(course_overview.lowest_passing_grade, None) - @ddt.data((ModuleStoreEnum.Type.mongo, 5, 5), (ModuleStoreEnum.Type.split, 3, 4)) + @ddt.data((ModuleStoreEnum.Type.mongo, 4, 4), (ModuleStoreEnum.Type.split, 3, 4)) @ddt.unpack def test_versioning(self, modulestore_type, min_mongo_calls, max_mongo_calls): """