def mock_descriptor(fields=[]): descriptor = Mock(entry_point=XBlock.entry_point) descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id')) descriptor.module_class.fields.values.return_value = fields descriptor.fields.values.return_value = fields descriptor.module_class.__name__ = 'MockProblemModule' return descriptor
def mock_descriptor(fields=[]): descriptor = Mock() descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id')) descriptor.module_class.fields.values.return_value = fields descriptor.fields.values.return_value = fields descriptor.module_class.__name__ = 'MockProblemModule' return descriptor
def mock_descriptor(fields=[]): descriptor = Mock(entry_point=XBlock.entry_point) descriptor.scope_ids = ScopeIds("user1", "mock_problem", location("def_id"), location("usage_id")) descriptor.module_class.fields.values.return_value = fields descriptor.fields.values.return_value = fields descriptor.module_class.__name__ = "MockProblemModule" return descriptor
def test_set_field_in_missing_student_module(self): "Test that setting a field in a missing StudentModule creates the student module" self.assertEquals(0, len(self.field_data_cache)) self.assertEquals(0, StudentModule.objects.all().count()) # We are updating a problem, so we write to courseware_studentmodulehistoryextended # as well as courseware_studentmodule. We also need to read the database # to discover if something other than the DjangoXBlockUserStateClient # has written to the StudentModule (such as UserStateCache setting the score # on the StudentModule). # Django 1.8 also has a number of other BEGIN and SAVESTATE queries. with self.assertNumQueries(4, using='default'): with self.assertNumQueries(1, using='student_module_history'): self.kvs.set(user_state_key('a_field'), 'a_value') self.assertEquals( 1, sum(len(cache) for cache in self.field_data_cache.cache.values())) self.assertEquals(1, StudentModule.objects.all().count()) student_module = StudentModule.objects.all()[0] self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state)) self.assertEquals(self.user, student_module.student) self.assertEquals( location('usage_id').replace(run=None), student_module.module_state_key) self.assertEquals(course_id, student_module.course_id)
def setUp(self): super(TestStudentModuleHistoryBackends, self).setUp() for record in (1, 2, 3): # This will store into CSMHE via the post_save signal csm = StudentModuleFactory.create(module_state_key=location('usage_id'), course_id=course_id, state=json.dumps({'type': 'csmhe', 'order': record})) # This manually gets us a CSMH record to compare csmh = StudentModuleHistory(student_module=csm, version=None, created=csm.modified, state=json.dumps({'type': 'csmh', 'order': record}), grade=csm.grade, max_grade=csm.max_grade) csmh.save()
def test_set_field_in_missing_student_module(self): "Test that setting a field in a missing StudentModule creates the student module" self.assertEquals(0, len(self.field_data_cache.cache)) self.assertEquals(0, StudentModule.objects.all().count()) self.kvs.set(user_state_key('a_field'), 'a_value') self.assertEquals(1, len(self.field_data_cache.cache)) self.assertEquals(1, StudentModule.objects.all().count()) student_module = StudentModule.objects.all()[0] self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state)) self.assertEquals(self.user, student_module.student) self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key) self.assertEquals(course_id, student_module.course_id)
def test_set_field_in_missing_student_module(self): "Test that setting a field in a missing StudentModule creates the student module" self.assertEquals(0, len(self.field_data_cache.cache)) self.assertEquals(0, StudentModule.objects.all().count()) # We are updating a problem, so we write to courseware_studentmodulehistory # as well as courseware_studentmodule with self.assertNumQueries(2): self.kvs.set(user_state_key('a_field'), 'a_value') self.assertEquals(1, len(self.field_data_cache.cache)) self.assertEquals(1, StudentModule.objects.all().count()) student_module = StudentModule.objects.all()[0] self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state)) self.assertEquals(self.user, student_module.student) self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key) self.assertEquals(course_id, student_module.course_id)
def test_set_field_in_missing_student_module(self): "Test that setting a field in a missing StudentModule creates the student module" self.assertEquals(0, len(self.field_data_cache.cache)) self.assertEquals(0, StudentModule.objects.all().count()) # We are updating a problem, so we write to courseware_studentmodulehistory # as well as courseware_studentmodule with self.assertNumQueries(6): self.kvs.set(user_state_key('a_field'), 'a_value') self.assertEquals(1, len(self.field_data_cache.cache)) self.assertEquals(1, StudentModule.objects.all().count()) student_module = StudentModule.objects.all()[0] self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state)) self.assertEquals(self.user, student_module.student) self.assertEquals( location('usage_id').replace(run=None), student_module.module_state_key) self.assertEquals(course_id, student_module.course_id)
def test_set_field_in_missing_student_module(self): "Test that setting a field in a missing StudentModule creates the student module" self.assertEquals(0, len(self.field_data_cache)) self.assertEquals(0, StudentModule.objects.all().count()) # We are updating a problem, so we write to courseware_studentmodulehistory # as well as courseware_studentmodule. We also need to read the database # to discover if something other than the DjangoXBlockUserStateClient # has written to the StudentModule (such as UserStateCache setting the score # on the StudentModule). with self.assertNumQueries(3): self.kvs.set(user_state_key('a_field'), 'a_value') self.assertEquals(1, sum(len(cache) for cache in self.field_data_cache.cache.values())) self.assertEquals(1, StudentModule.objects.all().count()) student_module = StudentModule.objects.all()[0] self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state)) self.assertEquals(self.user, student_module.student) self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key) self.assertEquals(course_id, student_module.course_id)
def setUp(self): super(TestStudentModuleHistoryBackends, self).setUp() for record in (1, 2, 3): # This will store into CSMHE via the post_save signal csm = StudentModuleFactory.create( module_state_key=location('usage_id'), course_id=course_id, state=json.dumps({ 'type': 'csmhe', 'order': record })) # This manually gets us a CSMH record to compare csmh = StudentModuleHistory(student_module=csm, version=None, created=csm.modified, state=json.dumps({ 'type': 'csmh', 'order': record }), grade=csm.grade, max_grade=csm.max_grade) csmh.save()
def test_set_field_in_missing_student_module(self): "Test that setting a field in a missing StudentModule creates the student module" self.assertEquals(0, len(self.field_data_cache)) self.assertEquals(0, StudentModule.objects.all().count()) # We are updating a problem, so we write to courseware_studentmodulehistoryextended # as well as courseware_studentmodule. We also need to read the database # to discover if something other than the DjangoXBlockUserStateClient # has written to the StudentModule (such as UserStateCache setting the score # on the StudentModule). # Django 1.8 also has a number of other BEGIN and SAVESTATE queries. with self.assertNumQueries(4, using="default"): with self.assertNumQueries(1, using="student_module_history"): self.kvs.set(user_state_key("a_field"), "a_value") self.assertEquals(1, sum(len(cache) for cache in self.field_data_cache.cache.values())) self.assertEquals(1, StudentModule.objects.all().count()) student_module = StudentModule.objects.all()[0] self.assertEquals({"a_field": "a_value"}, json.loads(student_module.state)) self.assertEquals(self.user, student_module.student) self.assertEquals(location("usage_id").replace(run=None), student_module.module_state_key) self.assertEquals(course_id, student_module.course_id)
class StudentModuleFactory(cmfStudentModuleFactory): module_state_key = location('usage_id') course_id = course_id
field.name = name return field def mock_descriptor(fields=[]): descriptor = Mock() descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id')) descriptor.module_class.fields.values.return_value = fields descriptor.fields.values.return_value = fields descriptor.module_class.__name__ = 'MockProblemModule' return descriptor # The user ids here are 1 because we make a student in the setUp functions, and # they get an id of 1. There's an assertion in setUp to ensure that assumption # is still true. user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('usage_id')) settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('usage_id')) user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1, location('usage_id')) prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1, 'mock_problem') user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None) class StudentModuleFactory(cmfStudentModuleFactory): module_state_key = location('usage_id') course_id = course_id class TestInvalidScopes(TestCase): def setUp(self): self.user = UserFactory.create(username='******') self.field_data_cache = FieldDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user)
class TestStudentModuleStorage(OtherUserFailureTestMixin, TestCase): """Tests for user_state storage via StudentModule""" other_key_factory = partial(DjangoKeyValueStore.Key, Scope.user_state, 2, location('usage_id')) # user_id=2, not 1 existing_field_name = "a_field" # Tell Django to clean out all databases, not just default multi_db = True def setUp(self): super(TestStudentModuleStorage, self).setUp() student_module = StudentModuleFactory( state=json.dumps({ 'a_field': 'a_value', 'b_field': 'b_value' })) self.user = student_module.student self.assertEqual( self.user.id, 1) # check our assumption hard-coded in the key functions above. # There should be only one query to load a single descriptor with a single user_state field with self.assertNumQueries(1): self.field_data_cache = FieldDataCache( [mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user) self.kvs = DjangoKeyValueStore(self.field_data_cache) def test_get_existing_field(self): "Test that getting an existing field in an existing StudentModule works" # This should only read from the cache, not the database with self.assertNumQueries(0): self.assertEquals('a_value', self.kvs.get(user_state_key('a_field'))) def test_get_missing_field(self): "Test that getting a missing field from an existing StudentModule raises a KeyError" # This should only read from the cache, not the database with self.assertNumQueries(0): self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field')) def test_set_existing_field(self): "Test that setting an existing user_state field changes the value" # We are updating a problem, so we write to courseware_studentmodulehistory # as well as courseware_studentmodule. We also need to read the database # to discover if something other than the DjangoXBlockUserStateClient # has written to the StudentModule (such as UserStateCache setting the score # on the StudentModule). with self.assertNumQueries(4, using='default'): with self.assertNumQueries(1, using='student_module_history'): self.kvs.set(user_state_key('a_field'), 'new_value') self.assertEquals(1, StudentModule.objects.all().count()) self.assertEquals({ 'b_field': 'b_value', 'a_field': 'new_value' }, json.loads(StudentModule.objects.all()[0].state)) def test_set_missing_field(self): "Test that setting a new user_state field changes the value" # We are updating a problem, so we write to courseware_studentmodulehistory # as well as courseware_studentmodule. We also need to read the database # to discover if something other than the DjangoXBlockUserStateClient # has written to the StudentModule (such as UserStateCache setting the score # on the StudentModule). with self.assertNumQueries(4, using='default'): with self.assertNumQueries(1, using='student_module_history'): self.kvs.set(user_state_key('not_a_field'), 'new_value') self.assertEquals(1, StudentModule.objects.all().count()) self.assertEquals( { 'b_field': 'b_value', 'a_field': 'a_value', 'not_a_field': 'new_value' }, json.loads(StudentModule.objects.all()[0].state)) def test_delete_existing_field(self): "Test that deleting an existing field removes it from the StudentModule" # We are updating a problem, so we write to courseware_studentmodulehistory # as well as courseware_studentmodule. We also need to read the database # to discover if something other than the DjangoXBlockUserStateClient # has written to the StudentModule (such as UserStateCache setting the score # on the StudentModule). with self.assertNumQueries(2, using='default'): with self.assertNumQueries(1, using='student_module_history'): self.kvs.delete(user_state_key('a_field')) self.assertEquals(1, StudentModule.objects.all().count()) self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field')) def test_delete_missing_field(self): "Test that deleting a missing field from an existing StudentModule raises a KeyError" with self.assertNumQueries(0): self.assertRaises(KeyError, self.kvs.delete, user_state_key('not_a_field')) self.assertEquals(1, StudentModule.objects.all().count()) self.assertEquals({ 'b_field': 'b_value', 'a_field': 'a_value' }, json.loads(StudentModule.objects.all()[0].state)) def test_has_existing_field(self): "Test that `has` returns True for existing fields in StudentModules" with self.assertNumQueries(0): self.assertTrue(self.kvs.has(user_state_key('a_field'))) def test_has_missing_field(self): "Test that `has` returns False for missing fields in StudentModule" with self.assertNumQueries(0): self.assertFalse(self.kvs.has(user_state_key('not_a_field'))) def construct_kv_dict(self): """Construct a kv_dict that can be passed to set_many""" key1 = user_state_key('field_a') key2 = user_state_key('field_b') new_value = 'new value' newer_value = 'newer value' return {key1: new_value, key2: newer_value} def test_set_many(self): "Test setting many fields that are scoped to Scope.user_state" kv_dict = self.construct_kv_dict() # Scope.user_state is stored in a single row in the database, so we only # need to send a single update to that table. # We also are updating a problem, so we write to courseware student module history # We also need to read the database to discover if something other than the # DjangoXBlockUserStateClient has written to the StudentModule (such as # UserStateCache setting the score on the StudentModule). with self.assertNumQueries(4, using="default"): with self.assertNumQueries(1, using="student_module_history"): self.kvs.set_many(kv_dict) for key in kv_dict: self.assertEquals(self.kvs.get(key), kv_dict[key]) def test_set_many_failure(self): "Test failures when setting many fields that are scoped to Scope.user_state" kv_dict = self.construct_kv_dict() # because we're patching the underlying save, we need to ensure the # fields are in the cache for key in kv_dict: self.kvs.set(key, 'test_value') with patch('django.db.models.Model.save', side_effect=DatabaseError): with self.assertRaises( KeyValueMultiSaveError) as exception_context: self.kvs.set_many(kv_dict) self.assertEquals(exception_context.exception.saved_field_names, [])
def mock_descriptor(fields=[]): descriptor = Mock(entry_point=XBlock.entry_point) descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id')) descriptor.module_class.fields.values.return_value = fields descriptor.fields.values.return_value = fields descriptor.module_class.__name__ = 'MockProblemModule' return descriptor # The user ids here are 1 because we make a student in the setUp functions, and # they get an id of 1. There's an assertion in setUp to ensure that assumption # is still true. user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('usage_id')) settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('usage_id')) user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1, location('usage_id')) prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1, 'mock_problem') user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None) class StudentModuleFactory(cmfStudentModuleFactory): module_state_key = location('usage_id') course_id = course_id class TestInvalidScopes(TestCase):
class TestStudentModuleStorage(OtherUserFailureTestMixin, TestCase): """Tests for user_state storage via StudentModule""" other_key_factory = partial(DjangoKeyValueStore.Key, Scope.user_state, 2, location('usage_id')) # user_id=2, not 1 existing_field_name = "a_field" def setUp(self): student_module = StudentModuleFactory(state=json.dumps({'a_field': 'a_value', 'b_field': 'b_value'})) self.user = student_module.student self.assertEqual(self.user.id, 1) # check our assumption hard-coded in the key functions above. self.field_data_cache = FieldDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user) self.kvs = DjangoKeyValueStore(self.field_data_cache) def test_get_existing_field(self): "Test that getting an existing field in an existing StudentModule works" self.assertEquals('a_value', self.kvs.get(user_state_key('a_field'))) def test_get_missing_field(self): "Test that getting a missing field from an existing StudentModule raises a KeyError" self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field')) def test_set_existing_field(self): "Test that setting an existing user_state field changes the value" self.kvs.set(user_state_key('a_field'), 'new_value') self.assertEquals(1, StudentModule.objects.all().count()) self.assertEquals({'b_field': 'b_value', 'a_field': 'new_value'}, json.loads(StudentModule.objects.all()[0].state)) def test_set_missing_field(self): "Test that setting a new user_state field changes the value" self.kvs.set(user_state_key('not_a_field'), 'new_value') self.assertEquals(1, StudentModule.objects.all().count()) self.assertEquals({'b_field': 'b_value', 'a_field': 'a_value', 'not_a_field': 'new_value'}, json.loads(StudentModule.objects.all()[0].state)) def test_delete_existing_field(self): "Test that deleting an existing field removes it from the StudentModule" self.kvs.delete(user_state_key('a_field')) self.assertEquals(1, StudentModule.objects.all().count()) self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field')) def test_delete_missing_field(self): "Test that deleting a missing field from an existing StudentModule raises a KeyError" self.assertRaises(KeyError, self.kvs.delete, user_state_key('not_a_field')) self.assertEquals(1, StudentModule.objects.all().count()) self.assertEquals({'b_field': 'b_value', 'a_field': 'a_value'}, json.loads(StudentModule.objects.all()[0].state)) def test_has_existing_field(self): "Test that `has` returns True for existing fields in StudentModules" self.assertTrue(self.kvs.has(user_state_key('a_field'))) def test_has_missing_field(self): "Test that `has` returns False for missing fields in StudentModule" self.assertFalse(self.kvs.has(user_state_key('not_a_field'))) def construct_kv_dict(self): """Construct a kv_dict that can be passed to set_many""" key1 = user_state_key('field_a') key2 = user_state_key('field_b') new_value = 'new value' newer_value = 'newer value' return {key1: new_value, key2: newer_value} def test_set_many(self): "Test setting many fields that are scoped to Scope.user_state" kv_dict = self.construct_kv_dict() self.kvs.set_many(kv_dict) for key in kv_dict: self.assertEquals(self.kvs.get(key), kv_dict[key]) def test_set_many_failure(self): "Test failures when setting many fields that are scoped to Scope.user_state" kv_dict = self.construct_kv_dict() # because we're patching the underlying save, we need to ensure the # fields are in the cache for key in kv_dict: self.kvs.set(key, 'test_value') with patch('django.db.models.Model.save', side_effect=DatabaseError): with self.assertRaises(KeyValueMultiSaveError) as exception_context: self.kvs.set_many(kv_dict) self.assertEquals(len(exception_context.exception.saved_field_names), 0)
field.name = name return field def mock_descriptor(fields=[]): descriptor = Mock(entry_point=XBlock.entry_point) descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id')) descriptor.module_class.fields.values.return_value = fields descriptor.fields.values.return_value = fields descriptor.module_class.__name__ = 'MockProblemModule' return descriptor # The user ids here are 1 because we make a student in the setUp functions, and # they get an id of 1. There's an assertion in setUp to ensure that assumption # is still true. user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('usage_id')) settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('usage_id')) user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1, location('usage_id')) prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1, 'mock_problem') user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None) class StudentModuleFactory(cmfStudentModuleFactory): module_state_key = location('usage_id') course_id = course_id @attr('shard_1') class TestInvalidScopes(TestCase): def setUp(self): super(TestInvalidScopes, self).setUp()