Refactor the test_crud file.
Move Split-specific tests to test_split_modulestore.py. Derive remaining tests from ModuleStoreTestCase. Remove unused persistent_factory.py.
This commit is contained in:
@@ -1,91 +0,0 @@
|
||||
"""Provides factories for Split."""
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.course_module import CourseDescriptor
|
||||
from xmodule.x_module import XModuleDescriptor
|
||||
import factory
|
||||
from factory.helpers import lazy_attribute
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
# Factories are self documenting
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
|
||||
class SplitFactory(factory.Factory):
|
||||
"""
|
||||
Abstracted superclass which defines modulestore so that there's no dependency on django
|
||||
if the caller passes modulestore in kwargs
|
||||
"""
|
||||
@lazy_attribute
|
||||
def modulestore(self):
|
||||
# Delayed import so that we only depend on django if the caller
|
||||
# hasn't provided their own modulestore
|
||||
from xmodule.modulestore.django import modulestore
|
||||
return modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.split)
|
||||
|
||||
|
||||
class PersistentCourseFactory(SplitFactory):
|
||||
"""
|
||||
Create a new course (not a new version of a course, but a whole new index entry).
|
||||
|
||||
keywords: any xblock field plus (note, the below are filtered out; so, if they
|
||||
become legitimate xblock fields, they won't be settable via this factory)
|
||||
* org: defaults to textX
|
||||
* master_branch: (optional) defaults to ModuleStoreEnum.BranchName.draft
|
||||
* user_id: (optional) defaults to 'test_user'
|
||||
* display_name (xblock field): will default to 'Robot Super Course' unless provided
|
||||
"""
|
||||
FACTORY_FOR = CourseDescriptor
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@classmethod
|
||||
def _create(cls, target_class, course='999', run='run', org='testX', user_id=ModuleStoreEnum.UserID.test,
|
||||
master_branch=ModuleStoreEnum.BranchName.draft, **kwargs):
|
||||
|
||||
modulestore = kwargs.pop('modulestore')
|
||||
root_block_id = kwargs.pop('root_block_id', 'course')
|
||||
# Write the data to the mongo datastore
|
||||
new_course = modulestore.create_course(
|
||||
org, course, run, user_id, fields=kwargs,
|
||||
master_branch=master_branch, root_block_id=root_block_id
|
||||
)
|
||||
|
||||
return new_course
|
||||
|
||||
@classmethod
|
||||
def _build(cls, target_class, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class ItemFactory(SplitFactory):
|
||||
FACTORY_FOR = XModuleDescriptor
|
||||
|
||||
display_name = factory.LazyAttributeSequence(lambda o, n: "{} {}".format(o.category, n))
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@classmethod
|
||||
def _create(cls, target_class, parent_location, category='chapter',
|
||||
user_id=ModuleStoreEnum.UserID.test, definition_locator=None, force=False,
|
||||
continue_version=False, **kwargs):
|
||||
"""
|
||||
passes *kwargs* as the new item's field values:
|
||||
|
||||
:param parent_location: (required) the location of the course & possibly parent
|
||||
|
||||
:param category: (defaults to 'chapter')
|
||||
|
||||
:param definition_locator (optional): the DescriptorLocator for the definition this uses or branches
|
||||
"""
|
||||
modulestore = kwargs.pop('modulestore')
|
||||
if isinstance(parent_location, UsageKey):
|
||||
return modulestore.create_child(
|
||||
user_id, parent_location, category, defintion_locator=definition_locator,
|
||||
force=force, continue_version=continue_version, **kwargs
|
||||
)
|
||||
else:
|
||||
return modulestore.create_item(
|
||||
user_id, parent_location, category, defintion_locator=definition_locator,
|
||||
force=force, continue_version=continue_version, **kwargs
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _build(cls, target_class, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
@@ -772,6 +772,122 @@ class SplitModuleCourseTests(SplitModuleTest):
|
||||
self.assertEqual(len(result.children[0].children), 1)
|
||||
self.assertEqual(result.children[0].children[0].locator.version_guid, versions[0])
|
||||
|
||||
@patch('xmodule.tabs.CourseTab.from_json', side_effect=mock_tab_from_json)
|
||||
def test_persist_dag(self, _from_json):
|
||||
"""
|
||||
try saving temporary xblocks
|
||||
"""
|
||||
test_course = modulestore().create_course(
|
||||
course='course', run='2014', org='testx',
|
||||
display_name='fun test course', user_id='testbot',
|
||||
master_branch=ModuleStoreEnum.BranchName.draft
|
||||
)
|
||||
test_chapter = modulestore().create_xblock(
|
||||
test_course.system, test_course.id, 'chapter', fields={'display_name': 'chapter n'},
|
||||
parent_xblock=test_course
|
||||
)
|
||||
self.assertEqual(test_chapter.display_name, 'chapter n')
|
||||
test_def_content = '<problem>boo</problem>'
|
||||
# create child
|
||||
new_block = modulestore().create_xblock(
|
||||
test_course.system, test_course.id,
|
||||
'problem',
|
||||
fields={
|
||||
'data': test_def_content,
|
||||
'display_name': 'problem'
|
||||
},
|
||||
parent_xblock=test_chapter
|
||||
)
|
||||
self.assertIsNotNone(new_block.definition_locator)
|
||||
self.assertTrue(isinstance(new_block.definition_locator.definition_id, LocalId))
|
||||
# better to pass in persisted parent over the subdag so
|
||||
# subdag gets the parent pointer (otherwise 2 ops, persist dag, update parent children,
|
||||
# persist parent
|
||||
persisted_course = modulestore().persist_xblock_dag(test_course, 'testbot')
|
||||
self.assertEqual(len(persisted_course.children), 1)
|
||||
persisted_chapter = persisted_course.get_children()[0]
|
||||
self.assertEqual(persisted_chapter.category, 'chapter')
|
||||
self.assertEqual(persisted_chapter.display_name, 'chapter n')
|
||||
self.assertEqual(len(persisted_chapter.children), 1)
|
||||
persisted_problem = persisted_chapter.get_children()[0]
|
||||
self.assertEqual(persisted_problem.category, 'problem')
|
||||
self.assertEqual(persisted_problem.data, test_def_content)
|
||||
# update it
|
||||
persisted_problem.display_name = 'altered problem'
|
||||
persisted_problem = modulestore().update_item(persisted_problem, 'testbot')
|
||||
self.assertEqual(persisted_problem.display_name, 'altered problem')
|
||||
|
||||
@patch('xmodule.tabs.CourseTab.from_json', side_effect=mock_tab_from_json)
|
||||
def test_block_generations(self, _from_json):
|
||||
"""
|
||||
Test get_block_generations
|
||||
"""
|
||||
test_course = modulestore().create_course(
|
||||
org='edu.harvard',
|
||||
course='history',
|
||||
run='hist101',
|
||||
display_name='history test course',
|
||||
user_id='testbot',
|
||||
master_branch=ModuleStoreEnum.BranchName.draft
|
||||
)
|
||||
chapter = modulestore().create_child(
|
||||
None, test_course.location,
|
||||
block_type='chapter',
|
||||
block_id='chapter1',
|
||||
fields={'display_name': 'chapter 1'}
|
||||
)
|
||||
sub = modulestore().create_child(
|
||||
None, chapter.location,
|
||||
block_type='vertical',
|
||||
block_id='subsection1',
|
||||
fields={'display_name': 'subsection 1'}
|
||||
)
|
||||
first_problem = modulestore().create_child(
|
||||
None, sub.location,
|
||||
block_type='problem',
|
||||
block_id='problem1',
|
||||
fields={'display_name': 'problem 1', 'data': '<problem></problem>'}
|
||||
)
|
||||
first_problem.max_attempts = 3
|
||||
first_problem.save() # decache the above into the kvs
|
||||
updated_problem = modulestore().update_item(first_problem, 'testbot')
|
||||
self.assertIsNotNone(updated_problem.previous_version)
|
||||
self.assertEqual(updated_problem.previous_version, first_problem.update_version)
|
||||
self.assertNotEqual(updated_problem.update_version, first_problem.update_version)
|
||||
modulestore().delete_item(updated_problem.location, 'testbot')
|
||||
|
||||
second_problem = modulestore().create_child(
|
||||
None, sub.location.version_agnostic(),
|
||||
block_type='problem',
|
||||
block_id='problem2',
|
||||
fields={'display_name': 'problem 2', 'data': '<problem></problem>'}
|
||||
)
|
||||
|
||||
# The draft course root has 2 revisions: the published revision, and then the subsequent
|
||||
# changes to the draft revision
|
||||
version_history = modulestore().get_block_generations(test_course.location)
|
||||
self.assertIsNotNone(version_history)
|
||||
self.assertEqual(version_history.locator.version_guid, test_course.location.version_guid)
|
||||
self.assertEqual(len(version_history.children), 1)
|
||||
self.assertEqual(version_history.children[0].children, [])
|
||||
self.assertEqual(version_history.children[0].locator.version_guid, chapter.location.version_guid)
|
||||
|
||||
# sub changed on add, add problem, delete problem, add problem in strict linear seq
|
||||
version_history = modulestore().get_block_generations(sub.location)
|
||||
self.assertEqual(len(version_history.children), 1)
|
||||
self.assertEqual(len(version_history.children[0].children), 1)
|
||||
self.assertEqual(len(version_history.children[0].children[0].children), 1)
|
||||
self.assertEqual(len(version_history.children[0].children[0].children[0].children), 0)
|
||||
|
||||
# first and second problem may show as same usage_id; so, need to ensure their histories are right
|
||||
version_history = modulestore().get_block_generations(updated_problem.location)
|
||||
self.assertEqual(version_history.locator.version_guid, first_problem.location.version_guid)
|
||||
self.assertEqual(len(version_history.children), 1) # updated max_attempts
|
||||
self.assertEqual(len(version_history.children[0].children), 0)
|
||||
|
||||
version_history = modulestore().get_block_generations(second_problem.location)
|
||||
self.assertNotEqual(version_history.locator.version_guid, first_problem.location.version_guid)
|
||||
|
||||
|
||||
class TestCourseStructureCache(SplitModuleTest):
|
||||
"""Tests for the CourseStructureCache"""
|
||||
|
||||
Reference in New Issue
Block a user