Ejemplo n.º 1
0
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'))
Ejemplo n.º 2
0
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"))
Ejemplo n.º 3
0
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')
Ejemplo n.º 4
0
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))
Ejemplo n.º 5
0
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))
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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'))
Ejemplo n.º 8
0
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'))
Ejemplo n.º 9
0
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"))
Ejemplo n.º 10
0
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'))
Ejemplo n.º 11
0
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"))