Spaces:
Runtime error
Runtime error
| """ | |
| Unit-тесты для базового класса LinkerEntity и его механизма сериализации/десериализации. | |
| """ | |
| import uuid | |
| from dataclasses import dataclass, field | |
| from uuid import UUID, uuid4 | |
| import pytest | |
| from ntr_text_fragmentation.models import LinkerEntity, register_entity | |
| from tests.custom_entity import \ | |
| CustomEntity # Используем существующий кастомный класс | |
| # Фикстуры | |
| def base_entity() -> LinkerEntity: | |
| """Фикстура для базовой сущности.""" | |
| return LinkerEntity(id=uuid4(), name="Base Name", text="Base Text") | |
| def link_entity() -> LinkerEntity: | |
| """Фикстура для сущности-связи.""" | |
| return LinkerEntity( | |
| id=uuid4(), | |
| name="Link Name", | |
| source_id=uuid4(), | |
| target_id=uuid4(), | |
| number_in_relation=1, | |
| ) | |
| def custom_entity_instance() -> CustomEntity: | |
| """Фикстура для кастомной сущности.""" | |
| return CustomEntity( | |
| id=uuid4(), | |
| name="Custom Name", | |
| text="Custom Text", | |
| custom_field="custom_value", | |
| metadata={"existing_meta": "meta_value"}, | |
| ) | |
| def serialized_custom_entity( | |
| custom_entity_instance: CustomEntity, | |
| ) -> LinkerEntity: | |
| """Фикстура для сериализованной кастомной сущности.""" | |
| return custom_entity_instance.serialize() | |
| # Тесты | |
| class TestLinkerEntity: | |
| """Тесты для класса LinkerEntity.""" | |
| def test_initialization_defaults(self): | |
| """Тест инициализации с значениями по умолчанию.""" | |
| entity = LinkerEntity() | |
| assert isinstance(entity.id, UUID) | |
| assert entity.name == "" | |
| assert entity.text == "" | |
| assert entity.metadata == {} | |
| assert entity.in_search_text is None | |
| assert entity.source_id is None | |
| assert entity.target_id is None | |
| assert entity.number_in_relation is None | |
| assert entity.groupper is None | |
| assert entity.type == "LinkerEntity" # Имя класса по умолчанию | |
| def test_initialization_with_values(self, base_entity: LinkerEntity): | |
| """Тест инициализации с заданными значениями.""" | |
| entity_id = base_entity.id | |
| assert base_entity.name == "Base Name" | |
| assert base_entity.text == "Base Text" | |
| assert base_entity.id == entity_id | |
| def test_is_link(self, base_entity: LinkerEntity, link_entity: LinkerEntity): | |
| """Тест метода is_link().""" | |
| assert not base_entity.is_link() | |
| assert link_entity.is_link() | |
| def test_owner_id_property(self, base_entity: LinkerEntity, link_entity: LinkerEntity): | |
| """Тест свойства owner_id.""" | |
| # У обычной сущности owner_id это target_id | |
| owner_uuid = uuid4() | |
| base_entity.target_id = owner_uuid | |
| assert base_entity.owner_id == owner_uuid | |
| # У связи нет owner_id | |
| assert link_entity.owner_id is None | |
| # Попытка установить owner_id для связи должна вызвать ошибку | |
| with pytest.raises(ValueError, match="Связь не может иметь владельца"): | |
| link_entity.owner_id = uuid4() | |
| # Установка owner_id для обычной сущности | |
| new_owner_id = uuid4() | |
| base_entity.owner_id = new_owner_id | |
| assert base_entity.target_id == new_owner_id | |
| def test_str_representation(self, base_entity: LinkerEntity): | |
| """Тест строкового представления __str__.""" | |
| assert str(base_entity) == "Base Name: Base Text" | |
| base_entity.in_search_text = "Search text representation" | |
| assert str(base_entity) == "Search text representation" | |
| def test_equality(self, base_entity: LinkerEntity): | |
| """Тест сравнения __eq__.""" | |
| entity_copy = LinkerEntity( | |
| id=base_entity.id, name="Base Name", text="Base Text" | |
| ) | |
| different_entity = LinkerEntity(name="Different Name") | |
| assert base_entity == entity_copy | |
| assert base_entity != different_entity | |
| assert base_entity != "not an entity" | |
| def test_equality_links(self, link_entity: LinkerEntity): | |
| """Тест сравнения связей.""" | |
| link_copy = LinkerEntity( | |
| id=link_entity.id, | |
| name="Link Name", | |
| source_id=link_entity.source_id, | |
| target_id=link_entity.target_id, | |
| number_in_relation=1, | |
| ) | |
| different_link = LinkerEntity( | |
| id=link_entity.id, | |
| name="Link Name", | |
| source_id=uuid4(), # Другой source_id | |
| target_id=link_entity.target_id, | |
| number_in_relation=1, | |
| ) | |
| non_link = LinkerEntity(id=link_entity.id) | |
| assert link_entity == link_copy | |
| assert link_entity != different_link | |
| assert link_entity != non_link | |
| # --- Тесты сериализации/десериализации --- | |
| def test_serialize_base_entity(self, base_entity: LinkerEntity): | |
| """Тест сериализации базовой сущности.""" | |
| serialized = base_entity.serialize() | |
| assert isinstance(serialized, LinkerEntity) | |
| # Проверяем, что это не тот же самый объект, а копия базового типа | |
| assert serialized is not base_entity | |
| assert type(serialized) is LinkerEntity | |
| assert serialized.id == base_entity.id | |
| assert serialized.name == base_entity.name | |
| assert serialized.text == base_entity.text | |
| assert serialized.metadata == {} # Нет доп. полей | |
| assert serialized.type == "LinkerEntity" # Сохраняем тип | |
| def test_serialize_custom_entity( | |
| self, | |
| custom_entity_instance: CustomEntity, | |
| serialized_custom_entity: LinkerEntity, | |
| ): | |
| """Тест сериализации кастомной сущности.""" | |
| serialized = serialized_custom_entity # Используем фикстуру | |
| assert isinstance(serialized, LinkerEntity) | |
| assert type(serialized) is LinkerEntity | |
| assert serialized.id == custom_entity_instance.id | |
| assert serialized.name == custom_entity_instance.name | |
| assert serialized.text == custom_entity_instance.text | |
| # Проверяем, что кастомное поле и исходные метаданные попали в metadata | |
| assert "_custom_field" in serialized.metadata | |
| assert serialized.metadata["_custom_field"] == "custom_value" | |
| assert "existing_meta" in serialized.metadata | |
| assert serialized.metadata["existing_meta"] == "meta_value" | |
| # Тип должен быть именем кастомного класса | |
| assert serialized.type == "CustomEntity" | |
| def test_deserialize_custom_entity( | |
| self, serialized_custom_entity: LinkerEntity | |
| ): | |
| """Тест десериализации в кастомный тип.""" | |
| # Используем класс CustomEntity для десериализации, так как он зарегистрирован | |
| deserialized = LinkerEntity._deserialize(serialized_custom_entity) | |
| assert isinstance(deserialized, CustomEntity) | |
| assert deserialized.id == serialized_custom_entity.id | |
| assert deserialized.name == serialized_custom_entity.name | |
| assert deserialized.text == serialized_custom_entity.text | |
| # Проверяем восстановление кастомного поля | |
| assert deserialized.custom_field == "custom_value" | |
| # Проверяем восстановление исходных метаданных | |
| assert "existing_meta" in deserialized.metadata | |
| assert deserialized.metadata["existing_meta"] == "meta_value" | |
| assert deserialized.type == "CustomEntity" # Тип сохраняется | |
| def test_deserialize_base_entity(self, base_entity: LinkerEntity): | |
| """Тест десериализации базовой сущности (должна вернуться сама).""" | |
| serialized = base_entity.serialize() # Сериализуем базовую | |
| deserialized = LinkerEntity._deserialize(serialized) | |
| assert deserialized is serialized # Возвращается исходный объект LinkerEntity | |
| assert type(deserialized) is LinkerEntity | |
| def test_deserialize_unregistered_type(self): | |
| """Тест десериализации незарегистрированного типа (должен вернуться исходный объект).""" | |
| unregistered_entity = LinkerEntity(id=uuid4(), type="UnregisteredType") | |
| deserialized = LinkerEntity._deserialize(unregistered_entity) | |
| assert deserialized is unregistered_entity | |
| assert deserialized.type == "UnregisteredType" | |
| def test_deserialize_to_me_on_custom_class( | |
| self, serialized_custom_entity: LinkerEntity | |
| ): | |
| """Тест прямого вызова _deserialize_to_me на кастомном классе.""" | |
| # Вызываем метод десериализации непосредственно у CustomEntity | |
| deserialized = CustomEntity._deserialize_to_me(serialized_custom_entity) | |
| assert isinstance(deserialized, CustomEntity) | |
| assert deserialized.id == serialized_custom_entity.id | |
| assert deserialized.custom_field == "custom_value" | |
| assert deserialized.metadata["existing_meta"] == "meta_value" | |
| def test_deserialize_to_me_type_error(self): | |
| """Тест ошибки TypeError в _deserialize_to_me при неверном типе данных.""" | |
| with pytest.raises(TypeError): | |
| # Пытаемся десериализовать не LinkerEntity | |
| CustomEntity._deserialize_to_me("not_an_entity") # type: ignore | |
| def test_register_entity_decorator(self): | |
| """Тест работы декоратора @register_entity.""" | |
| class TempEntity(LinkerEntity): | |
| temp_field: str = "temp" | |
| type: str = "Temporary" # Явно указываем тип для регистрации | |
| assert "Temporary" in LinkerEntity._entity_classes | |
| assert LinkerEntity._entity_classes["Temporary"] is TempEntity | |
| # Проверяем, что он десериализуется | |
| instance = TempEntity(id=uuid4(), name="Temp instance", temp_field="value") | |
| serialized = instance.serialize() | |
| assert serialized.type == "Temporary" | |
| deserialized = LinkerEntity._deserialize(serialized) | |
| assert isinstance(deserialized, TempEntity) | |
| assert deserialized.temp_field == "value" | |
| # Удаляем временный класс из реестра, чтобы не влиять на другие тесты | |
| del LinkerEntity._entity_classes["Temporary"] | |
| assert "Temporary" not in LinkerEntity._entity_classes |