From 3ae568a38a70dd28766c34b499d396ac9ca3a504 Mon Sep 17 00:00:00 2001 From: novirium Date: Sun, 15 Dec 2019 13:19:47 +0800 Subject: [PATCH] Add tests. Closes #5 --- tests/test_preserve.py | 116 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/test_preserve.py diff --git a/tests/test_preserve.py b/tests/test_preserve.py new file mode 100644 index 0000000..ac99938 --- /dev/null +++ b/tests/test_preserve.py @@ -0,0 +1,116 @@ +import pytest +import preserve + + +class PlainClass: + def __init__(self): + self.attr_int = 734 + self.attr_string = "I'm a test string" + self.attr_float = 42.085 + self.attr_dict = {"key1": 1, "key2": "val2"} + self.attr_list = ["item1", 2, 3, 4] + self.attr_bool = True + + +@preserve.preservable +class PreservableClass(PlainClass): + pass + + +@pytest.fixture +def primitive_data(): + return {'key1': ["item1", {"d2k1": "val1", "d2k2": 2}, {"d3k1": "val1", "d3k2": True}, "test str"]} + + +def obj_attrs_and_type_equal(obj1, obj2): + # Checks that both the __dict__ on each object and the __class__ on each object + # are equal + return (vars(type(obj1)) == vars(type(obj2))) and (vars(obj1) == vars(obj2)) + + +def test_primitive_data(primitive_data): + # preserve/restore shouldn't modify something that's already all primitives + preserved_data = preserve.preserve(primitive_data) + assert preserved_data == primitive_data + assert (preserve.restore(preserved_data)) == primitive_data + + +def test_data_with_preservable(primitive_data): + # Preservable class within a data structure + primitive_data["preservable"] = PreservableClass() + restored_data = preserve.restore(preserve.preserve(primitive_data)) + assert restored_data['key1'] == primitive_data['key1'] + assert restored_data["preservable"] != primitive_data["preservable"] + assert obj_attrs_and_type_equal(restored_data["preservable"], primitive_data["preservable"]) + + +def test_plain_class(): + # plain class is not preservable + with pytest.raises(Exception, match="is not preservable"): + preserve.preserve(PlainClass()) + + +def test_preservable_class(): + # Preservable class should restore to a new instance with same content + obj = PreservableClass() + restored_obj = preserve.restore(preserve.preserve(obj)) + assert restored_obj != obj + assert obj_attrs_and_type_equal(restored_obj, obj) + + +def test_attr_plain_class(): + # Class with non-preservable class as an attribute should fail + obj = PreservableClass() + obj.attr_obj = PlainClass() + with pytest.raises(Exception, match="is not preservable"): + preserve.preserve(obj) + + +def test_class_key(): + # Should be able to change the default class key before decorators + # and have preserve/restore work + old_class_key = preserve.class_key + preserve.class_key = "A different key" + + @preserve.preservable + class TestClass(PlainClass): + pass + + obj = TestClass() + restored_obj = preserve.restore(preserve.preserve(obj)) + assert restored_obj != obj + assert obj_attrs_and_type_equal(restored_obj, obj) + + preserve.class_key = old_class_key + + +def test_class_key_in_data(): + # Can't use the class key as dict key being preserved + with pytest.raises(Exception, match="reserved for internal use"): + preserve.preserve({preserve.class_key: 1}) + + +def test_unrestorable(primitive_data): + # Shouldn't be able to restore from data containing non-primitive types + preserved_data = preserve.preserve(primitive_data) + + preserved_data["unrestorable"] = (1, 2, 3) + with pytest.raises(Exception, match="is not restorable"): + preserve.restore(preserved_data) + + preserved_data["unrestorable"] = PlainClass() + with pytest.raises(Exception, match="is not restorable"): + preserve.restore(preserved_data) + + +def test_str_dict_keys(primitive_data): + # Non-string dict keys aren't restorable or preservable + preserved_data = preserve.preserve(primitive_data) + + primitive_data[2] = "has a non-string key" + with pytest.raises(Exception, match="Non-string dictionary keys are not preservable"): + preserve.preserve(primitive_data) + + preserved_data[2] = "has a non-string key" + with pytest.raises(Exception, match="Non-string dictionary keys are not restorable"): + preserve.restore(preserved_data)