def test_field_access(): class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = Integer(scope=Scope.settings) field_b = Integer(scope=Scope.content, default=10) field_c = Integer(scope=Scope.user_state, default=42) float_a = Float(scope=Scope.settings, default=5.8) float_b = Float(scope=Scope.settings) field_data = DictFieldData({'field_a': 5, 'float_a': 6.1, 'field_x': 15}) field_tester = FieldTester( TestRuntime(services={'field-data': field_data}), scope_ids=Mock()) # Verify that the fields have been set assert_equals(5, field_tester.field_a) assert_equals(10, field_tester.field_b) assert_equals(42, field_tester.field_c) assert_equals(6.1, field_tester.float_a) assert_equals(None, field_tester.float_b) assert not hasattr(field_tester, 'field_x') # Set two of the fields. field_tester.field_a = 20 field_tester.float_a = 20.5 # field_a should be updated in the cache, but /not/ in the underlying db. assert_equals(20, field_tester.field_a) assert_equals(20.5, field_tester.float_a) assert_equals(5, field_data.get(field_tester, 'field_a')) assert_equals(6.1, field_data.get(field_tester, 'float_a')) # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert_equals(20, field_tester.field_a) assert_equals(20.5, field_tester.float_a) # Now, field_a should be updated in the underlying db assert_equals(20, field_data.get(field_tester, 'field_a')) assert_equals(20.5, field_data.get(field_tester, 'float_a')) assert_equals(10, field_tester.field_b) assert_equals(42, field_tester.field_c) assert_equals(None, field_tester.float_b) # Deletes happen immediately (do not require a save) del field_tester.field_a del field_tester.float_a # After delete, we should find default values in the cache assert_equals(None, field_tester.field_a) assert_equals(5.8, field_tester.float_a) # But the fields should not actually be present in the underlying kvstore with assert_raises(KeyError): field_data.get(field_tester, 'field_a') assert_false(field_data.has(field_tester, 'field_a')) with assert_raises(KeyError): field_data.get(field_tester, 'float_a') assert_false(field_data.has(field_tester, 'float_a'))
def test_field_access(): class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = Integer(scope=Scope.settings) field_b = Integer(scope=Scope.content, default=10) field_c = Integer(scope=Scope.user_state, default=42) float_a = Float(scope=Scope.settings, default=5.8) float_b = Float(scope=Scope.settings) field_data = DictFieldData({"field_a": 5, "float_a": 6.1, "field_x": 15}) field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock()) # Verify that the fields have been set assert_equals(5, field_tester.field_a) assert_equals(10, field_tester.field_b) assert_equals(42, field_tester.field_c) assert_equals(6.1, field_tester.float_a) assert_equals(None, field_tester.float_b) assert not hasattr(field_tester, "field_x") # Set two of the fields. field_tester.field_a = 20 field_tester.float_a = 20.5 # field_a should be updated in the cache, but /not/ in the underlying db. assert_equals(20, field_tester.field_a) assert_equals(20.5, field_tester.float_a) assert_equals(5, field_data.get(field_tester, "field_a")) assert_equals(6.1, field_data.get(field_tester, "float_a")) # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert_equals(20, field_tester.field_a) assert_equals(20.5, field_tester.float_a) # Now, field_a should be updated in the underlying db assert_equals(20, field_data.get(field_tester, "field_a")) assert_equals(20.5, field_data.get(field_tester, "float_a")) assert_equals(10, field_tester.field_b) assert_equals(42, field_tester.field_c) assert_equals(None, field_tester.float_b) # Deletes happen immediately (do not require a save) del field_tester.field_a del field_tester.float_a # After delete, we should find default values in the cache assert_equals(None, field_tester.field_a) assert_equals(5.8, field_tester.float_a) # But the fields should not actually be present in the underlying kvstore with assert_raises(KeyError): field_data.get(field_tester, "field_a") assert_false(field_data.has(field_tester, "field_a")) with assert_raises(KeyError): field_data.get(field_tester, "float_a") assert_false(field_data.has(field_tester, "float_a"))
def test_field_access(): class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = Integer(scope=Scope.settings) field_b = Integer(scope=Scope.content, default=10) field_c = Integer(scope=Scope.user_state, default=42) float_a = Float(scope=Scope.settings, default=5.8) float_b = Float(scope=Scope.settings) field_data = DictFieldData({'field_a': 5, 'float_a': 6.1, 'field_x': 15}) field_tester = FieldTester(TestRuntime(services={'field-data': field_data}), scope_ids=Mock()) # Verify that the fields have been set assert field_tester.field_a == 5 assert field_tester.field_b == 10 assert field_tester.field_c == 42 assert field_tester.float_a == 6.1 assert field_tester.float_b is None assert not hasattr(field_tester, 'field_x') # Set two of the fields. field_tester.field_a = 20 field_tester.float_a = 20.5 # field_a should be updated in the cache, but /not/ in the underlying db. assert field_tester.field_a == 20 assert field_tester.float_a == 20.5 assert field_data.get(field_tester, 'field_a') == 5 assert field_data.get(field_tester, 'float_a') == 6.1 # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert field_tester.field_a == 20 assert field_tester.float_a == 20.5 # Now, field_a should be updated in the underlying db assert field_data.get(field_tester, 'field_a') == 20 assert field_data.get(field_tester, 'float_a') == 20.5 assert field_tester.field_b == 10 assert field_tester.field_c == 42 assert field_tester.float_b is None # Deletes happen immediately (do not require a save) del field_tester.field_a del field_tester.float_a # After delete, we should find default values in the cache assert field_tester.field_a is None assert field_tester.float_a == 5.8 # But the fields should not actually be present in the underlying kvstore with pytest.raises(KeyError): field_data.get(field_tester, 'field_a') assert not field_data.has(field_tester, 'field_a') with pytest.raises(KeyError): field_data.get(field_tester, 'float_a') assert not field_data.has(field_tester, 'float_a')
def test_default_values(): # Check that values that are deleted are restored to their default values class FieldTester(XBlock): """Test XBlock for field access testing""" dic1 = Dict(scope=Scope.settings) dic2 = Dict(scope=Scope.content, default={'a': 1, 'b': 2, 'c': 3}) list1 = List(scope=Scope.settings) list2 = List(scope=Scope.content, default=[1, 2, 3]) field_data = DictFieldData({'dic1': {'a': 200}, 'list1': ['a', 'b']}) field_tester = FieldTester( TestRuntime(services={'field-data': field_data}), scope_ids=Mock(spec=ScopeIds)) assert_equals({'a': 200}, field_tester.dic1) assert_equals({'a': 1, 'b': 2, 'c': 3}, field_tester.dic2) assert_equals(['a', 'b'], field_tester.list1) assert_equals([1, 2, 3], field_tester.list2) # Modify the fields & save field_tester.dic1.popitem() field_tester.dic2.clear() field_tester.list1.pop() field_tester.list2.remove(2) field_tester.save() # Test that after save, new values exist and fields are present in the underlying kvstore assert_equals({}, field_tester.dic1) assert_equals({}, field_tester.dic2) assert_equals(['a'], field_tester.list1) assert_equals([1, 3], field_tester.list2) for fname in ['dic1', 'dic2', 'list1', 'list2']: assert field_data.has(field_tester, fname) # Now delete each field del field_tester.dic1 del field_tester.dic2 del field_tester.list1 del field_tester.list2 # Test that default values return after a delete, but fields not actually # in the underlying kvstore # Defaults not explicitly set assert_equals({}, field_tester.dic1) assert_equals([], field_tester.list1) # Defaults explicitly set assert_equals({'a': 1, 'b': 2, 'c': 3}, field_tester.dic2) assert_equals([1, 2, 3], field_tester.list2) for fname in ['dic1', 'dic2', 'list1', 'list2']: assert_false(field_data.has(field_tester, fname))
def test_default_values(): # Check that values that are deleted are restored to their default values class FieldTester(XBlock): """Test XBlock for field access testing""" dic1 = Dict(scope=Scope.settings) dic2 = Dict(scope=Scope.content, default={"a": 1, "b": 2, "c": 3}) list1 = List(scope=Scope.settings) list2 = List(scope=Scope.content, default=[1, 2, 3]) field_data = DictFieldData({"dic1": {"a": 200}, "list1": ["a", "b"]}) field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock(spec=ScopeIds)) assert_equals({"a": 200}, field_tester.dic1) assert_equals({"a": 1, "b": 2, "c": 3}, field_tester.dic2) assert_equals(["a", "b"], field_tester.list1) assert_equals([1, 2, 3], field_tester.list2) # Modify the fields & save field_tester.dic1.popitem() field_tester.dic2.clear() field_tester.list1.pop() field_tester.list2.remove(2) field_tester.save() # Test that after save, new values exist and fields are present in the underlying kvstore assert_equals({}, field_tester.dic1) assert_equals({}, field_tester.dic2) assert_equals(["a"], field_tester.list1) assert_equals([1, 3], field_tester.list2) for fname in ["dic1", "dic2", "list1", "list2"]: assert field_data.has(field_tester, fname) # Now delete each field del field_tester.dic1 del field_tester.dic2 del field_tester.list1 del field_tester.list2 # Test that default values return after a delete, but fields not actually # in the underlying kvstore # Defaults not explicitly set assert_equals({}, field_tester.dic1) assert_equals([], field_tester.list1) # Defaults explicitly set assert_equals({"a": 1, "b": 2, "c": 3}, field_tester.dic2) assert_equals([1, 2, 3], field_tester.list2) for fname in ["dic1", "dic2", "list1", "list2"]: assert_false(field_data.has(field_tester, fname))
def test_default_values(): # Check that values that are deleted are restored to their default values class FieldTester(XBlock): """Test XBlock for field access testing""" dic1 = Dict(scope=Scope.settings) dic2 = Dict(scope=Scope.content, default={'a': 1, 'b': 2, 'c': 3}) list1 = List(scope=Scope.settings) list2 = List(scope=Scope.content, default=[1, 2, 3]) field_data = DictFieldData({'dic1': {'a': 200}, 'list1': ['a', 'b']}) field_tester = FieldTester(TestRuntime(services={'field-data': field_data}), scope_ids=Mock(spec=ScopeIds)) assert {'a': 200} == field_tester.dic1 assert {'a': 1, 'b': 2, 'c': 3} == field_tester.dic2 assert ['a', 'b'] == field_tester.list1 assert [1, 2, 3] == field_tester.list2 # Modify the fields & save field_tester.dic1.popitem() field_tester.dic2.clear() field_tester.list1.pop() field_tester.list2.remove(2) field_tester.save() # Test that after save, new values exist and fields are present in the underlying kvstore assert {} == field_tester.dic1 assert {} == field_tester.dic2 assert ['a'] == field_tester.list1 assert [1, 3] == field_tester.list2 for fname in ['dic1', 'dic2', 'list1', 'list2']: assert field_data.has(field_tester, fname) # Now delete each field del field_tester.dic1 del field_tester.dic2 del field_tester.list1 del field_tester.list2 # Test that default values return after a delete, but fields not actually # in the underlying kvstore # Defaults not explicitly set assert {} == field_tester.dic1 assert [] == field_tester.list1 # Defaults explicitly set assert {'a': 1, 'b': 2, 'c': 3} == field_tester.dic2 assert [1, 2, 3] == field_tester.list2 for fname in ['dic1', 'dic2', 'list1', 'list2']: assert not field_data.has(field_tester, fname)
def test_dict_field_access(): # Check that dicts are correctly saved when not directly set class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = Dict(scope=Scope.settings) field_b = Dict(scope=Scope.content, default={'a': 1, 'b': 2, 'c': 3}) field_c = Dict(scope=Scope.content, default={'a': 4, 'b': 5, 'c': 6}) field_d = Dict(scope=Scope.settings) field_data = DictFieldData({ 'field_a': {'a': 200}, 'field_b': {'a': 11, 'b': 12, 'c': 13} }) field_tester = FieldTester( TestRuntime(services={'field-data': field_data}), None, Mock() ) # Check initial values have been set properly assert_equals({'a': 200}, field_tester.field_a) assert_equals({'a': 11, 'b': 12, 'c': 13}, field_tester.field_b) assert_equals({'a': 4, 'b': 5, 'c': 6}, field_tester.field_c) assert_equals({}, field_tester.field_d) # Update the fields field_tester.field_a['a'] = 250 field_tester.field_b['d'] = 14 field_tester.field_c['a'] = 0 field_tester.field_d['new'] = 'value' # The fields should be update in the cache, but /not/ in the underlying kvstore. assert_equals({'a': 250}, field_tester.field_a) assert_equals({'a': 11, 'b': 12, 'c': 13, 'd': 14}, field_tester.field_b) assert_equals({'a': 0, 'b': 5, 'c': 6}, field_tester.field_c) assert_equals({'new': 'value'}, field_tester.field_d) # Examine model data directly # Caveat: there's not a clean way to copy the originally provided values for `field_a` and `field_b` # when we instantiate the XBlock. So, the values for those two in both `field_data` and `_field_data_cache` # point at the same object. Thus, `field_a` and `field_b` actually have the correct values in # `field_data` right now. `field_c` does not, because it has never been written to the `field_data`. assert_false(field_data.has(field_tester, 'field_c')) assert_false(field_data.has(field_tester, 'field_d')) field_tester.save() # verify that the fields have been updated correctly assert_equals({'a': 250}, field_tester.field_a) assert_equals({'a': 11, 'b': 12, 'c': 13, 'd': 14}, field_tester.field_b) assert_equals({'a': 0, 'b': 5, 'c': 6}, field_tester.field_c) assert_equals({'new': 'value'}, field_tester.field_d) # Now, the fields should be updated in the underlying kvstore assert_equals({'a': 250}, field_data.get(field_tester, 'field_a')) assert_equals({'a': 11, 'b': 12, 'c': 13, 'd': 14}, field_data.get(field_tester, 'field_b')) assert_equals({'a': 0, 'b': 5, 'c': 6}, field_data.get(field_tester, 'field_c')) assert_equals({'new': 'value'}, field_data.get(field_tester, 'field_d'))
def test_list_field_access(): # Check that lists are correctly saved when not directly set class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = List(scope=Scope.settings) field_b = List(scope=Scope.content, default=[1, 2, 3]) field_c = List(scope=Scope.content, default=[4, 5, 6]) field_d = List(scope=Scope.settings) field_data = DictFieldData({'field_a': [200], 'field_b': [11, 12, 13]}) field_tester = FieldTester( TestRuntime(services={'field-data': field_data}), scope_ids=Mock(spec=ScopeIds)) # Check initial values have been set properly assert_equals([200], field_tester.field_a) assert_equals([11, 12, 13], field_tester.field_b) assert_equals([4, 5, 6], field_tester.field_c) assert_equals([], field_tester.field_d) # Update the fields field_tester.field_a.append(1) field_tester.field_b.append(14) field_tester.field_c.append(7) field_tester.field_d.append(1) # The fields should be update in the cache, but /not/ in the underlying kvstore. assert_equals([200, 1], field_tester.field_a) assert_equals([11, 12, 13, 14], field_tester.field_b) assert_equals([4, 5, 6, 7], field_tester.field_c) assert_equals([1], field_tester.field_d) # Examine model data directly # Caveat: there's not a clean way to copy the originally provided values for `field_a` and `field_b` # when we instantiate the XBlock. So, the values for those two in both `field_data` and `_field_data_cache` # point at the same object. Thus, `field_a` and `field_b` actually have the correct values in # `field_data` right now. `field_c` does not, because it has never been written to the `field_data`. assert_false(field_data.has(field_tester, 'field_c')) assert_false(field_data.has(field_tester, 'field_d')) # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert_equals([200, 1], field_tester.field_a) assert_equals([11, 12, 13, 14], field_tester.field_b) assert_equals([4, 5, 6, 7], field_tester.field_c) assert_equals([1], field_tester.field_d) # Now, the fields should be updated in the underlying kvstore assert_equals([200, 1], field_data.get(field_tester, 'field_a')) assert_equals([11, 12, 13, 14], field_data.get(field_tester, 'field_b')) assert_equals([4, 5, 6, 7], field_data.get(field_tester, 'field_c')) assert_equals([1], field_data.get(field_tester, 'field_d'))
def test_list_field_access(): # Check that lists are correctly saved when not directly set class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = List(scope=Scope.settings) field_b = List(scope=Scope.content, default=[1, 2, 3]) field_c = List(scope=Scope.content, default=[4, 5, 6]) field_d = List(scope=Scope.settings) field_data = DictFieldData({"field_a": [200], "field_b": [11, 12, 13]}) field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock(spec=ScopeIds)) # Check initial values have been set properly assert_equals([200], field_tester.field_a) assert_equals([11, 12, 13], field_tester.field_b) assert_equals([4, 5, 6], field_tester.field_c) assert_equals([], field_tester.field_d) # Update the fields field_tester.field_a.append(1) field_tester.field_b.append(14) field_tester.field_c.append(7) field_tester.field_d.append(1) # The fields should be update in the cache, but /not/ in the underlying kvstore. assert_equals([200, 1], field_tester.field_a) assert_equals([11, 12, 13, 14], field_tester.field_b) assert_equals([4, 5, 6, 7], field_tester.field_c) assert_equals([1], field_tester.field_d) # Examine model data directly # Caveat: there's not a clean way to copy the originally provided values for `field_a` and `field_b` # when we instantiate the XBlock. So, the values for those two in both `field_data` and `_field_data_cache` # point at the same object. Thus, `field_a` and `field_b` actually have the correct values in # `field_data` right now. `field_c` does not, because it has never been written to the `field_data`. assert_false(field_data.has(field_tester, "field_c")) assert_false(field_data.has(field_tester, "field_d")) # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert_equals([200, 1], field_tester.field_a) assert_equals([11, 12, 13, 14], field_tester.field_b) assert_equals([4, 5, 6, 7], field_tester.field_c) assert_equals([1], field_tester.field_d) # Now, the fields should be updated in the underlying kvstore assert_equals([200, 1], field_data.get(field_tester, "field_a")) assert_equals([11, 12, 13, 14], field_data.get(field_tester, "field_b")) assert_equals([4, 5, 6, 7], field_data.get(field_tester, "field_c")) assert_equals([1], field_data.get(field_tester, "field_d"))
def test_xblock_write_then_delete(): # Tests that setting a field, then deleting it later, doesn't # cause an erroneous write of the originally set value after # a call to `XBlock.save` class FieldTester(XBlock): """Test XBlock with two fields""" field_a = Integer(scope=Scope.settings) field_b = Integer(scope=Scope.content, default=10) field_data = DictFieldData({'field_a': 5}) field_tester = FieldTester( TestRuntime(services={'field-data': field_data}), scope_ids=Mock(spec=ScopeIds)) # Verify that the fields have been set correctly assert_equals(5, field_tester.field_a) assert_equals(10, field_tester.field_b) # Set the fields to new values field_tester.field_a = 20 field_tester.field_b = 20 # Assert that we've correctly cached the value of both fields to the newly set values. assert_equals(20, field_tester.field_a) assert_equals(20, field_tester.field_b) # Before saving, delete all the fields. Deletes are performed immediately for now, # so the field should immediately not be present in the field_data after the delete. # However, we copy the default values into the cache, so after the delete we expect the # cached values to be the default values, but the fields to be removed from the field_data. del field_tester.field_a del field_tester.field_b # Assert that we're now finding the right cached values - these should be the default values # that the fields have from the class since we've performed a delete, and XBlock.__delete__ # inserts the default values into the cache as an optimization. assert_equals(None, field_tester.field_a) assert_equals(10, field_tester.field_b) # Perform explicit save field_tester.save() # Now that we've done the save, double-check that we still have the correct cached values (the defaults) assert_equals(None, field_tester.field_a) assert_equals(10, field_tester.field_b) # Additionally assert that in the model data, we don't have any values actually set for these fields. # Basically, we want to ensure that the `save` didn't overwrite anything in the actual field_data # Note this test directly accessess field_data and is thus somewhat fragile. assert_false(field_data.has(field_tester, 'field_a')) assert_false(field_data.has(field_tester, 'field_b'))
def test_xblock_write_then_delete(): # Tests that setting a field, then deleting it later, doesn't # cause an erroneous write of the originally set value after # a call to `XBlock.save` class FieldTester(XBlock): """Test XBlock with two fields""" field_a = Integer(scope=Scope.settings) field_b = Integer(scope=Scope.content, default=10) field_data = DictFieldData({"field_a": 5}) field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock(spec=ScopeIds)) # Verify that the fields have been set correctly assert_equals(5, field_tester.field_a) assert_equals(10, field_tester.field_b) # Set the fields to new values field_tester.field_a = 20 field_tester.field_b = 20 # Assert that we've correctly cached the value of both fields to the newly set values. assert_equals(20, field_tester.field_a) assert_equals(20, field_tester.field_b) # Before saving, delete all the fields. Deletes are performed immediately for now, # so the field should immediately not be present in the field_data after the delete. # However, we copy the default values into the cache, so after the delete we expect the # cached values to be the default values, but the fields to be removed from the field_data. del field_tester.field_a del field_tester.field_b # Assert that we're now finding the right cached values - these should be the default values # that the fields have from the class since we've performed a delete, and XBlock.__delete__ # inserts the default values into the cache as an optimization. assert_equals(None, field_tester.field_a) assert_equals(10, field_tester.field_b) # Perform explicit save field_tester.save() # Now that we've done the save, double-check that we still have the correct cached values (the defaults) assert_equals(None, field_tester.field_a) assert_equals(10, field_tester.field_b) # Additionally assert that in the model data, we don't have any values actually set for these fields. # Basically, we want to ensure that the `save` didn't overwrite anything in the actual field_data # Note this test directly accessess field_data and is thus somewhat fragile. assert_false(field_data.has(field_tester, "field_a")) assert_false(field_data.has(field_tester, "field_b"))