diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 49f846ee2b..1d71819f2d 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -8,8 +8,6 @@ from datetime import datetime import dateutil.parser from lazy import lazy -from opaque_keys.edx.locations import Location -from opaque_keys.edx.locator import UsageKey from xmodule.seq_module import SequenceDescriptor, SequenceModule from xmodule.graders import grader_from_conf from xmodule.tabs import CourseTabList @@ -17,7 +15,6 @@ import json from xblock.fields import Scope, List, String, Dict, Boolean, Integer from .fields import Date -from opaque_keys.edx.locator import CourseLocator from django.utils.timezone import UTC log = logging.getLogger(__name__) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index ad43e48afc..6d314684f9 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -12,6 +12,7 @@ from xmodule.modulestore import ModuleStoreEnum from collections import namedtuple import datetime import pytz +from xmodule.tabs import CoursewareTab, CourseInfoTab, StaticTab, DiscussionTab, ProgressTab, WikiTab def mixed_store_config(data_dir, mappings): @@ -91,7 +92,7 @@ def split_mongo_store_config(data_dir): store = { 'default': { 'NAME': 'draft', - 'ENGINE': 'xmodule.modulestore.split_mongo.split.SplitMongoModuleStore', + 'ENGINE': 'xmodule.modulestore.split_mongo.split_draft.DraftVersioningModuleStore', 'DOC_STORE_CONFIG': { 'host': 'localhost', 'db': 'test_xmodule', @@ -422,23 +423,6 @@ class ModuleStoreTestCase(TestCase): clear_existing_modulestores() TestCase.setUpClass() - @classmethod - def tearDownClass(cls): - """ - Drop the existing modulestores, causing them to be reloaded. - Clean up any data stored in Mongo. - """ - # Clean up by flushing the Mongo modulestore - cls.drop_mongo_collections() - - # 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() - - TestCase.tearDownClass() - def _pre_setup(self): """ Flush the ModuleStore. @@ -455,6 +439,11 @@ class ModuleStoreTestCase(TestCase): Flush the ModuleStore after each test. """ self.drop_mongo_collections() + # 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() # Call superclass implementation super(ModuleStoreTestCase, self)._post_teardown() @@ -501,13 +490,13 @@ class ModuleStoreTestCase(TestCase): "display_name" : "Toy Course", "graded" : True, "tabs" : [ - {"type" : "courseware", "name" : "Courseware"}, - {"type" : "course_info", "name" : "Course Info"}, - {"type" : "static_tab", "name" : "Syllabus", "url_slug" : "syllabus"}, - {"type" : "static_tab", "name" : "Resources", "url_slug" : "resources"}, - {"type" : "discussion", "name" : "Discussion"}, - {"type" : "wiki", "name" : "Wiki"}, - {"type" : "progress", "name" : "Progress"} + CoursewareTab(), # {"type" : "courseware", "name" : "Courseware"}, + CourseInfoTab(), # {"type" : "course_info", "name" : "Course Info"}, + StaticTab(name="Syllabus", url_slug="syllabus"), + StaticTab(name="Resources", url_slug="resources"), + DiscussionTab(), + WikiTab(), + ProgressTab(), ], "discussion_topics" : {"General" : {"id" : "i4x-edX-toy-course-2012_Fall"}}, "graceperiod" : datetime.timedelta(days=2, seconds=21599), diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 6e2185c474..c950bf6740 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -1,7 +1,7 @@ """ Test for lms courseware app, module render unit """ -from ddt import ddt, data +import ddt from functools import partial from mock import MagicMock, patch, Mock import json @@ -20,7 +20,7 @@ from xblock.fields import ScopeIds from xmodule.lti_module import LTIDescriptor from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory +from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory, check_mongo_calls from xmodule.x_module import XModuleDescriptor, STUDENT_VIEW from opaque_keys.edx.locations import SlashSeparatedCourseKey @@ -38,6 +38,7 @@ from courseware.tests.test_submitting_problems import TestSubmittingProblems from student.models import anonymous_id_for_user from lms.lib.xblock.runtime import quote_slashes +from xmodule.modulestore import ModuleStoreEnum @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) @@ -313,61 +314,75 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase): ) +@ddt.ddt @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) class TestTOC(ModuleStoreTestCase): """Check the Table of Contents for a course""" - def setUp(self): - super(TestTOC, self).setUp() + def setup_modulestore(self, default_ms, num_finds, num_sends): self.course_key = self.create_toy_course() self.chapter = 'Overview' chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter) factory = RequestFactory() self.request = factory.get(chapter_url) self.request.user = UserFactory() - self.toy_course = self.store.get_course(self.toy_loc) - self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( - self.toy_loc, self.request.user, self.toy_course, depth=2) + self.modulestore = self.store._get_modulestore_for_courseid(self.course_key) + with check_mongo_calls(self.modulestore, num_finds, num_sends): + self.toy_course = self.store.get_course(self.toy_loc, depth=2) + self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( + self.toy_loc, self.request.user, self.toy_course, depth=2) - def test_toc_toy_from_chapter(self): - expected = ([{'active': True, 'sections': - [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, - 'format': u'Lecture Sequence', 'due': None, 'active': False}, - {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, - 'format': '', 'due': None, 'active': False}, - {'url_name': 'video_123456789012', 'display_name': 'Test Video', 'graded': True, - 'format': '', 'due': None, 'active': False}, - {'url_name': 'video_4f66f493ac8f', 'display_name': 'Video', 'graded': True, - 'format': '', 'due': None, 'active': False}], - 'url_name': 'Overview', 'display_name': u'Overview'}, - {'active': False, 'sections': - [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, - 'format': '', 'due': None, 'active': False}], - 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) - actual = render.toc_for_course(self.request.user, self.request, self.toy_course, self.chapter, None, self.field_data_cache) + @ddt.data((ModuleStoreEnum.Type.mongo, 3, 0), (ModuleStoreEnum.Type.split, 7, 0)) + @ddt.unpack + def test_toc_toy_from_chapter(self, default_ms, num_finds, num_sends): + with self.store.default_store(default_ms): + self.setup_modulestore(default_ms, num_finds, num_sends) + expected = ([{'active': True, 'sections': + [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, + 'format': u'Lecture Sequence', 'due': None, 'active': False}, + {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, + 'format': '', 'due': None, 'active': False}, + {'url_name': 'video_123456789012', 'display_name': 'Test Video', 'graded': True, + 'format': '', 'due': None, 'active': False}, + {'url_name': 'video_4f66f493ac8f', 'display_name': 'Video', 'graded': True, + 'format': '', 'due': None, 'active': False}], + 'url_name': 'Overview', 'display_name': u'Overview'}, + {'active': False, 'sections': + [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, + 'format': '', 'due': None, 'active': False}], + 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) + + with check_mongo_calls(self.modulestore, 0, 0): + actual = render.toc_for_course( + self.request.user, self.request, self.toy_course, self.chapter, None, self.field_data_cache + ) for toc_section in expected: self.assertIn(toc_section, actual) - def test_toc_toy_from_section(self): - section = 'Welcome' - expected = ([{'active': True, 'sections': - [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, - 'format': u'Lecture Sequence', 'due': None, 'active': False}, - {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, - 'format': '', 'due': None, 'active': True}, - {'url_name': 'video_123456789012', 'display_name': 'Test Video', 'graded': True, - 'format': '', 'due': None, 'active': False}, - {'url_name': 'video_4f66f493ac8f', 'display_name': 'Video', 'graded': True, - 'format': '', 'due': None, 'active': False}], - 'url_name': 'Overview', 'display_name': u'Overview'}, - {'active': False, 'sections': - [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, - 'format': '', 'due': None, 'active': False}], - 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) + @ddt.data((ModuleStoreEnum.Type.mongo, 3, 0), (ModuleStoreEnum.Type.split, 7, 0)) + @ddt.unpack + def test_toc_toy_from_section(self, default_ms, num_finds, num_sends): + with self.store.default_store(default_ms): + self.setup_modulestore(default_ms, num_finds, num_sends) + section = 'Welcome' + expected = ([{'active': True, 'sections': + [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, + 'format': u'Lecture Sequence', 'due': None, 'active': False}, + {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, + 'format': '', 'due': None, 'active': True}, + {'url_name': 'video_123456789012', 'display_name': 'Test Video', 'graded': True, + 'format': '', 'due': None, 'active': False}, + {'url_name': 'video_4f66f493ac8f', 'display_name': 'Video', 'graded': True, + 'format': '', 'due': None, 'active': False}], + 'url_name': 'Overview', 'display_name': u'Overview'}, + {'active': False, 'sections': + [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, + 'format': '', 'due': None, 'active': False}], + 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) - actual = render.toc_for_course(self.request.user, self.request, self.toy_course, self.chapter, section, self.field_data_cache) - for toc_section in expected: - self.assertIn(toc_section, actual) + actual = render.toc_for_course(self.request.user, self.request, self.toy_course, self.chapter, section, self.field_data_cache) + for toc_section in expected: + self.assertIn(toc_section, actual) @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) @@ -755,7 +770,7 @@ PER_STUDENT_ANONYMIZED_DESCRIPTORS = set( ) -@ddt +@ddt.ddt @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase): """ @@ -795,7 +810,7 @@ class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase): Mock(), # XQueue Callback Url Prefix ).xmodule_runtime.anonymous_student_id - @data(*PER_STUDENT_ANONYMIZED_DESCRIPTORS) + @ddt.data(*PER_STUDENT_ANONYMIZED_DESCRIPTORS) def test_per_student_anonymized_id(self, descriptor_class): for course_id in ('MITx/6.00x/2012_Fall', 'MITx/6.00x/2013_Spring'): self.assertEquals( @@ -805,7 +820,7 @@ class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase): self._get_anonymous_id(SlashSeparatedCourseKey.from_deprecated_string(course_id), descriptor_class) ) - @data(*PER_COURSE_ANONYMIZED_DESCRIPTORS) + @ddt.data(*PER_COURSE_ANONYMIZED_DESCRIPTORS) def test_per_course_anonymized_id(self, descriptor_class): self.assertEquals( # This value is set by observation, so that later changes to the student