diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
index 9d80d29bd1..c0feac00fa 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
@@ -2,9 +2,7 @@
"""
Modulestore configuration for test cases.
"""
-import datetime
import functools
-import pytz
from uuid import uuid4
from mock import patch
@@ -22,7 +20,6 @@ from xmodule.contentstore.django import _CONTENTSTORE
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore, clear_existing_modulestores
from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST
-from xmodule.modulestore.tests.sample_courses import default_block_info_tree, TOY_BLOCK_INFO_TREE
from xmodule.modulestore.tests.factories import XMODULE_FACTORY_LOCK
@@ -445,93 +442,3 @@ class ModuleStoreTestCase(TestCase):
self.store.update_item(course, user_id)
updated_course = self.store.get_course(course.id)
return updated_course
-
- def create_sample_course(self, org, course, run, block_info_tree=None, course_fields=None):
- """
- create a course in the default modulestore from the collection of BlockInfo
- records defining the course tree
- Returns:
- course_loc: the CourseKey for the created course
- """
- if block_info_tree is None:
- block_info_tree = default_block_info_tree
-
- with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, None):
- course = self.store.create_course(org, course, run, self.user.id, fields=course_fields)
- self.course_loc = course.location # pylint: disable=attribute-defined-outside-init
-
- def create_sub_tree(parent_loc, block_info):
- """Recursively creates a sub_tree on this parent_loc with this block."""
- block = self.store.create_child(
- self.user.id,
- # TODO remove version_agnostic() when we impl the single transaction
- parent_loc.version_agnostic(),
- block_info.category, block_id=block_info.block_id,
- fields=block_info.fields,
- )
- for tree in block_info.sub_tree:
- create_sub_tree(block.location, tree)
- setattr(self, block_info.block_id, block.location.version_agnostic())
-
- for tree in block_info_tree:
- create_sub_tree(self.course_loc, tree)
-
- # remove version_agnostic when bulk write works
- self.store.publish(self.course_loc.version_agnostic(), self.user.id)
- return self.course_loc.course_key.version_agnostic()
-
- def create_toy_course(self, org='edX', course='toy', run='2012_Fall'):
- """
- Create an equivalent to the toy xml course
- """
- with self.store.bulk_operations(self.store.make_course_key(org, course, run), emit_signals=False):
- self.toy_loc = self.create_sample_course( # pylint: disable=attribute-defined-outside-init
- org, course, run, TOY_BLOCK_INFO_TREE,
- {
- "textbooks": [["Textbook", "https://s3.amazonaws.com/edx-textbooks/guttag_computation_v3/"]],
- "wiki_slug": "toy",
- "display_name": "Toy Course",
- "graded": True,
- "discussion_topics": {"General": {"id": "i4x-edX-toy-course-2012_Fall"}},
- "graceperiod": datetime.timedelta(days=2, seconds=21599),
- "start": datetime.datetime(2015, 07, 17, 12, tzinfo=pytz.utc),
- "xml_attributes": {"filename": ["course/2012_Fall.xml", "course/2012_Fall.xml"]},
- "pdf_textbooks": [
- {
- "tab_title": "Sample Multi Chapter Textbook",
- "id": "MyTextbook",
- "chapters": [
- {"url": "/static/Chapter1.pdf", "title": "Chapter 1"},
- {"url": "/static/Chapter2.pdf", "title": "Chapter 2"}
- ]
- }
- ],
- "course_image": "just_a_test.jpg",
- }
- )
- with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.toy_loc):
- self.store.create_item(
- self.user.id, self.toy_loc, "about", block_id="short_description",
- fields={"data": "A course about toys."}
- )
- self.store.create_item(
- self.user.id, self.toy_loc, "about", block_id="effort",
- fields={"data": "6 hours"}
- )
- self.store.create_item(
- self.user.id, self.toy_loc, "about", block_id="end_date",
- fields={"data": "TBD"}
- )
- self.store.create_item(
- self.user.id, self.toy_loc, "course_info", "handouts",
- fields={"data": "Sample"}
- )
- self.store.create_item(
- self.user.id, self.toy_loc, "static_tab", "resources",
- fields={"display_name": "Resources"},
- )
- self.store.create_item(
- self.user.id, self.toy_loc, "static_tab", "syllabus",
- fields={"display_name": "Syllabus"},
- )
- return self.toy_loc
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py
index 24f76048c2..85fac57f03 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py
@@ -2,8 +2,10 @@
Factories for use in tests of XBlocks.
"""
+import datetime
import functools
import pymongo.message
+import pytz
import threading
import traceback
from collections import defaultdict
@@ -20,6 +22,7 @@ from opaque_keys.edx.locations import Location
from opaque_keys.edx.keys import UsageKey
from xblock.core import XBlock
from xmodule.modulestore import prefer_xmodules, ModuleStoreEnum
+from xmodule.modulestore.tests.sample_courses import default_block_info_tree, TOY_BLOCK_INFO_TREE
from xmodule.tabs import CourseTab
from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT
@@ -134,6 +137,110 @@ class CourseFactory(XModuleFactory):
return new_course
+class SampleCourseFactory(CourseFactory):
+ """
+ Factory for sample courses using block_info_tree definitions.
+ """
+ # pylint: disable=unused-argument
+ @classmethod
+ def _create(cls, target_class, **kwargs):
+ """
+ Create and return a new sample course. See CourseFactory for customization kwargs.
+ """
+ block_info_tree = kwargs.pop('block_info_tree', default_block_info_tree)
+ store = kwargs.get('modulestore')
+ user_id = kwargs.get('user_id', ModuleStoreEnum.UserID.test)
+ with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, None):
+ course = super(SampleCourseFactory, cls)._create(target_class, **kwargs)
+
+ def create_sub_tree(parent_loc, block_info):
+ """Recursively creates a sub_tree on this parent_loc with this block."""
+ block = store.create_child(
+ user_id,
+ parent_loc,
+ block_info.category,
+ block_id=block_info.block_id,
+ fields=block_info.fields,
+ )
+ for tree in block_info.sub_tree:
+ create_sub_tree(block.location, tree)
+
+ for tree in block_info_tree:
+ create_sub_tree(course.location, tree)
+
+ store.publish(course.location, user_id)
+ return course
+
+
+class ToyCourseFactory(SampleCourseFactory):
+ """
+ Factory for sample course that is equivalent to the toy xml course.
+ """
+ org = 'edX'
+ course = 'toy'
+ run = '2012_Fall'
+ display_name = 'Toy Course'
+
+ # pylint: disable=unused-argument
+ @classmethod
+ def _create(cls, target_class, **kwargs):
+ """
+ Create and return a new toy course instance. See SampleCourseFactory for customization kwargs.
+ """
+ store = kwargs.get('modulestore')
+ user_id = kwargs.get('user_id', ModuleStoreEnum.UserID.test)
+ toy_course = super(ToyCourseFactory, cls)._create(
+ target_class,
+ block_info_tree=TOY_BLOCK_INFO_TREE,
+ textbooks=[["Textbook", "path/to/a/text_book"]],
+ wiki_slug="toy",
+ graded=True,
+ discussion_topics={"General": {"id": "i4x-edX-toy-course-2012_Fall"}},
+ graceperiod=datetime.timedelta(days=2, seconds=21599),
+ start=datetime.datetime(2015, 07, 17, 12, tzinfo=pytz.utc),
+ xml_attributes={"filename": ["course/2012_Fall.xml", "course/2012_Fall.xml"]},
+ pdf_textbooks=[
+ {
+ "tab_title": "Sample Multi Chapter Textbook",
+ "id": "MyTextbook",
+ "chapters": [
+ {"url": "/static/Chapter1.pdf", "title": "Chapter 1"},
+ {"url": "/static/Chapter2.pdf", "title": "Chapter 2"}
+ ]
+ }
+ ],
+ course_image="just_a_test.jpg",
+ **kwargs
+ )
+ with store.bulk_operations(toy_course.id, emit_signals=False):
+ with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, toy_course.id):
+ store.create_item(
+ user_id, toy_course.id, "about", block_id="short_description",
+ fields={"data": "A course about toys."}
+ )
+ store.create_item(
+ user_id, toy_course.id, "about", block_id="effort",
+ fields={"data": "6 hours"}
+ )
+ store.create_item(
+ user_id, toy_course.id, "about", block_id="end_date",
+ fields={"data": "TBD"}
+ )
+ store.create_item(
+ user_id, toy_course.id, "course_info", "handouts",
+ fields={"data": "Sample"}
+ )
+ store.create_item(
+ user_id, toy_course.id, "static_tab", "resources",
+ fields={"display_name": "Resources"},
+ )
+ store.create_item(
+ user_id, toy_course.id, "static_tab", "syllabus",
+ fields={"display_name": "Syllabus"},
+ )
+ return toy_course
+
+
class LibraryFactory(XModuleFactory):
"""
Factory for creating a content library
diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py
index 4afe1e86a3..cb673a0e68 100644
--- a/lms/djangoapps/courseware/tests/test_module_render.py
+++ b/lms/djangoapps/courseware/tests/test_module_render.py
@@ -47,7 +47,7 @@ from xmodule.lti_module import LTIDescriptor
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
-from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory, check_mongo_calls
+from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory, ToyCourseFactory, check_mongo_calls
from xmodule.x_module import XModuleDescriptor, XModule, STUDENT_VIEW, CombinedSystem
from openedx.core.djangoapps.credit.models import CreditCourse
@@ -127,7 +127,7 @@ class ModuleRenderTestCase(ModuleStoreTestCase, LoginEnrollmentTestCase):
"""
super(ModuleRenderTestCase, self).setUp()
- self.course_key = self.create_toy_course()
+ self.course_key = ToyCourseFactory.create().id
self.toy_course = modulestore().get_course(self.course_key)
self.mock_user = UserFactory()
self.mock_user.id = 1
@@ -403,7 +403,7 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase):
def setUp(self):
super(TestHandleXBlockCallback, self).setUp()
- self.course_key = self.create_toy_course()
+ self.course_key = ToyCourseFactory.create().id
self.location = self.course_key.make_usage_key('chapter', 'Overview')
self.toy_course = modulestore().get_course(self.course_key)
self.mock_user = UserFactory.create()
@@ -602,8 +602,11 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase):
@ddt.ddt
class TestTOC(ModuleStoreTestCase):
"""Check the Table of Contents for a course"""
- def setup_modulestore(self, default_ms, num_finds, num_sends):
- self.course_key = self.create_toy_course()
+ def setup_request_and_course(self, num_finds, num_sends):
+ """
+ Sets up the toy course in the modulestore and the request object.
+ """
+ self.course_key = ToyCourseFactory.create().id # pylint: disable=attribute-defined-outside-init
self.chapter = 'Overview'
chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter)
factory = RequestFactory()
@@ -612,9 +615,9 @@ class TestTOC(ModuleStoreTestCase):
self.modulestore = self.store._get_modulestore_for_courselike(self.course_key) # pylint: disable=protected-access, attribute-defined-outside-init
with self.modulestore.bulk_operations(self.course_key):
with check_mongo_calls(num_finds, num_sends):
- self.toy_course = self.store.get_course(self.toy_loc, depth=2)
+ self.toy_course = self.store.get_course(self.course_key, depth=2) # pylint: disable=attribute-defined-outside-init
self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
- self.toy_loc, self.request.user, self.toy_course, depth=2
+ self.course_key, self.request.user, self.toy_course, depth=2
)
# Mongo makes 3 queries to load the course to depth 2:
@@ -632,7 +635,7 @@ class TestTOC(ModuleStoreTestCase):
@ddt.unpack
def test_toc_toy_from_chapter(self, default_ms, setup_finds, setup_sends, toc_finds):
with self.store.default_store(default_ms):
- self.setup_modulestore(default_ms, setup_finds, setup_sends)
+ self.setup_request_and_course(setup_finds, setup_sends)
expected = ([{'active': True, 'sections':
[{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True,
@@ -672,7 +675,7 @@ class TestTOC(ModuleStoreTestCase):
@ddt.unpack
def test_toc_toy_from_section(self, default_ms, setup_finds, setup_sends, toc_finds):
with self.store.default_store(default_ms):
- self.setup_modulestore(default_ms, setup_finds, setup_sends)
+ self.setup_request_and_course(setup_finds, setup_sends)
section = 'Welcome'
expected = ([{'active': True, 'sections':
[{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True,
@@ -707,7 +710,7 @@ class TestProctoringRendering(ModuleStoreTestCase):
Set up the initial mongo datastores
"""
super(TestProctoringRendering, self).setUp()
- self.course_key = self.create_toy_course()
+ self.course_key = ToyCourseFactory.create().id
self.chapter = 'Overview'
chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter)
factory = RequestFactory()
@@ -715,9 +718,9 @@ class TestProctoringRendering(ModuleStoreTestCase):
self.request.user = UserFactory()
self.modulestore = self.store._get_modulestore_for_courselike(self.course_key) # pylint: disable=protected-access, attribute-defined-outside-init
with self.modulestore.bulk_operations(self.course_key):
- self.toy_course = self.store.get_course(self.toy_loc, depth=2)
+ self.toy_course = self.store.get_course(self.course_key, depth=2)
self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
- self.toy_loc, self.request.user, self.toy_course, depth=2
+ self.course_key, self.request.user, self.toy_course, depth=2
)
@ddt.data(
@@ -1475,7 +1478,7 @@ class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase):
def setUp(self):
super(TestAnonymousStudentId, self).setUp(create_user=False)
self.user = UserFactory()
- self.course_key = self.create_toy_course()
+ self.course_key = ToyCourseFactory.create().id
self.course = modulestore().get_course(self.course_key)
@patch('courseware.module_render.has_access', Mock(return_value=True))
diff --git a/lms/lib/xblock/test/test_mixin.py b/lms/lib/xblock/test/test_mixin.py
index 9a5cbc327b..cebf7d7a8e 100644
--- a/lms/lib/xblock/test/test_mixin.py
+++ b/lms/lib/xblock/test/test_mixin.py
@@ -5,7 +5,7 @@ import ddt
from xblock.validation import ValidationMessage
from xmodule.modulestore import ModuleStoreEnum
-from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
+from xmodule.modulestore.tests.factories import CourseFactory, ToyCourseFactory, ItemFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_TOY_MODULESTORE
from xmodule.partitions.partitions import Group, UserPartition
@@ -169,7 +169,7 @@ class XBlockGetParentTest(LmsXBlockMixinTestCase):
if modulestore_type == 'xml':
course_key = self.store.make_course_key('edX', 'toy', '2012_Fall')
else:
- course_key = self.create_toy_course('edX', 'toy', '2012_Fall_copy')
+ course_key = ToyCourseFactory.create(run='2012_Fall_copy').id
course = self.store.get_course(course_key)
self.assertIsNone(course.get_parent())