From 06977c198ebf3cbd3cc8d24cbc243ace635c5d01 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Mon, 19 Aug 2013 08:47:53 -0400 Subject: [PATCH 01/10] Created new test configuration for MixedModuleStore --- .../xmodule/modulestore/tests/django_utils.py | 51 ++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 4f998d57fb..8b8d61c85a 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -1,4 +1,3 @@ - import copy from uuid import uuid4 from django.test import TestCase @@ -8,6 +7,41 @@ import xmodule.modulestore.django from unittest.util import safe_repr +def mixed_store_config(data_dir, mappings): + """ + Return a `MixedModuleStore` configuration, which provides + access to both Mongo- and XML-backed courses. + + `data_dir` is the directory from which to load XML-backed courses. + `mappings` is a dictionary mapping course IDs to modulestores, for example: + + { + 'MITx/2.01x/2013_Spring': 'xml', + 'edx/999/2013_Spring': 'default' + } + + where 'xml' and 'default' are the two options provided by this configuration, + mapping (respectively) to XML-backed and Mongo-backed modulestores.. + """ + mongo_config = mongo_store_config(data_dir) + xml_config = xml_store_config(data_dir) + + store = { + 'default': { + 'ENGINE': 'xmodule.modulestore.mixed.MixedModuleStore', + 'OPTIONS': { + 'mappings': mappings, + 'stores': { + 'default': mongo_config['default'], + 'xml': xml_config['default'] + } + } + } + } + store['direct'] = store['default'] + return store + + def mongo_store_config(data_dir): """ Defines default module store using MongoModuleStore. @@ -27,6 +61,7 @@ def mongo_store_config(data_dir): } } } + store['direct'] = store['default'] return store @@ -45,23 +80,22 @@ def draft_mongo_store_config(data_dir): 'render_template': 'mitxmako.shortcuts.render_to_string' } - return { + store = { 'default': { 'ENGINE': 'xmodule.modulestore.mongo.draft.DraftModuleStore', 'OPTIONS': modulestore_options - }, - 'direct': { - 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', - 'OPTIONS': modulestore_options } } + store['direct'] = store['default'] + return store + def xml_store_config(data_dir): """ Defines default module store using XMLModuleStore. """ - return { + store = { 'default': { 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', 'OPTIONS': { @@ -71,6 +105,9 @@ def xml_store_config(data_dir): } } + store['direct'] = store['default'] + return store + class ModuleStoreTestCase(TestCase): """ Subclass for any test case that uses the mongodb From 05b34098abfce0c3c1e0d9d2bbacd7ca623a148e Mon Sep 17 00:00:00 2001 From: Will Daly Date: Mon, 19 Aug 2013 09:27:36 -0400 Subject: [PATCH 02/10] Refactored ModuleStoreTestCase to use modulestore interface for clearing _MODULESTORES --- .../lib/xmodule/xmodule/modulestore/django.py | 9 +++++++++ .../xmodule/modulestore/tests/django_utils.py | 18 +++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py index 2f0cd126f9..cd0166e4b0 100644 --- a/common/lib/xmodule/xmodule/modulestore/django.py +++ b/common/lib/xmodule/xmodule/modulestore/django.py @@ -53,3 +53,12 @@ def modulestore(name='default'): settings.MODULESTORE[name]['OPTIONS']) return _MODULESTORES[name] + +def clear_existing_modulestores(): + """ + Clear the existing modulestore instances, causing + them to be re-created when accessed again. + + This is useful for flushing state between unit tests. + """ + _MODULESTORES.clear() diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 8b8d61c85a..a38cab79f6 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -3,7 +3,7 @@ from uuid import uuid4 from django.test import TestCase from django.conf import settings -import xmodule.modulestore.django +from xmodule.modulestore.django import modulestore, clear_existing_modulestores from unittest.util import safe_repr @@ -126,7 +126,7 @@ class ModuleStoreTestCase(TestCase): 'data' is a dictionary with an entry for each CourseField we want to update. """ - store = xmodule.modulestore.django.modulestore() + store = modulestore() store.update_metadata(course.location, data) updated_course = store.get_instance(course.id, course.location) return updated_course @@ -136,15 +136,15 @@ class ModuleStoreTestCase(TestCase): """ Delete everything in the module store except templates. """ - modulestore = xmodule.modulestore.django.modulestore() + store = modulestore() # This query means: every item in the collection # that is not a template query = {"_id.course": {"$ne": "templates"}} # Remove everything except templates - modulestore.collection.remove(query) - modulestore.collection.drop() + store.collection.remove(query) + store.collection.drop() @classmethod def setUpClass(cls): @@ -160,7 +160,7 @@ class ModuleStoreTestCase(TestCase): settings.MODULESTORE['default']['OPTIONS']['collection'] = 'modulestore_%s' % uuid4().hex settings.MODULESTORE['direct']['OPTIONS']['collection'] = 'modulestore_%s' % uuid4().hex - xmodule.modulestore.django._MODULESTORES.clear() + clear_existing_modulestores() print settings.MODULESTORE @@ -173,10 +173,10 @@ class ModuleStoreTestCase(TestCase): """ # Clean up by dropping the collection - modulestore = xmodule.modulestore.django.modulestore() - modulestore.collection.drop() + store = modulestore() + store.collection.drop() - xmodule.modulestore.django._MODULESTORES.clear() + clear_existing_modulestores() # Restore the original modulestore settings settings.MODULESTORE = cls.orig_modulestore From bd65cfa813266a31b18c670c06c10f4928d85bd8 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Mon, 19 Aug 2013 09:35:30 -0400 Subject: [PATCH 03/10] Removed outdated template logic in ModuleStoreTestCase --- .../xmodule/modulestore/tests/django_utils.py | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index a38cab79f6..8e4655cf3f 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -110,10 +110,11 @@ def xml_store_config(data_dir): class ModuleStoreTestCase(TestCase): - """ Subclass for any test case that uses the mongodb - module store. This populates a uniquely named modulestore - collection with templates before running the TestCase - and drops it they are finished. """ + """ + Subclass for any test case that uses a ModuleStore. + + Ensures that the ModuleStore is cleaned before/after each test. + """ @staticmethod def update_course(course, data): @@ -132,24 +133,19 @@ class ModuleStoreTestCase(TestCase): return updated_course @staticmethod - def flush_mongo_except_templates(): + def drop_mongo_collection(): """ - Delete everything in the module store except templates. + If using a Mongo-backed modulestore, drop the collection. """ store = modulestore() - # This query means: every item in the collection - # that is not a template - query = {"_id.course": {"$ne": "templates"}} - - # Remove everything except templates - store.collection.remove(query) - store.collection.drop() + if hasattr(store, 'collection'): + store.collection.drop() @classmethod def setUpClass(cls): """ - Flush the mongo store and set up templates. + Flush the ModuleStore. """ # Use a uuid to differentiate @@ -173,8 +169,7 @@ class ModuleStoreTestCase(TestCase): """ # Clean up by dropping the collection - store = modulestore() - store.collection.drop() + cls.drop_mongo_collection() clear_existing_modulestores() @@ -183,21 +178,20 @@ class ModuleStoreTestCase(TestCase): def _pre_setup(self): """ - Remove everything but the templates before each test. + Flush the ModuleStore before each test. """ - # Flush anything that is not a template - ModuleStoreTestCase.flush_mongo_except_templates() + # Flush the Mongo modulestore + ModuleStoreTestCase.drop_mongo_collection() # Call superclass implementation super(ModuleStoreTestCase, self)._pre_setup() def _post_teardown(self): """ - Flush everything we created except the templates. + Flush the ModuleStore after each test. """ - # Flush anything that is not a template - ModuleStoreTestCase.flush_mongo_except_templates() + ModuleStoreTestCase.drop_mongo_collection() # Call superclass implementation super(ModuleStoreTestCase, self)._post_teardown() From 48c6daacb89ec7a3480b6070447f93043b590aa7 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Mon, 19 Aug 2013 09:45:18 -0400 Subject: [PATCH 04/10] Removed unnecessary settings wrangling from ModuleStoreTestCase. Modified navigation tests to use MixedModulestore Updated factories to find editable modulestore Updated test_submitting_problems Updated test_tabs.py Updated test_view_authentication Updated test_views Updated courseware/tests/tests.py Updated test_masquerade Updated test_module_render Pylint fixes Updated video and word cloud tests Updated course wiki tests Updated license and open_ended tests. One open_ended test still failing due to Mako initialization issues Updated staticbook Updated django_comment_client tests Updated instructor tests Updated instructor task tests Updated external_auth tests Updated course_groups --- .../djangoapps/course_groups/tests/tests.py | 13 +- .../external_auth/tests/test_shib.py | 8 +- .../lib/xmodule/xmodule/modulestore/django.py | 31 ++++ .../xmodule/modulestore/tests/django_utils.py | 65 +++++---- .../xmodule/modulestore/tests/factories.py | 10 +- lms/djangoapps/course_wiki/tests/tests.py | 15 +- lms/djangoapps/courseware/tests/__init__.py | 4 +- .../courseware/tests/modulestore_config.py | 16 ++- .../courseware/tests/test_masquerade.py | 22 ++- .../courseware/tests/test_module_render.py | 21 ++- .../courseware/tests/test_navigation.py | 4 +- .../tests/test_submitting_problems.py | 9 +- lms/djangoapps/courseware/tests/test_tabs.py | 4 +- .../tests/test_view_authentication.py | 4 +- lms/djangoapps/courseware/tests/test_views.py | 24 ++-- lms/djangoapps/courseware/tests/tests.py | 132 +++++++++--------- .../django_comment_client/base/tests.py | 4 +- .../django_comment_client/forum/tests.py | 4 +- .../instructor/tests/test_access.py | 10 +- lms/djangoapps/instructor/tests/test_api.py | 16 +-- .../instructor/tests/test_hint_manager.py | 4 +- .../tests/test_legacy_download_csv.py | 5 +- .../tests/test_legacy_enrollment.py | 4 +- .../tests/test_legacy_forum_admin.py | 4 +- .../instructor/tests/test_legacy_gradebook.py | 4 +- .../instructor/tests/test_legacy_xss.py | 4 +- .../instructor_task/tests/test_base.py | 8 +- lms/djangoapps/licenses/tests.py | 4 +- lms/djangoapps/open_ended_grading/tests.py | 19 ++- lms/djangoapps/staticbook/tests.py | 4 +- 30 files changed, 255 insertions(+), 221 deletions(-) diff --git a/common/djangoapps/course_groups/tests/tests.py b/common/djangoapps/course_groups/tests/tests.py index 2e519edb30..debdc68c26 100644 --- a/common/djangoapps/course_groups/tests/tests.py +++ b/common/djangoapps/course_groups/tests/tests.py @@ -8,19 +8,20 @@ from course_groups.models import CourseUserGroup from course_groups.cohorts import (get_cohort, get_course_cohorts, is_commentable_cohorted, get_cohort_by_name) -from xmodule.modulestore.django import modulestore, _MODULESTORES +from xmodule.modulestore.django import modulestore, clear_existing_modulestores -from xmodule.modulestore.tests.django_utils import xml_store_config +from xmodule.modulestore.tests.django_utils import mixed_store_config # NOTE: running this with the lms.envs.test config works without # manually overriding the modulestore. However, running with # cms.envs.test doesn't. TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT -TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) +TEST_MAPPING = { 'edX/toy/2012_Fall': 'xml' } +TEST_DATA_MIXED_MODULESTORE = mixed_store_config(TEST_DATA_DIR, TEST_MAPPING) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestCohorts(django.test.TestCase): @staticmethod @@ -82,9 +83,7 @@ class TestCohorts(django.test.TestCase): """ Make sure that course is reloaded every time--clear out the modulestore. """ - # don't like this, but don't know a better way to undo all changes made - # to course. We don't have a course.clone() method. - _MODULESTORES.clear() + clear_existing_modulestores() def test_get_cohort(self): """ diff --git a/common/djangoapps/external_auth/tests/test_shib.py b/common/djangoapps/external_auth/tests/test_shib.py index 6bb9c38e6f..187acdb595 100644 --- a/common/djangoapps/external_auth/tests/test_shib.py +++ b/common/djangoapps/external_auth/tests/test_shib.py @@ -16,9 +16,9 @@ from django.utils.importlib import import_module from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.inheritance import own_metadata -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.django import editable_modulestore -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE from external_auth.models import ExternalAuthMap from external_auth.views import shib_login, course_specific_login, course_specific_register @@ -64,7 +64,7 @@ def gen_all_identities(): yield _build_identity_dict(mail, given_name, surname) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE, SESSION_ENGINE='django.contrib.sessions.backends.cache') +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE, SESSION_ENGINE='django.contrib.sessions.backends.cache') class ShibSPTest(ModuleStoreTestCase): """ Tests for the Shibboleth SP, which communicates via request.META @@ -73,7 +73,7 @@ class ShibSPTest(ModuleStoreTestCase): request_factory = RequestFactory() def setUp(self): - self.store = modulestore() + self.store = editable_modulestore() @unittest.skipUnless(settings.MITX_FEATURES.get('AUTH_USE_SHIB'), True) def test_exception_shib_login(self): diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py index cd0166e4b0..f1235668dc 100644 --- a/common/lib/xmodule/xmodule/modulestore/django.py +++ b/common/lib/xmodule/xmodule/modulestore/django.py @@ -54,6 +54,7 @@ def modulestore(name='default'): return _MODULESTORES[name] + def clear_existing_modulestores(): """ Clear the existing modulestore instances, causing @@ -62,3 +63,33 @@ def clear_existing_modulestores(): This is useful for flushing state between unit tests. """ _MODULESTORES.clear() + + +def editable_modulestore(name='default'): + """ + Retrieve a modulestore that we can modify. + This is useful for tests that need to insert test + data into the modulestore. + + Currently, only Mongo-backed modulestores can be modified. + Returns `None` if no editable modulestore is available. + """ + + # Try to retrieve the ModuleStore + # Depending on the settings, this may or may not + # be editable. + store = modulestore(name) + + # If this is a `MixedModuleStore`, then we will need + # to retrieve the actual Mongo instance. + # We assume that the default is Mongo. + if hasattr(store, 'modulestores'): + store = store.modulestores['default'] + + # At this point, we either have the ability to create + # items in the store, or we do not. + if hasattr(store, 'create_xmodule'): + return store + + else: + return None diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 8e4655cf3f..87156ec0dd 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -1,9 +1,11 @@ -import copy +""" +eoduleStore configuration for test cases. +""" + from uuid import uuid4 from django.test import TestCase - -from django.conf import settings -from xmodule.modulestore.django import modulestore, clear_existing_modulestores +from xmodule.modulestore.django import editable_modulestore, \ + editable_modulestore, clear_existing_modulestores from unittest.util import safe_repr @@ -112,8 +114,24 @@ def xml_store_config(data_dir): class ModuleStoreTestCase(TestCase): """ Subclass for any test case that uses a ModuleStore. - Ensures that the ModuleStore is cleaned before/after each test. + + Usage: + + 1. Create a subclass of `ModuleStoreTestCase` + 2. Use Django's @override_settings decorator to use + the desired modulestore configuration. + + For example: + + MIXED_CONFIG = mixed_store_config(data_dir, mappings) + + @override_settings(MODULESTORE=MIXED_CONFIG) + class FooTest(ModuleStoreTestCase): + # ... + + 3. Use factories (e.g. `CourseFactory`, `ItemFactory`) to populate + the modulestore with test data. """ @staticmethod @@ -127,7 +145,7 @@ class ModuleStoreTestCase(TestCase): 'data' is a dictionary with an entry for each CourseField we want to update. """ - store = modulestore() + store = editable_modulestore('direct') store.update_metadata(course.location, data) updated_course = store.get_instance(course.id, course.location) return updated_course @@ -137,7 +155,10 @@ class ModuleStoreTestCase(TestCase): """ If using a Mongo-backed modulestore, drop the collection. """ - store = modulestore() + + # This will return the mongo-backed modulestore + # even if we're using a mixed modulestore + store = editable_modulestore() if hasattr(store, 'collection'): store.collection.drop() @@ -145,36 +166,30 @@ class ModuleStoreTestCase(TestCase): @classmethod def setUpClass(cls): """ - Flush the ModuleStore. + Delete the existing modulestores, causing them to be reloaded. """ - - # Use a uuid to differentiate - # the mongo collections on jenkins. - cls.orig_modulestore = copy.deepcopy(settings.MODULESTORE) - if 'direct' not in settings.MODULESTORE: - settings.MODULESTORE['direct'] = settings.MODULESTORE['default'] - - settings.MODULESTORE['default']['OPTIONS']['collection'] = 'modulestore_%s' % uuid4().hex - settings.MODULESTORE['direct']['OPTIONS']['collection'] = 'modulestore_%s' % uuid4().hex + # Clear out any existing modulestores, + # which will cause them to be re-created + # the next time they are accessed. clear_existing_modulestores() - - print settings.MODULESTORE - TestCase.setUpClass() @classmethod def tearDownClass(cls): """ - Revert to the old modulestore settings. + Drop the existing modulestores, causing them to be reloaded. + Clean up any data stored in Mongo. """ - - # Clean up by dropping the collection + # Clean up by flushing the Mongo modulestore cls.drop_mongo_collection() + # Clear out the existing modulestores, + # which will cause them to be re-created + # the next time they are accessed. + # We do this at *both* setup and teardown just to be safe. clear_existing_modulestores() - # Restore the original modulestore settings - settings.MODULESTORE = cls.orig_modulestore + TestCase.tearDownClass() def _pre_setup(self): """ diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py index f2e4017114..7913434086 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -5,11 +5,12 @@ from uuid import uuid4 from pytz import UTC from xmodule.modulestore import Location -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.django import editable_modulestore from xmodule.course_module import CourseDescriptor from xblock.core import Scope from xmodule.x_module import XModuleDescriptor + class XModuleCourseFactory(Factory): """ Factory for XModule courses. @@ -25,10 +26,7 @@ class XModuleCourseFactory(Factory): display_name = kwargs.pop('display_name', None) location = Location('i4x', org, number, 'course', Location.clean(display_name)) - try: - store = modulestore('direct') - except KeyError: - store = modulestore() + store = editable_modulestore('direct') # Write the data to the mongo datastore new_course = store.create_xmodule(location) @@ -117,7 +115,7 @@ class XModuleItemFactory(Factory): if not isinstance(data, basestring): data.update(template.get('data')) - store = modulestore('direct') + store = editable_modulestore('direct') # This code was based off that in cms/djangoapps/contentstore/views.py parent = store.get_item(parent_location) diff --git a/lms/djangoapps/course_wiki/tests/tests.py b/lms/djangoapps/course_wiki/tests/tests.py index 6bbd8011d6..93954dab61 100644 --- a/lms/djangoapps/course_wiki/tests/tests.py +++ b/lms/djangoapps/course_wiki/tests/tests.py @@ -3,21 +3,18 @@ from django.test.utils import override_settings import xmodule.modulestore.django -from courseware.tests.tests import LoginEnrollmentTestCase, TEST_DATA_XML_MODULESTORE +from courseware.tests.tests import LoginEnrollmentTestCase +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.django import modulestore -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class WikiRedirectTestCase(LoginEnrollmentTestCase): + def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} - courses = modulestore().get_courses() - def find_course(name): - """Assumes the course is present""" - return [c for c in courses if c.location.course == name][0] - - self.toy = find_course("toy") + # Load the toy course + self.toy = modulestore().get_course('edX/toy/2012_Fall') # Create two accounts self.student = 'view@test.com' diff --git a/lms/djangoapps/courseware/tests/__init__.py b/lms/djangoapps/courseware/tests/__init__.py index 9d1b549b9f..4b93e804bf 100644 --- a/lms/djangoapps/courseware/tests/__init__.py +++ b/lms/djangoapps/courseware/tests/__init__.py @@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse from django.test.client import Client from student.tests.factories import UserFactory, CourseEnrollmentFactory -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.tests import get_test_system from xmodule.modulestore import Location from xmodule.modulestore.django import modulestore @@ -20,7 +20,7 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class BaseTestXmodule(ModuleStoreTestCase): """Base class for testing Xmodules with mongo store. diff --git a/lms/djangoapps/courseware/tests/modulestore_config.py b/lms/djangoapps/courseware/tests/modulestore_config.py index 80a7b0a7c1..e4ee86878f 100644 --- a/lms/djangoapps/courseware/tests/modulestore_config.py +++ b/lms/djangoapps/courseware/tests/modulestore_config.py @@ -1,4 +1,6 @@ -from xmodule.modulestore.tests.django_utils import xml_store_config, mongo_store_config, draft_mongo_store_config +from xmodule.modulestore.tests.django_utils import xml_store_config, \ + mongo_store_config, draft_mongo_store_config,\ + mixed_store_config from django.conf import settings @@ -6,3 +8,15 @@ TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) TEST_DATA_MONGO_MODULESTORE = mongo_store_config(TEST_DATA_DIR) TEST_DATA_DRAFT_MONGO_MODULESTORE = draft_mongo_store_config(TEST_DATA_DIR) + +# Map all XML course fixtures so they are accessible through +# the MixedModuleStore +MAPPINGS = { + 'edX/toy/2012_Fall': 'xml', + 'edX/toy/TT_2012_Fall': 'xml', + 'edX/test_end/2012_Fall': 'xml', + 'edX/test_about_blob_end_date/2012_Fall': 'xml', + 'edX/graded/2012_Fall': 'xml', + 'edX/open_ended/2012_Fall': 'xml', +} +TEST_DATA_MIXED_MODULESTORE = mixed_store_config(TEST_DATA_DIR, MAPPINGS) diff --git a/lms/djangoapps/courseware/tests/test_masquerade.py b/lms/djangoapps/courseware/tests/test_masquerade.py index 0fc4eae242..3122dc6477 100644 --- a/lms/djangoapps/courseware/tests/test_masquerade.py +++ b/lms/djangoapps/courseware/tests/test_masquerade.py @@ -15,23 +15,18 @@ from django.core.urlresolvers import reverse from django.contrib.auth.models import Group, User from courseware.access import _course_staff_group_name from courseware.tests.helpers import LoginEnrollmentTestCase -from modulestore_config import TEST_DATA_XML_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.django import modulestore -import xmodule.modulestore.django import json -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestStaffMasqueradeAsStudent(LoginEnrollmentTestCase): - ''' - Check for staff being able to masquerade as student - ''' + """ + Check for staff being able to masquerade as student. + """ def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} - - #self.full = modulestore().get_course("edX/full/6.002_Spring_2012") - #self.toy = modulestore().get_course("edX/toy/2012_Fall") self.graded_course = modulestore().get_course("edX/graded/2012_Fall") # Create staff account @@ -50,7 +45,6 @@ class TestStaffMasqueradeAsStudent(LoginEnrollmentTestCase): self.logout() self.login(self.instructor, self.password) self.enroll(self.graded_course) - # self.factory = RequestFactory() def get_cw_section(self): url = reverse('courseware_section', @@ -70,9 +64,9 @@ class TestStaffMasqueradeAsStudent(LoginEnrollmentTestCase): self.assertTrue(sdebug in resp.content) def toggle_masquerade(self): - ''' - Toggle masquerade state - ''' + """ + Toggle masquerade state. + """ masq_url = reverse('masquerade-switch', kwargs={'marg': 'toggle'}) print "masq_url ", masq_url resp = self.client.get(masq_url) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 25056ba100..9c11dfc617 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -15,22 +15,17 @@ from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase import courseware.module_render as render -from courseware.tests.tests import LoginEnrollmentTestCase, TEST_DATA_MONGO_MODULESTORE +from courseware.tests.tests import LoginEnrollmentTestCase from courseware.model_data import ModelDataCache -from modulestore_config import TEST_DATA_XML_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from courseware.courses import get_course_with_access from .factories import UserFactory -class Stub: - def __init__(self): - pass - - -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class ModuleRenderTestCase(LoginEnrollmentTestCase): +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class ModuleRenderTestCase(ModuleStoreTestCase, LoginEnrollmentTestCase): def setUp(self): self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] self.course_id = 'edX/toy/2012_Fall' @@ -96,7 +91,7 @@ class ModuleRenderTestCase(LoginEnrollmentTestCase): settings.MAX_FILEUPLOADS_PER_INPUT})) mock_request_2 = MagicMock() mock_request_2.FILES.keys.return_value = ['file_id'] - inputfile = Stub() + inputfile = MagicMock() inputfile.size = 1 + settings.STUDENT_FILEUPLOAD_MAX_SIZE inputfile.name = 'name' filelist = [inputfile] @@ -109,7 +104,7 @@ class ModuleRenderTestCase(LoginEnrollmentTestCase): mock_request_3.POST.copy.return_value = {'position': 1} mock_request_3.FILES = False mock_request_3.user = self.mock_user - inputfile_2 = Stub() + inputfile_2 = MagicMock() inputfile_2.size = 1 inputfile_2.name = 'name' self.assertIsInstance(render.modx_dispatch(mock_request_3, 'goto_position', @@ -200,7 +195,7 @@ class ModuleRenderTestCase(LoginEnrollmentTestCase): self.assertEquals(403, response.status_code) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestTOC(TestCase): """Check the Table of Contents for a course""" def setUp(self): @@ -266,7 +261,7 @@ class TestTOC(TestCase): self.assertIn(toc_section, actual) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestHtmlModifiers(ModuleStoreTestCase): """ Tests to verify that standard modifications to the output of XModule/XBlock diff --git a/lms/djangoapps/courseware/tests/test_navigation.py b/lms/djangoapps/courseware/tests/test_navigation.py index dd1f00711c..2b416b16de 100644 --- a/lms/djangoapps/courseware/tests/test_navigation.py +++ b/lms/djangoapps/courseware/tests/test_navigation.py @@ -6,10 +6,10 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from helpers import LoginEnrollmentTestCase, check_for_get_code -from modulestore_config import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Check that navigation state is saved properly. diff --git a/lms/djangoapps/courseware/tests/test_submitting_problems.py b/lms/djangoapps/courseware/tests/test_submitting_problems.py index 9081a910c9..f8cfaefd75 100644 --- a/lms/djangoapps/courseware/tests/test_submitting_problems.py +++ b/lms/djangoapps/courseware/tests/test_submitting_problems.py @@ -13,17 +13,17 @@ from django.test.utils import override_settings from courseware import grades from courseware.model_data import ModelDataCache -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.django import modulestore, editable_modulestore #import factories and parent testcase modules from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from capa.tests.response_xml_factory import OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory from courseware.tests.helpers import LoginEnrollmentTestCase -from courseware.tests.modulestore_config import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Check that a course gets graded properly. @@ -217,7 +217,8 @@ class TestCourseGrader(TestSubmittingProblems): """ course_data = {'grading_policy': grading_policy} - modulestore().update_item(self.course.location, course_data) + store = editable_modulestore('direct') + store.update_item(self.course.location, course_data) self.refresh_course() def get_grade_summary(self): diff --git a/lms/djangoapps/courseware/tests/test_tabs.py b/lms/djangoapps/courseware/tests/test_tabs.py index 4435b5c951..5de7a39f63 100644 --- a/lms/djangoapps/courseware/tests/test_tabs.py +++ b/lms/djangoapps/courseware/tests/test_tabs.py @@ -7,9 +7,9 @@ import courseware.tabs as tabs from django.test.utils import override_settings from django.core.urlresolvers import reverse -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE class ProgressTestCase(TestCase): @@ -261,7 +261,7 @@ class ValidateTabsTestCase(TestCase): self.assertRaises(tabs.InvalidTabsException, tabs.validate_tabs, self.courses[4]) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class DiscussionLinkTestCase(ModuleStoreTestCase): def setUp(self): diff --git a/lms/djangoapps/courseware/tests/test_view_authentication.py b/lms/djangoapps/courseware/tests/test_view_authentication.py index 055c860fcc..849e5fdc45 100644 --- a/lms/djangoapps/courseware/tests/test_view_authentication.py +++ b/lms/djangoapps/courseware/tests/test_view_authentication.py @@ -16,10 +16,10 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from helpers import LoginEnrollmentTestCase, check_for_get_code -from modulestore_config import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Check that view authentication works properly. diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 6f665f7345..0c23b31f53 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -17,22 +17,20 @@ from xmodule.modulestore.django import modulestore import courseware.views as views from xmodule.modulestore import Location from pytz import UTC -from modulestore_config import TEST_DATA_XML_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -class Stub(): - pass - - -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestJumpTo(TestCase): - """Check the jumpto link for a course""" - def setUp(self): - self._MODULESTORES = {} + """ + Check the jumpto link for a course. + """ - # Toy courses should be loaded + def setUp(self): + + # Load toy course from XML self.course_name = 'edX/toy/2012_Fall' - self.toy_course = modulestore().get_course('edX/toy/2012_Fall') + self.toy_course = modulestore().get_course(self.course_name) def test_jumpto_invalid_location(self): location = Location('i4x', 'edX', 'toy', 'NoSuchPlace', None) @@ -71,7 +69,7 @@ class ViewsTestCase(TestCase): self.enrollment.created = self.date self.enrollment.save() self.location = ['tag', 'org', 'course', 'category', 'name'] - self._MODULESTORES = {} + # This is a CourseDescriptor object self.toy_course = modulestore().get_course('edX/toy/2012_Fall') self.request_factory = RequestFactory() @@ -85,7 +83,7 @@ class ViewsTestCase(TestCase): self.assertEquals(views.user_groups(mock_user), []) def test_get_current_child(self): - self.assertIsNone(views.get_current_child(Stub())) + self.assertIsNone(views.get_current_child(MagicMock())) mock_xmodule = MagicMock() mock_xmodule.position = -1 mock_xmodule.get_display_items.return_value = ['one', 'two'] diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index cd245d2610..995c7a352c 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -1,25 +1,21 @@ -''' -Test for lms courseware app -''' -import random - +""" +Test for LMS courseware app. +""" from django.test import TestCase from django.core.urlresolvers import reverse from django.test.utils import override_settings -import xmodule.modulestore.django from xmodule.error_module import ErrorDescriptor from xmodule.modulestore.django import modulestore from xmodule.modulestore import Location from xmodule.modulestore.xml_importer import import_from_xml -from xmodule.modulestore.xml import XMLModuleStore +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from helpers import LoginEnrollmentTestCase -from modulestore_config import TEST_DATA_DIR, \ - TEST_DATA_XML_MODULESTORE, \ +from courseware.tests.helpers import LoginEnrollmentTestCase +from courseware.tests.modulestore_config import TEST_DATA_DIR, \ TEST_DATA_MONGO_MODULESTORE, \ - TEST_DATA_DRAFT_MONGO_MODULESTORE -import xmodule + TEST_DATA_DRAFT_MONGO_MODULESTORE, \ + TEST_DATA_MIXED_MODULESTORE class ActivateLoginTest(LoginEnrollmentTestCase): @@ -47,57 +43,60 @@ class PageLoaderTestCase(LoginEnrollmentTestCase): Base class that adds a function to load all pages in a modulestore. """ - def check_random_page_loads(self, module_store): + def check_all_pages_load(self, course_id): """ - Choose a page in the course randomly, and assert that it loads. + Assert that all pages in the course load correctly. + `course_id` is the ID of the course to check. """ - # enroll in the course before trying to access pages - courses = module_store.get_courses() - self.assertEqual(len(courses), 1) - course = courses[0] + + store = modulestore() + + # Enroll in the course before trying to access pages + course = store.get_course(course_id) self.enroll(course, True) - course_id = course.id # Search for items in the course # None is treated as a wildcard course_loc = course.location - location_query = Location(course_loc.tag, course_loc.org, - course_loc.course, None, None, None) + location_query = Location( + course_loc.tag, course_loc.org, + course_loc.course, None, None, None + ) - items = module_store.get_items(location_query) + items = store.get_items( + location_query, + course_id=course_id, + depth=2 + ) if len(items) < 1: self.fail('Could not retrieve any items from course') - else: - descriptor = random.choice(items) - # We have ancillary course information now as modules - # and we can't simply use 'jump_to' to view them - if descriptor.location.category == 'about': - self._assert_loads('about_course', - {'course_id': course_id}, - descriptor) + # Try to load each item in the course + for descriptor in items: - elif descriptor.location.category == 'static_tab': - kwargs = {'course_id': course_id, - 'tab_slug': descriptor.location.name} - self._assert_loads('static_tab', kwargs, descriptor) + if descriptor.location.category == 'about': + self._assert_loads('about_course', + {'course_id': course_id}, + descriptor) - elif descriptor.location.category == 'course_info': - self._assert_loads('info', {'course_id': course_id}, - descriptor) + elif descriptor.location.category == 'static_tab': + kwargs = {'course_id': course_id, + 'tab_slug': descriptor.location.name} + self._assert_loads('static_tab', kwargs, descriptor) - elif descriptor.location.category == 'custom_tag_template': - pass + elif descriptor.location.category == 'course_info': + self._assert_loads('info', {'course_id': course_id}, + descriptor) - else: + else: - kwargs = {'course_id': course_id, - 'location': descriptor.location.url()} + kwargs = {'course_id': course_id, + 'location': descriptor.location.url()} - self._assert_loads('jump_to', kwargs, descriptor, - expect_redirect=True, - check_content=True) + self._assert_loads('jump_to', kwargs, descriptor, + expect_redirect=True, + check_content=True) def _assert_loads(self, django_url, kwargs, descriptor, expect_redirect=False, @@ -124,54 +123,51 @@ class PageLoaderTestCase(LoginEnrollmentTestCase): self.assertNotIsInstance(descriptor, ErrorDescriptor) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class TestCoursesLoadTestCase_XmlModulestore(PageLoaderTestCase): +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class TestXmlCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase): """ Check that all pages in test courses load properly from XML. """ def setUp(self): - super(TestCoursesLoadTestCase_XmlModulestore, self).setUp() + super(TestXmlCoursesLoad, self).setUp() self.setup_user() - xmodule.modulestore.django._MODULESTORES.clear() def test_toy_course_loads(self): - module_class = 'xmodule.hidden_module.HiddenDescriptor' - module_store = XMLModuleStore(TEST_DATA_DIR, - default_class=module_class, - course_dirs=['toy'], - load_error_modules=True) - self.check_random_page_loads(module_store) + # Load one of the XML based courses + # Our test mapping rules allow the MixedModuleStore + # to load this course from XML, not Mongo. + self.check_all_pages_load('edX/toy/2012_Fall') +# Importing XML courses isn't possible with MixedModuleStore, +# so we use a Mongo modulestore directly (as we would in Studio) @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) -class TestCoursesLoadTestCase_MongoModulestore(PageLoaderTestCase): +class TestMongoCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase): """ Check that all pages in test courses load properly from Mongo. """ def setUp(self): - super(TestCoursesLoadTestCase_MongoModulestore, self).setUp() + super(TestMongoCoursesLoad, self).setUp() self.setup_user() - xmodule.modulestore.django._MODULESTORES.clear() - modulestore().collection.drop() + + # Import the toy course into a Mongo-backed modulestore + self.store = modulestore() + import_from_xml(self.store, TEST_DATA_DIR, ['toy']) def test_toy_course_loads(self): - module_store = modulestore() - import_from_xml(module_store, TEST_DATA_DIR, ['toy']) - self.check_random_page_loads(module_store) + self.check_all_pages_load('edX/toy/2012_Fall') def test_toy_textbooks_loads(self): - module_store = modulestore() - import_from_xml(module_store, TEST_DATA_DIR, ['toy']) - - course = module_store.get_item(Location(['i4x', 'edX', 'toy', 'course', '2012_Fall', None])) - + location = Location(['i4x', 'edX', 'toy', 'course', '2012_Fall', None]) + course = self.store.get_item(location) self.assertGreater(len(course.textbooks), 0) + @override_settings(MODULESTORE=TEST_DATA_DRAFT_MONGO_MODULESTORE) -class TestDraftModuleStore(TestCase): +class TestDraftModuleStore(ModuleStoreTestCase, TestCase): def test_get_items_with_course_items(self): store = modulestore() diff --git a/lms/djangoapps/django_comment_client/base/tests.py b/lms/djangoapps/django_comment_client/base/tests.py index 434d4d616b..e6ce3b2d25 100644 --- a/lms/djangoapps/django_comment_client/base/tests.py +++ b/lms/djangoapps/django_comment_client/base/tests.py @@ -10,14 +10,14 @@ from django.core.urlresolvers import reverse from django.core.management import call_command from util.testing import UrlResetMixin -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from nose.tools import assert_true, assert_equal from mock import patch log = logging.getLogger(__name__) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) @patch('comment_client.utils.requests.request') class ViewsTestCase(UrlResetMixin, ModuleStoreTestCase): diff --git a/lms/djangoapps/django_comment_client/forum/tests.py b/lms/djangoapps/django_comment_client/forum/tests.py index bd18ab80d6..2d889722a4 100644 --- a/lms/djangoapps/django_comment_client/forum/tests.py +++ b/lms/djangoapps/django_comment_client/forum/tests.py @@ -6,7 +6,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from django.core.urlresolvers import reverse from util.testing import UrlResetMixin -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from nose.tools import assert_true from mock import patch, Mock @@ -15,7 +15,7 @@ import logging log = logging.getLogger(__name__) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): @patch.dict("django.conf.settings.MITX_FEATURES", {"ENABLE_DISCUSSION_SERVICE": True}) diff --git a/lms/djangoapps/instructor/tests/test_access.py b/lms/djangoapps/instructor/tests/test_access.py index 688ed89dad..ee2e91f766 100644 --- a/lms/djangoapps/instructor/tests/test_access.py +++ b/lms/djangoapps/instructor/tests/test_access.py @@ -9,7 +9,7 @@ from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from django.test.utils import override_settings -from courseware.tests.modulestore_config import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from courseware.access import get_access_group_name from django_comment_common.models import (Role, @@ -20,7 +20,7 @@ from instructor.access import (allow_access, update_forum_role_membership) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAccessList(ModuleStoreTestCase): """ Test access listings. """ def setUp(self): @@ -42,7 +42,7 @@ class TestInstructorAccessList(ModuleStoreTestCase): self.assertEqual(set(beta_testers), set(self.beta_testers)) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAccessAllow(ModuleStoreTestCase): """ Test access allow. """ def setUp(self): @@ -85,7 +85,7 @@ class TestInstructorAccessAllow(ModuleStoreTestCase): group = Group.objects.get(name=get_access_group_name(self.course, 'staff')) self.assertIn(user, group.user_set.all()) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAccessRevoke(ModuleStoreTestCase): """ Test access revoke. """ def setUp(self): @@ -129,7 +129,7 @@ class TestInstructorAccessRevoke(ModuleStoreTestCase): self.assertNotIn(user, group.user_set.all()) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAccessForum(ModuleStoreTestCase): """ Test forum access control. diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index 155a8a2c9f..7d55b001d0 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -14,7 +14,7 @@ from django.core.urlresolvers import reverse from django.http import HttpRequest, HttpResponse from django.contrib.auth.models import User -from courseware.tests.modulestore_config import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from courseware.tests.helpers import LoginEnrollmentTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -90,7 +90,7 @@ class TestCommonExceptions400(unittest.TestCase): self.assertIn("Task is already running", result["error"]) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAPIDenyLevels(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Ensure that users cannot access endpoints they shouldn't be able to. @@ -147,7 +147,7 @@ class TestInstructorAPIDenyLevels(ModuleStoreTestCase, LoginEnrollmentTestCase): self.assertEqual(response.status_code, 403) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAPIEnrollment(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Test enrollment modification endpoint. @@ -270,7 +270,7 @@ class TestInstructorAPIEnrollment(ModuleStoreTestCase, LoginEnrollmentTestCase): self.assertEqual(res_json, expected) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAPILevelsAccess(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Test endpoints whereby instructors can change permissions @@ -414,7 +414,7 @@ class TestInstructorAPILevelsAccess(ModuleStoreTestCase, LoginEnrollmentTestCase self.assertEqual(res_json, expected) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Test endpoints that show data without side effects. @@ -521,7 +521,7 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa self.assertEqual(response.status_code, 400) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAPIRegradeTask(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Test endpoints whereby instructors can change student grades. @@ -655,7 +655,7 @@ class TestInstructorAPIRegradeTask(ModuleStoreTestCase, LoginEnrollmentTestCase) self.assertTrue(act.called) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAPITaskLists(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Test instructor task list endpoint. @@ -745,7 +745,7 @@ class TestInstructorAPITaskLists(ModuleStoreTestCase, LoginEnrollmentTestCase): self.assertEqual(json.loads(response.content), expected_res) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) @override_settings(ANALYTICS_SERVER_URL="http://robotanalyticsserver.netbot:900/") @override_settings(ANALYTICS_API_KEY="robot_api_key") class TestInstructorAPIAnalyticsProxy(ModuleStoreTestCase, LoginEnrollmentTestCase): diff --git a/lms/djangoapps/instructor/tests/test_hint_manager.py b/lms/djangoapps/instructor/tests/test_hint_manager.py index 8f12572875..4513025aa5 100644 --- a/lms/djangoapps/instructor/tests/test_hint_manager.py +++ b/lms/djangoapps/instructor/tests/test_hint_manager.py @@ -5,14 +5,14 @@ from django.test.utils import override_settings from courseware.models import XModuleContentField from courseware.tests.factories import ContentFactory -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE import instructor.hint_manager as view from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class HintManagerTest(ModuleStoreTestCase): def setUp(self): diff --git a/lms/djangoapps/instructor/tests/test_legacy_download_csv.py b/lms/djangoapps/instructor/tests/test_legacy_download_csv.py index b05746f015..b77626c8a1 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_download_csv.py +++ b/lms/djangoapps/instructor/tests/test_legacy_download_csv.py @@ -17,12 +17,12 @@ from django.core.urlresolvers import reverse from courseware.access import _course_staff_group_name from courseware.tests.helpers import LoginEnrollmentTestCase -from courseware.tests.modulestore_config import TEST_DATA_XML_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.django import modulestore import xmodule.modulestore.django -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorDashboardGradeDownloadCSV(LoginEnrollmentTestCase): ''' Check for download of csv @@ -31,7 +31,6 @@ class TestInstructorDashboardGradeDownloadCSV(LoginEnrollmentTestCase): def setUp(self): xmodule.modulestore.django._MODULESTORES = {} - self.full = modulestore().get_course("edX/full/6.002_Spring_2012") self.toy = modulestore().get_course("edX/toy/2012_Fall") # Create two accounts diff --git a/lms/djangoapps/instructor/tests/test_legacy_enrollment.py b/lms/djangoapps/instructor/tests/test_legacy_enrollment.py index 1f5ea8ad56..4c1c252891 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_enrollment.py +++ b/lms/djangoapps/instructor/tests/test_legacy_enrollment.py @@ -7,7 +7,7 @@ from django.test.utils import override_settings from django.contrib.auth.models import User from django.core.urlresolvers import reverse from courseware.tests.helpers import LoginEnrollmentTestCase -from courseware.tests.modulestore_config import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -18,7 +18,7 @@ from django.core import mail USER_COUNT = 4 -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Check Enrollment/Unenrollment with/without auto-enrollment on activation and with/without email notification diff --git a/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py b/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py index 90dadd569e..3b691aa708 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py +++ b/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py @@ -15,7 +15,7 @@ from django_comment_client.utils import has_forum_access from courseware.access import _course_staff_group_name from courseware.tests.helpers import LoginEnrollmentTestCase -from courseware.tests.modulestore_config import TEST_DATA_XML_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.django import modulestore import xmodule.modulestore.django @@ -32,7 +32,7 @@ def action_name(operation, rolename): return '{0} forum {1}'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename]) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorDashboardForumAdmin(LoginEnrollmentTestCase): ''' Check for change in forum admin role memberships diff --git a/lms/djangoapps/instructor/tests/test_legacy_gradebook.py b/lms/djangoapps/instructor/tests/test_legacy_gradebook.py index aaf03deb8c..fd285d2e3f 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_gradebook.py +++ b/lms/djangoapps/instructor/tests/test_legacy_gradebook.py @@ -7,7 +7,7 @@ from django.core.urlresolvers import reverse from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE from capa.tests.response_xml_factory import StringResponseXMLFactory from courseware.tests.factories import StudentModuleFactory from xmodule.modulestore import Location @@ -17,7 +17,7 @@ from xmodule.modulestore.django import modulestore USER_COUNT = 11 -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestGradebook(ModuleStoreTestCase): grading_policy = None diff --git a/lms/djangoapps/instructor/tests/test_legacy_xss.py b/lms/djangoapps/instructor/tests/test_legacy_xss.py index 7df6511b3c..784838fc4c 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_xss.py +++ b/lms/djangoapps/instructor/tests/test_legacy_xss.py @@ -7,14 +7,14 @@ from django.test.client import RequestFactory from django.test.utils import override_settings from markupsafe import escape -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE from student.tests.factories import UserFactory, CourseEnrollmentFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from instructor.views import legacy -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestXss(ModuleStoreTestCase): def setUp(self): self._request_factory = RequestFactory() diff --git a/lms/djangoapps/instructor_task/tests/test_base.py b/lms/djangoapps/instructor_task/tests/test_base.py index b67453e997..2c1fe02bd8 100644 --- a/lms/djangoapps/instructor_task/tests/test_base.py +++ b/lms/djangoapps/instructor_task/tests/test_base.py @@ -13,13 +13,13 @@ from django.contrib.auth.models import User from django.test.utils import override_settings from capa.tests.response_xml_factory import OptionResponseXMLFactory -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.django import editable_modulestore from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from student.tests.factories import CourseEnrollmentFactory, UserFactory from courseware.model_data import StudentModule -from courseware.tests.tests import LoginEnrollmentTestCase, TEST_DATA_MONGO_MODULESTORE +from courseware.tests.tests import LoginEnrollmentTestCase, TEST_DATA_MIXED_MODULESTORE from instructor_task.api_helper import encode_problem_and_student_input from instructor_task.models import PROGRESS, QUEUING @@ -95,7 +95,7 @@ class InstructorTaskTestCase(TestCase): return self._create_entry(task_state=task_state, task_output=progress, student=student) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class InstructorTaskModuleTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): """ Base test class for InstructorTask-related tests that require @@ -106,7 +106,7 @@ class InstructorTaskModuleTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase) def initialize_course(self): """Create a course in the store, with a chapter and section.""" - self.module_store = modulestore() + self.module_store = editable_modulestore() # Create the course self.course = CourseFactory.create(org=TEST_COURSE_ORG, diff --git a/lms/djangoapps/licenses/tests.py b/lms/djangoapps/licenses/tests.py index 151a0faa9d..a853955c83 100644 --- a/lms/djangoapps/licenses/tests.py +++ b/lms/djangoapps/licenses/tests.py @@ -14,7 +14,7 @@ from django.core.management import call_command from django.core.urlresolvers import reverse from nose.tools import assert_true -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from licenses.models import CourseSoftware, UserLicense from student.tests.factories import UserFactory @@ -143,7 +143,7 @@ class LicenseTestCase(TestCase): self.assertEqual(302, response.status_code) -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class CommandTest(ModuleStoreTestCase): '''Test management command for importing serial numbers''' def setUp(self): diff --git a/lms/djangoapps/open_ended_grading/tests.py b/lms/djangoapps/open_ended_grading/tests.py index 262124d667..7ae5994dc1 100644 --- a/lms/djangoapps/open_ended_grading/tests.py +++ b/lms/djangoapps/open_ended_grading/tests.py @@ -27,14 +27,15 @@ log = logging.getLogger(__name__) from django.test.utils import override_settings from xmodule.tests import test_util_open_ended +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from courseware.tests import factories -from courseware.tests.modulestore_config import TEST_DATA_XML_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from courseware.tests.helpers import LoginEnrollmentTestCase, check_for_get_code, check_for_post_code -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class TestStaffGradingService(LoginEnrollmentTestCase): +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class TestStaffGradingService(ModuleStoreTestCase, LoginEnrollmentTestCase): ''' Check that staff grading service proxy works. Basically just checking the access control and error handling logic -- all the actual work is on the @@ -42,8 +43,6 @@ class TestStaffGradingService(LoginEnrollmentTestCase): ''' def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} - self.student = 'view@test.com' self.instructor = 'view2@test.com' self.password = 'foo' @@ -138,8 +137,8 @@ class TestStaffGradingService(LoginEnrollmentTestCase): self.assertIsNotNone(content['problem_list']) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class TestPeerGradingService(LoginEnrollmentTestCase): +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class TestPeerGradingService(ModuleStoreTestCase, LoginEnrollmentTestCase): ''' Check that staff grading service proxy works. Basically just checking the access control and error handling logic -- all the actual work is on the @@ -147,8 +146,6 @@ class TestPeerGradingService(LoginEnrollmentTestCase): ''' def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} - self.student = 'view@test.com' self.instructor = 'view2@test.com' self.password = 'foo' @@ -293,8 +290,8 @@ class TestPeerGradingService(LoginEnrollmentTestCase): self.assertFalse('actual_score' in response) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class TestPanel(LoginEnrollmentTestCase): +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class TestPanel(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Run tests on the open ended panel """ diff --git a/lms/djangoapps/staticbook/tests.py b/lms/djangoapps/staticbook/tests.py index deb13ffc9e..c18b3663e7 100644 --- a/lms/djangoapps/staticbook/tests.py +++ b/lms/djangoapps/staticbook/tests.py @@ -10,7 +10,7 @@ import requests from django.test.utils import override_settings from django.core.urlresolvers import reverse, NoReverseMatch -from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from student.tests.factories import UserFactory, CourseEnrollmentFactory from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -36,7 +36,7 @@ HTML_BOOK = { ], } -@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class StaticBookTest(ModuleStoreTestCase): """ Helpers for the static book tests. From 151782acf052fc3a3c5c722d5668855514687a36 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Wed, 21 Aug 2013 16:23:48 -0400 Subject: [PATCH 05/10] LMS acceptance tests use mixed modulestore --- common/djangoapps/terrain/browser.py | 5 ++-- common/djangoapps/terrain/course_helpers.py | 6 ++-- .../xmodule/modulestore/tests/django_utils.py | 29 ------------------- lms/envs/acceptance.py | 18 ++++++++---- 4 files changed, 17 insertions(+), 41 deletions(-) diff --git a/common/djangoapps/terrain/browser.py b/common/djangoapps/terrain/browser.py index c2bf2bbbf3..24dd9f3729 100644 --- a/common/djangoapps/terrain/browser.py +++ b/common/djangoapps/terrain/browser.py @@ -108,9 +108,10 @@ def reset_databases(scenario): mongo = MongoClient() mongo.drop_database(settings.CONTENTSTORE['OPTIONS']['db']) _CONTENTSTORE.clear() - modulestore = xmodule.modulestore.django.modulestore() + + modulestore = xmodule.modulestore.django.editable_modulestore() modulestore.collection.drop() - xmodule.modulestore.django._MODULESTORES.clear() + xmodule.modulestore.django.clear_existing_modulestores() # Uncomment below to trigger a screenshot on error diff --git a/common/djangoapps/terrain/course_helpers.py b/common/djangoapps/terrain/course_helpers.py index eca3290080..fc01d25d66 100644 --- a/common/djangoapps/terrain/course_helpers.py +++ b/common/djangoapps/terrain/course_helpers.py @@ -10,7 +10,7 @@ from django.contrib.auth import authenticate, login from django.contrib.auth.middleware import AuthenticationMiddleware from django.contrib.sessions.middleware import SessionMiddleware from student.models import CourseEnrollment -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.django import editable_modulestore from xmodule.contentstore.django import contentstore from urllib import quote_plus @@ -60,11 +60,9 @@ def register_by_course_id(course_id, is_staff=False): @world.absorb def clear_courses(): # Flush and initialize the module store - # It needs the templates because it creates new records - # by cloning from the template. # Note that if your test module gets in some weird state # (though it shouldn't), do this manually # from the bash shell to drop it: # $ mongo test_xmodule --eval "db.dropDatabase()" - modulestore().collection.drop() + editable_modulestore().collection.drop() contentstore().fs_files.drop() diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 87156ec0dd..dabdd00e43 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -210,32 +210,3 @@ class ModuleStoreTestCase(TestCase): # Call superclass implementation super(ModuleStoreTestCase, self)._post_teardown() - - - def assert2XX(self, status_code, msg=None): - """ - Assert that the given value is a success status (between 200 and 299) - """ - msg = self._formatMessage(msg, "%s is not a success status" % safe_repr(status_code)) - self.assertTrue(status_code >= 200 and status_code < 300, msg=msg) - - def assert3XX(self, status_code, msg=None): - """ - Assert that the given value is a redirection status (between 300 and 399) - """ - msg = self._formatMessage(msg, "%s is not a redirection status" % safe_repr(status_code)) - self.assertTrue(status_code >= 300 and status_code < 400, msg=msg) - - def assert4XX(self, status_code, msg=None): - """ - Assert that the given value is a client error status (between 400 and 499) - """ - msg = self._formatMessage(msg, "%s is not a client error status" % safe_repr(status_code)) - self.assertTrue(status_code >= 400 and status_code < 500, msg=msg) - - def assert5XX(self, status_code, msg=None): - """ - Assert that the given value is a server error status (between 500 and 599) - """ - msg = self._formatMessage(msg, "%s is not a server error status" % safe_repr(status_code)) - self.assertTrue(status_code >= 500 and status_code < 600, msg=msg) diff --git a/lms/envs/acceptance.py b/lms/envs/acceptance.py index 1e188d3b45..a5c455288a 100644 --- a/lms/envs/acceptance.py +++ b/lms/envs/acceptance.py @@ -35,15 +35,21 @@ modulestore_options = { MODULESTORE = { 'default': { - 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', - 'OPTIONS': modulestore_options - }, - 'direct': { - 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', - 'OPTIONS': modulestore_options + 'ENGINE': 'xmodule.modulestore.mixed.MixedModuleStore', + 'OPTIONS': { + 'mappings': {}, + 'stores': { + 'default': { + 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', + 'OPTIONS': modulestore_options + } + } + } } } +MODULESTORE['direct'] = MODULESTORE['default'] + CONTENTSTORE = { 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', 'OPTIONS': { From 109d3c3d100f67fe2b49feecddd6573dcf37d027 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Wed, 21 Aug 2013 16:52:37 -0400 Subject: [PATCH 06/10] Refactored to remove test#XXX methods from ModuleStoreTestCase --- .../contentstore/tests/test_assets.py | 4 +-- .../contentstore/tests/test_contentstore.py | 30 ++++++++-------- .../tests/test_course_settings.py | 6 ++-- .../contentstore/tests/test_item.py | 2 +- .../contentstore/tests/test_textbooks.py | 22 ++++++------ .../contentstore/tests/test_users.py | 34 +++++++++---------- .../xmodule/modulestore/tests/django_utils.py | 2 +- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_assets.py b/cms/djangoapps/contentstore/tests/test_assets.py index b627237729..2f158cfda6 100644 --- a/cms/djangoapps/contentstore/tests/test_assets.py +++ b/cms/djangoapps/contentstore/tests/test_assets.py @@ -60,11 +60,11 @@ class UploadTestCase(CourseTestCase): f = BytesIO("sample content") f.name = "sample.txt" resp = self.client.post(self.url, {"name": "my-name", "file": f}) - self.assert2XX(resp.status_code) + self.assertEquals(resp.status_code, 200) def test_no_file(self): resp = self.client.post(self.url, {"name": "file.txt"}) - self.assert4XX(resp.status_code) + self.assertEquals(resp.status_code, 400) def test_get(self): resp = self.client.get(self.url) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 96b0b84e36..2e94b42476 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -1367,7 +1367,7 @@ class ContentStoreTest(ModuleStoreTestCase): 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) self.assertContains(resp, 'Chapter 2') # go to various pages @@ -1377,92 +1377,92 @@ class ContentStoreTest(ModuleStoreTestCase): kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # export page resp = self.client.get(reverse('export_course', kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # manage users resp = self.client.get(reverse('manage_users', kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # course info resp = self.client.get(reverse('course_info', kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # settings_details resp = self.client.get(reverse('settings_details', kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # settings_details resp = self.client.get(reverse('settings_grading', kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # static_pages resp = self.client.get(reverse('static_pages', kwargs={'org': loc.org, 'course': loc.course, 'coursename': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # static_pages resp = self.client.get(reverse('asset_index', kwargs={'org': loc.org, 'course': loc.course, 'name': loc.name})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # go look at a subsection page subsection_location = loc.replace(category='sequential', name='test_sequence') resp = self.client.get(reverse('edit_subsection', kwargs={'location': subsection_location.url()})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # go look at the Edit page unit_location = loc.replace(category='vertical', name='test_vertical') resp = self.client.get(reverse('edit_unit', kwargs={'location': unit_location.url()})) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # delete a component del_loc = loc.replace(category='html', name='test_html') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # delete a unit del_loc = loc.replace(category='vertical', name='test_vertical') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # delete a unit del_loc = loc.replace(category='sequential', name='test_sequence') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # delete a chapter del_loc = loc.replace(category='chapter', name='chapter_2') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) def test_import_into_new_course_id(self): module_store = modulestore('direct') diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 2007ba2f69..f413820aac 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -430,12 +430,12 @@ class CourseGraderUpdatesTest(CourseTestCase): def test_get(self): resp = self.client.get(self.url) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) obj = json.loads(resp.content) def test_delete(self): resp = self.client.delete(self.url) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) def test_post(self): grader = { @@ -446,5 +446,5 @@ class CourseGraderUpdatesTest(CourseTestCase): "weight": 17.3, } resp = self.client.post(self.url, grader) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) obj = json.loads(resp.content) diff --git a/cms/djangoapps/contentstore/tests/test_item.py b/cms/djangoapps/contentstore/tests/test_item.py index 260444a8f7..e5ff992cb8 100644 --- a/cms/djangoapps/contentstore/tests/test_item.py +++ b/cms/djangoapps/contentstore/tests/test_item.py @@ -34,7 +34,7 @@ class DeleteItem(CourseTestCase): resp.content, "application/json" ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) class TestCreateItem(CourseTestCase): diff --git a/cms/djangoapps/contentstore/tests/test_textbooks.py b/cms/djangoapps/contentstore/tests/test_textbooks.py index a21a1b1023..950d0f780e 100644 --- a/cms/djangoapps/contentstore/tests/test_textbooks.py +++ b/cms/djangoapps/contentstore/tests/test_textbooks.py @@ -23,7 +23,7 @@ class TextbookIndexTestCase(CourseTestCase): def test_view_index(self): "Basic check that the textbook index page responds correctly" resp = self.client.get(self.url) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # we don't have resp.context right now, # due to bugs in our testing harness :( if resp.context: @@ -36,7 +36,7 @@ class TextbookIndexTestCase(CourseTestCase): HTTP_ACCEPT="application/json", HTTP_X_REQUESTED_WITH='XMLHttpRequest' ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) obj = json.loads(resp.content) self.assertEqual(self.course.pdf_textbooks, obj) @@ -73,7 +73,7 @@ class TextbookIndexTestCase(CourseTestCase): HTTP_ACCEPT="application/json", HTTP_X_REQUESTED_WITH='XMLHttpRequest' ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) obj = json.loads(resp.content) self.assertEqual(content, obj) @@ -90,7 +90,7 @@ class TextbookIndexTestCase(CourseTestCase): HTTP_ACCEPT="application/json", HTTP_X_REQUESTED_WITH='XMLHttpRequest' ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) # reload course store = get_modulestore(self.course.location) @@ -111,7 +111,7 @@ class TextbookIndexTestCase(CourseTestCase): HTTP_ACCEPT="application/json", HTTP_X_REQUESTED_WITH='XMLHttpRequest' ) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) obj = json.loads(resp.content) self.assertIn("error", obj) @@ -184,7 +184,7 @@ class TextbookCreateTestCase(CourseTestCase): HTTP_ACCEPT="application/json", HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) self.assertNotIn("Location", resp) @@ -238,14 +238,14 @@ class TextbookByIdTestCase(CourseTestCase): def test_get_1(self): "Get the first textbook" resp = self.client.get(self.url1) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) compare = json.loads(resp.content) self.assertEqual(compare, self.textbook1) def test_get_2(self): "Get the second textbook" resp = self.client.get(self.url2) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) compare = json.loads(resp.content) self.assertEqual(compare, self.textbook2) @@ -257,7 +257,7 @@ class TextbookByIdTestCase(CourseTestCase): def test_delete(self): "Delete a textbook by ID" resp = self.client.delete(self.url1) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) course = self.store.get_item(self.course.location) self.assertEqual(course.pdf_textbooks, [self.textbook2]) @@ -288,7 +288,7 @@ class TextbookByIdTestCase(CourseTestCase): ) self.assertEqual(resp.status_code, 201) resp2 = self.client.get(url) - self.assert2XX(resp2.status_code) + self.assertEqual(resp2.status_code, 200) compare = json.loads(resp2.content) self.assertEqual(compare, textbook) course = self.store.get_item(self.course.location) @@ -311,7 +311,7 @@ class TextbookByIdTestCase(CourseTestCase): ) self.assertEqual(resp.status_code, 201) resp2 = self.client.get(self.url2) - self.assert2XX(resp2.status_code) + self.assertEqual(resp2.status_code, 200) compare = json.loads(resp2.content) self.assertEqual(compare, replacement) course = self.store.get_item(self.course.location) diff --git a/cms/djangoapps/contentstore/tests/test_users.py b/cms/djangoapps/contentstore/tests/test_users.py index cbb8aa8b01..80b2364c43 100644 --- a/cms/djangoapps/contentstore/tests/test_users.py +++ b/cms/djangoapps/contentstore/tests/test_users.py @@ -72,13 +72,13 @@ class UsersTestCase(CourseTestCase): def test_detail_inactive(self): resp = self.client.get(self.inactive_detail_url) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 200) result = json.loads(resp.content) self.assertFalse(result["active"]) def test_detail_invalid(self): resp = self.client.get(self.invalid_detail_url) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 404) result = json.loads(resp.content) self.assertIn("error", result) @@ -87,7 +87,7 @@ class UsersTestCase(CourseTestCase): self.detail_url, data={"role": None}, ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -103,7 +103,7 @@ class UsersTestCase(CourseTestCase): content_type="application/json", HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -122,7 +122,7 @@ class UsersTestCase(CourseTestCase): content_type="application/json", HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -142,7 +142,7 @@ class UsersTestCase(CourseTestCase): content_type="application/json", HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -157,7 +157,7 @@ class UsersTestCase(CourseTestCase): content_type="application/json", HTTP_ACCEPT="application/json", ) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) result = json.loads(resp.content) self.assertIn("error", result) self.assert_not_enrolled() @@ -169,7 +169,7 @@ class UsersTestCase(CourseTestCase): content_type="application/json", HTTP_ACCEPT="application/json", ) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) result = json.loads(resp.content) self.assertIn("error", result) self.assert_not_enrolled() @@ -180,7 +180,7 @@ class UsersTestCase(CourseTestCase): data={"role": "staff"}, HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -197,7 +197,7 @@ class UsersTestCase(CourseTestCase): self.detail_url, HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -214,7 +214,7 @@ class UsersTestCase(CourseTestCase): self.detail_url, HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) groups = [g.name for g in ext_user.groups.all()] @@ -273,7 +273,7 @@ class UsersTestCase(CourseTestCase): data={"role": "instructor"}, HTTP_ACCEPT="application/json", ) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) result = json.loads(resp.content) self.assertIn("error", result) @@ -288,7 +288,7 @@ class UsersTestCase(CourseTestCase): data={"role": "instructor"}, HTTP_ACCEPT="application/json", ) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) result = json.loads(resp.content) self.assertIn("error", result) @@ -306,7 +306,7 @@ class UsersTestCase(CourseTestCase): }) resp = self.client.delete(self_url) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) # reload user from DB user = User.objects.get(email=self.user.email) groups = [g.name for g in user.groups.all()] @@ -321,7 +321,7 @@ class UsersTestCase(CourseTestCase): self.ext_user.save() resp = self.client.delete(self.detail_url) - self.assert4XX(resp.status_code) + self.assertEqual(resp.status_code, 400) result = json.loads(resp.content) self.assertIn("error", result) # reload user from DB @@ -347,7 +347,7 @@ class UsersTestCase(CourseTestCase): self.detail_url, HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) self.assert_enrolled() def test_staff_to_instructor_still_enrolled(self): @@ -366,7 +366,7 @@ class UsersTestCase(CourseTestCase): content_type="application/json", HTTP_ACCEPT="application/json", ) - self.assert2XX(resp.status_code) + self.assertEqual(resp.status_code, 204) self.assert_enrolled() def assert_not_enrolled(self): diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index dabdd00e43..00e34ce41a 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -1,5 +1,5 @@ """ -eoduleStore configuration for test cases. +Modulestore configuration for test cases. """ from uuid import uuid4 From 8165a033b143c0c14a1d4adac54b37637c6b346d Mon Sep 17 00:00:00 2001 From: Will Daly Date: Wed, 21 Aug 2013 19:42:59 -0400 Subject: [PATCH 07/10] Pep8/pylint fixes Fixed test_masquerade failure due to not clearing the modulestore between tests. --- common/djangoapps/course_groups/tests/tests.py | 2 +- common/djangoapps/external_auth/tests/test_shib.py | 2 +- common/lib/xmodule/xmodule/js/libpeerconnection.log | 0 common/lib/xmodule/xmodule/modulestore/django.py | 3 +-- .../xmodule/xmodule/modulestore/tests/django_utils.py | 3 +-- lms/djangoapps/courseware/tests/modulestore_config.py | 8 ++++++-- lms/djangoapps/courseware/tests/test_masquerade.py | 9 +++++++-- lms/djangoapps/courseware/tests/tests.py | 6 +++--- lms/djangoapps/instructor/tests/test_access.py | 1 + lms/djangoapps/instructor/tests/test_legacy_xss.py | 1 + lms/djangoapps/staticbook/tests.py | 1 + 11 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 common/lib/xmodule/xmodule/js/libpeerconnection.log diff --git a/common/djangoapps/course_groups/tests/tests.py b/common/djangoapps/course_groups/tests/tests.py index debdc68c26..a17df56a71 100644 --- a/common/djangoapps/course_groups/tests/tests.py +++ b/common/djangoapps/course_groups/tests/tests.py @@ -17,7 +17,7 @@ from xmodule.modulestore.tests.django_utils import mixed_store_config # cms.envs.test doesn't. TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT -TEST_MAPPING = { 'edX/toy/2012_Fall': 'xml' } +TEST_MAPPING = {'edX/toy/2012_Fall': 'xml'} TEST_DATA_MIXED_MODULESTORE = mixed_store_config(TEST_DATA_DIR, TEST_MAPPING) diff --git a/common/djangoapps/external_auth/tests/test_shib.py b/common/djangoapps/external_auth/tests/test_shib.py index 187acdb595..d48948c6ae 100644 --- a/common/djangoapps/external_auth/tests/test_shib.py +++ b/common/djangoapps/external_auth/tests/test_shib.py @@ -18,7 +18,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.inheritance import own_metadata from xmodule.modulestore.django import editable_modulestore -from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from external_auth.models import ExternalAuthMap from external_auth.views import shib_login, course_specific_login, course_specific_register diff --git a/common/lib/xmodule/xmodule/js/libpeerconnection.log b/common/lib/xmodule/xmodule/js/libpeerconnection.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py index adafbc1253..b239e5f1d4 100644 --- a/common/lib/xmodule/xmodule/modulestore/django.py +++ b/common/lib/xmodule/xmodule/modulestore/django.py @@ -103,10 +103,9 @@ def editable_modulestore(name='default'): store = store.modulestores['default'] # At this point, we either have the ability to create - # items in the store, or we do not. + # items in the store, or we do not. if hasattr(store, 'create_xmodule'): return store else: return None - diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 00e34ce41a..e7b0b98824 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -5,8 +5,7 @@ Modulestore configuration for test cases. from uuid import uuid4 from django.test import TestCase from xmodule.modulestore.django import editable_modulestore, \ - editable_modulestore, clear_existing_modulestores -from unittest.util import safe_repr + clear_existing_modulestores def mixed_store_config(data_dir, mappings): diff --git a/lms/djangoapps/courseware/tests/modulestore_config.py b/lms/djangoapps/courseware/tests/modulestore_config.py index e4ee86878f..74fd3da57f 100644 --- a/lms/djangoapps/courseware/tests/modulestore_config.py +++ b/lms/djangoapps/courseware/tests/modulestore_config.py @@ -1,6 +1,10 @@ +""" +Define test configuration for modulestores. +""" + from xmodule.modulestore.tests.django_utils import xml_store_config, \ - mongo_store_config, draft_mongo_store_config,\ - mixed_store_config + mongo_store_config, draft_mongo_store_config,\ + mixed_store_config from django.conf import settings diff --git a/lms/djangoapps/courseware/tests/test_masquerade.py b/lms/djangoapps/courseware/tests/test_masquerade.py index 3122dc6477..0ec320b605 100644 --- a/lms/djangoapps/courseware/tests/test_masquerade.py +++ b/lms/djangoapps/courseware/tests/test_masquerade.py @@ -16,17 +16,22 @@ from django.contrib.auth.models import Group, User from courseware.access import _course_staff_group_name from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.django import modulestore, clear_existing_modulestores import json @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) -class TestStaffMasqueradeAsStudent(LoginEnrollmentTestCase): +class TestStaffMasqueradeAsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Check for staff being able to masquerade as student. """ def setUp(self): + + # Clear out the modulestores, causing them to reload + clear_existing_modulestores() + self.graded_course = modulestore().get_course("edX/graded/2012_Fall") # Create staff account diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index 995c7a352c..4486a6a032 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -64,9 +64,9 @@ class PageLoaderTestCase(LoginEnrollmentTestCase): ) items = store.get_items( - location_query, - course_id=course_id, - depth=2 + location_query, + course_id=course_id, + depth=2 ) if len(items) < 1: diff --git a/lms/djangoapps/instructor/tests/test_access.py b/lms/djangoapps/instructor/tests/test_access.py index ee2e91f766..1874e88f22 100644 --- a/lms/djangoapps/instructor/tests/test_access.py +++ b/lms/djangoapps/instructor/tests/test_access.py @@ -85,6 +85,7 @@ class TestInstructorAccessAllow(ModuleStoreTestCase): group = Group.objects.get(name=get_access_group_name(self.course, 'staff')) self.assertIn(user, group.user_set.all()) + @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestInstructorAccessRevoke(ModuleStoreTestCase): """ Test access revoke. """ diff --git a/lms/djangoapps/instructor/tests/test_legacy_xss.py b/lms/djangoapps/instructor/tests/test_legacy_xss.py index 784838fc4c..d748876032 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_xss.py +++ b/lms/djangoapps/instructor/tests/test_legacy_xss.py @@ -14,6 +14,7 @@ from xmodule.modulestore.tests.factories import CourseFactory from instructor.views import legacy + @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestXss(ModuleStoreTestCase): def setUp(self): diff --git a/lms/djangoapps/staticbook/tests.py b/lms/djangoapps/staticbook/tests.py index c18b3663e7..135150a2d1 100644 --- a/lms/djangoapps/staticbook/tests.py +++ b/lms/djangoapps/staticbook/tests.py @@ -36,6 +36,7 @@ HTML_BOOK = { ], } + @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class StaticBookTest(ModuleStoreTestCase): """ From 078ad4b25e2dd51ada41422a974ba130991655bd Mon Sep 17 00:00:00 2001 From: Will Daly Date: Wed, 21 Aug 2013 20:31:23 -0400 Subject: [PATCH 08/10] Added comment justifying ModuleStoreTestCase design. --- .../xmodule/modulestore/tests/django_utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index e7b0b98824..1f856d7eba 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -131,6 +131,22 @@ class ModuleStoreTestCase(TestCase): 3. Use factories (e.g. `CourseFactory`, `ItemFactory`) to populate the modulestore with test data. + + NOTE: + * For Mongo-backed courses (created with `CourseFactory`), + the state of the course will be reset before/after each + test method executes. + + * For XML-backed courses, the course state will NOT + reset between test methods (although it will reset + between test classes) + + The reason is: XML courses are not editable, so to reset + a course you have to reload it from disk, which is slow. + + If you do need to reset an XML course, use + `clear_existing_modulestores()` directly in + your `setUp()` method. """ @staticmethod From 736b3e0ecdf3ef66b70bcadafbc4a687ce29bb99 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Thu, 22 Aug 2013 14:06:13 -0400 Subject: [PATCH 09/10] Common djangoapps no longer access courseware; other cleanup --- common/djangoapps/external_auth/tests/test_shib.py | 6 +++--- lms/djangoapps/instructor/tests/test_hint_manager.py | 2 +- .../instructor/tests/test_legacy_download_csv.py | 8 ++++---- .../instructor/tests/test_legacy_forum_admin.py | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common/djangoapps/external_auth/tests/test_shib.py b/common/djangoapps/external_auth/tests/test_shib.py index d48948c6ae..0355730256 100644 --- a/common/djangoapps/external_auth/tests/test_shib.py +++ b/common/djangoapps/external_auth/tests/test_shib.py @@ -14,12 +14,10 @@ from django.contrib.auth.models import AnonymousUser, User from django.utils.importlib import import_module from xmodule.modulestore.tests.factories import CourseFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, mixed_store_config from xmodule.modulestore.inheritance import own_metadata from xmodule.modulestore.django import editable_modulestore -from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE - from external_auth.models import ExternalAuthMap from external_auth.views import shib_login, course_specific_login, course_specific_register @@ -27,6 +25,8 @@ from student.views import create_account, change_enrollment from student.models import UserProfile, Registration, CourseEnrollment from student.tests.factories import UserFactory +TEST_DATA_MIXED_MODULESTORE = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {}) + # Shib is supposed to provide 'REMOTE_USER', 'givenName', 'sn', 'mail', 'Shib-Identity-Provider' # attributes via request.META. We can count on 'Shib-Identity-Provider', and 'REMOTE_USER' being present # b/c of how mod_shib works but should test the behavior with the rest of the attributes present/missing diff --git a/lms/djangoapps/instructor/tests/test_hint_manager.py b/lms/djangoapps/instructor/tests/test_hint_manager.py index 3b124f1c99..456f8e0ed8 100644 --- a/lms/djangoapps/instructor/tests/test_hint_manager.py +++ b/lms/djangoapps/instructor/tests/test_hint_manager.py @@ -5,7 +5,7 @@ from django.test.utils import override_settings from courseware.models import XModuleContentField from courseware.tests.factories import ContentFactory -from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE +from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE import instructor.hint_manager as view from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase diff --git a/lms/djangoapps/instructor/tests/test_legacy_download_csv.py b/lms/djangoapps/instructor/tests/test_legacy_download_csv.py index b77626c8a1..c65547e408 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_download_csv.py +++ b/lms/djangoapps/instructor/tests/test_legacy_download_csv.py @@ -18,19 +18,19 @@ from django.core.urlresolvers import reverse from courseware.access import _course_staff_group_name from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.django import modulestore, clear_existing_modulestores import xmodule.modulestore.django @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) -class TestInstructorDashboardGradeDownloadCSV(LoginEnrollmentTestCase): +class TestInstructorDashboardGradeDownloadCSV(ModuleStoreTestCase, LoginEnrollmentTestCase): ''' Check for download of csv ''' def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} - + clear_existing_modulestores() self.toy = modulestore().get_course("edX/toy/2012_Fall") # Create two accounts diff --git a/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py b/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py index 3b691aa708..29046b151f 100644 --- a/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py +++ b/lms/djangoapps/instructor/tests/test_legacy_forum_admin.py @@ -16,8 +16,8 @@ from django_comment_client.utils import has_forum_access from courseware.access import _course_staff_group_name from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -from xmodule.modulestore.django import modulestore -import xmodule.modulestore.django +from xmodule.modulestore.django import modulestore, clear_existing_modulestores +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase FORUM_ROLES = [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA] @@ -33,13 +33,13 @@ def action_name(operation, rolename): @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) -class TestInstructorDashboardForumAdmin(LoginEnrollmentTestCase): +class TestInstructorDashboardForumAdmin(ModuleStoreTestCase, LoginEnrollmentTestCase): ''' Check for change in forum admin role memberships ''' def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} + clear_existing_modulestores() courses = modulestore().get_courses() self.course_id = "edX/toy/2012_Fall" From 1cb52df16b4ea05828128fe9fdbef4caf792d454 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Thu, 22 Aug 2013 16:10:24 -0400 Subject: [PATCH 10/10] Removed unnecessary TestCase --- lms/djangoapps/courseware/tests/tests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index 4486a6a032..98bcba4ed0 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -1,7 +1,6 @@ """ Test for LMS courseware app. """ -from django.test import TestCase from django.core.urlresolvers import reverse from django.test.utils import override_settings @@ -167,7 +166,7 @@ class TestMongoCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase): @override_settings(MODULESTORE=TEST_DATA_DRAFT_MONGO_MODULESTORE) -class TestDraftModuleStore(ModuleStoreTestCase, TestCase): +class TestDraftModuleStore(ModuleStoreTestCase): def test_get_items_with_course_items(self): store = modulestore()