Commit ce466619 by Nimisha Asthagiri

Add SampleCourseFactory and ToyCourseFactory

parent 16ab4f43
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
""" """
Modulestore configuration for test cases. Modulestore configuration for test cases.
""" """
import datetime
import functools import functools
import pytz
from uuid import uuid4 from uuid import uuid4
from mock import patch from mock import patch
...@@ -22,7 +20,6 @@ from xmodule.contentstore.django import _CONTENTSTORE ...@@ -22,7 +20,6 @@ from xmodule.contentstore.django import _CONTENTSTORE
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore, clear_existing_modulestores 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.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 from xmodule.modulestore.tests.factories import XMODULE_FACTORY_LOCK
...@@ -445,93 +442,3 @@ class ModuleStoreTestCase(TestCase): ...@@ -445,93 +442,3 @@ class ModuleStoreTestCase(TestCase):
self.store.update_item(course, user_id) self.store.update_item(course, user_id)
updated_course = self.store.get_course(course.id) updated_course = self.store.get_course(course.id)
return updated_course 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": "<a href='/static/handouts/sample_handout.txt'>Sample</a>"}
)
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
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
Factories for use in tests of XBlocks. Factories for use in tests of XBlocks.
""" """
import datetime
import functools import functools
import pymongo.message import pymongo.message
import pytz
import threading import threading
import traceback import traceback
from collections import defaultdict from collections import defaultdict
...@@ -20,6 +22,7 @@ from opaque_keys.edx.locations import Location ...@@ -20,6 +22,7 @@ from opaque_keys.edx.locations import Location
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from xblock.core import XBlock from xblock.core import XBlock
from xmodule.modulestore import prefer_xmodules, ModuleStoreEnum 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.tabs import CourseTab
from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT
...@@ -134,6 +137,110 @@ class CourseFactory(XModuleFactory): ...@@ -134,6 +137,110 @@ class CourseFactory(XModuleFactory):
return new_course 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": "<a href='/static/handouts/sample_handout.txt'>Sample</a>"}
)
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): class LibraryFactory(XModuleFactory):
""" """
Factory for creating a content library Factory for creating a content library
......
...@@ -47,7 +47,7 @@ from xmodule.lti_module import LTIDescriptor ...@@ -47,7 +47,7 @@ from xmodule.lti_module import LTIDescriptor
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase 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 xmodule.x_module import XModuleDescriptor, XModule, STUDENT_VIEW, CombinedSystem
from openedx.core.djangoapps.credit.models import CreditCourse from openedx.core.djangoapps.credit.models import CreditCourse
...@@ -127,7 +127,7 @@ class ModuleRenderTestCase(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -127,7 +127,7 @@ class ModuleRenderTestCase(ModuleStoreTestCase, LoginEnrollmentTestCase):
""" """
super(ModuleRenderTestCase, self).setUp() 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.toy_course = modulestore().get_course(self.course_key)
self.mock_user = UserFactory() self.mock_user = UserFactory()
self.mock_user.id = 1 self.mock_user.id = 1
...@@ -403,7 +403,7 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -403,7 +403,7 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase):
def setUp(self): def setUp(self):
super(TestHandleXBlockCallback, self).setUp() 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.location = self.course_key.make_usage_key('chapter', 'Overview')
self.toy_course = modulestore().get_course(self.course_key) self.toy_course = modulestore().get_course(self.course_key)
self.mock_user = UserFactory.create() self.mock_user = UserFactory.create()
...@@ -602,8 +602,11 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -602,8 +602,11 @@ class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase):
@ddt.ddt @ddt.ddt
class TestTOC(ModuleStoreTestCase): class TestTOC(ModuleStoreTestCase):
"""Check the Table of Contents for a course""" """Check the Table of Contents for a course"""
def setup_modulestore(self, default_ms, num_finds, num_sends): def setup_request_and_course(self, num_finds, num_sends):
self.course_key = self.create_toy_course() """
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' self.chapter = 'Overview'
chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter) chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter)
factory = RequestFactory() factory = RequestFactory()
...@@ -612,9 +615,9 @@ class TestTOC(ModuleStoreTestCase): ...@@ -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 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 self.modulestore.bulk_operations(self.course_key):
with check_mongo_calls(num_finds, num_sends): 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.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: # Mongo makes 3 queries to load the course to depth 2:
...@@ -632,7 +635,7 @@ class TestTOC(ModuleStoreTestCase): ...@@ -632,7 +635,7 @@ class TestTOC(ModuleStoreTestCase):
@ddt.unpack @ddt.unpack
def test_toc_toy_from_chapter(self, default_ms, setup_finds, setup_sends, toc_finds): def test_toc_toy_from_chapter(self, default_ms, setup_finds, setup_sends, toc_finds):
with self.store.default_store(default_ms): 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': expected = ([{'active': True, 'sections':
[{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True,
...@@ -672,7 +675,7 @@ class TestTOC(ModuleStoreTestCase): ...@@ -672,7 +675,7 @@ class TestTOC(ModuleStoreTestCase):
@ddt.unpack @ddt.unpack
def test_toc_toy_from_section(self, default_ms, setup_finds, setup_sends, toc_finds): def test_toc_toy_from_section(self, default_ms, setup_finds, setup_sends, toc_finds):
with self.store.default_store(default_ms): 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' section = 'Welcome'
expected = ([{'active': True, 'sections': expected = ([{'active': True, 'sections':
[{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True,
...@@ -707,7 +710,7 @@ class TestProctoringRendering(ModuleStoreTestCase): ...@@ -707,7 +710,7 @@ class TestProctoringRendering(ModuleStoreTestCase):
Set up the initial mongo datastores Set up the initial mongo datastores
""" """
super(TestProctoringRendering, self).setUp() super(TestProctoringRendering, self).setUp()
self.course_key = self.create_toy_course() self.course_key = ToyCourseFactory.create().id
self.chapter = 'Overview' self.chapter = 'Overview'
chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter) chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter)
factory = RequestFactory() factory = RequestFactory()
...@@ -715,9 +718,9 @@ class TestProctoringRendering(ModuleStoreTestCase): ...@@ -715,9 +718,9 @@ class TestProctoringRendering(ModuleStoreTestCase):
self.request.user = UserFactory() self.request.user = UserFactory()
self.modulestore = self.store._get_modulestore_for_courselike(self.course_key) # pylint: disable=protected-access, attribute-defined-outside-init 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 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.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( @ddt.data(
...@@ -1475,7 +1478,7 @@ class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -1475,7 +1478,7 @@ class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase):
def setUp(self): def setUp(self):
super(TestAnonymousStudentId, self).setUp(create_user=False) super(TestAnonymousStudentId, self).setUp(create_user=False)
self.user = UserFactory() self.user = UserFactory()
self.course_key = self.create_toy_course() self.course_key = ToyCourseFactory.create().id
self.course = modulestore().get_course(self.course_key) self.course = modulestore().get_course(self.course_key)
@patch('courseware.module_render.has_access', Mock(return_value=True)) @patch('courseware.module_render.has_access', Mock(return_value=True))
......
...@@ -5,7 +5,7 @@ import ddt ...@@ -5,7 +5,7 @@ import ddt
from xblock.validation import ValidationMessage from xblock.validation import ValidationMessage
from xmodule.modulestore import ModuleStoreEnum 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.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_TOY_MODULESTORE
from xmodule.partitions.partitions import Group, UserPartition from xmodule.partitions.partitions import Group, UserPartition
...@@ -169,7 +169,7 @@ class XBlockGetParentTest(LmsXBlockMixinTestCase): ...@@ -169,7 +169,7 @@ class XBlockGetParentTest(LmsXBlockMixinTestCase):
if modulestore_type == 'xml': if modulestore_type == 'xml':
course_key = self.store.make_course_key('edX', 'toy', '2012_Fall') course_key = self.store.make_course_key('edX', 'toy', '2012_Fall')
else: 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) course = self.store.get_course(course_key)
self.assertIsNone(course.get_parent()) self.assertIsNone(course.get_parent())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment