Download backend/tests/test_entity_resolution.py from yusufcalisir/Collaborative-Fraud-Intelligence-Simulator: direct link, hf CLI and curl.
- Browser
- Download file 5.59 kB
-
https://huggingface.co/spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/resolve/main/backend/tests/test_entity_resolution.py
- Command line
-
hf download hf://spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/backend/tests/test_entity_resolution.py
-
curl -L -o test_entity_resolution.py https://huggingface.co/spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/resolve/main/backend/tests/test_entity_resolution.py
5.59 kB
| """Tests for entity resolution service.""" | |
| import pytest | |
| from app.application.services.entity_resolution import EntityResolutionService | |
| from app.domain.enums import EntityType, RelationshipType | |
| from app.domain.value_objects_investigation import PrivacyPreservingIdentifier | |
| def entity_service() -> EntityResolutionService: | |
| return EntityResolutionService() | |
| class TestEntityCreation: | |
| def test_create_entity(self, entity_service: EntityResolutionService) -> None: | |
| entity = entity_service.create_entity( | |
| entity_type=EntityType.CUSTOMER, | |
| raw_identifier="john.doe@email.com", | |
| bank_id="bank_a", | |
| ) | |
| assert entity.entity_type == EntityType.CUSTOMER | |
| assert entity.bank_id == "bank_a" | |
| assert entity.display_label.startswith("CUST-") | |
| assert len(entity.privacy_id) == 32 | |
| def test_deterministic_hashing(self, entity_service: EntityResolutionService) -> None: | |
| entity1 = entity_service.create_entity(EntityType.CUSTOMER, "same_id", "bank_a") | |
| # Creating again with same raw ID + bank should return existing entity | |
| entity2 = entity_service.create_entity(EntityType.CUSTOMER, "same_id", "bank_a") | |
| assert entity1.id == entity2.id | |
| def test_display_label_prefix(self, entity_service: EntityResolutionService) -> None: | |
| cust = entity_service.create_entity(EntityType.CUSTOMER, "c1", "bank_a") | |
| merch = entity_service.create_entity(EntityType.MERCHANT, "m1", "bank_a") | |
| dev = entity_service.create_entity(EntityType.DEVICE, "d1", "bank_a") | |
| assert cust.display_label.startswith("CUST-") | |
| assert merch.display_label.startswith("MERCH-") | |
| assert dev.display_label.startswith("DEV-") | |
| class TestCrossInstitutionResolution: | |
| def test_same_entity_at_different_banks(self, entity_service: EntityResolutionService) -> None: | |
| # Same raw identifier at two different banks | |
| e1 = entity_service.create_entity(EntityType.CUSTOMER, "shared_customer", "bank_a") | |
| e2 = entity_service.create_entity(EntityType.CUSTOMER, "shared_customer", "bank_b") | |
| # Same privacy hash | |
| assert e1.privacy_id == e2.privacy_id | |
| # Different entity IDs (they're different records at different banks) | |
| assert e1.id != e2.id | |
| # Cross-institution resolution should find both | |
| matches = entity_service.resolve_cross_institution(e1.privacy_id) | |
| assert len(matches) == 2 | |
| banks = {m.bank_id for m in matches} | |
| assert banks == {"bank_a", "bank_b"} | |
| def test_detect_shared_entities(self, entity_service: EntityResolutionService) -> None: | |
| entity_service.create_entity(EntityType.CUSTOMER, "shared_1", "bank_a") | |
| entity_service.create_entity(EntityType.CUSTOMER, "shared_1", "bank_b") | |
| entity_service.create_entity(EntityType.CUSTOMER, "unique_a", "bank_a") | |
| entity_service.create_entity(EntityType.CUSTOMER, "unique_b", "bank_b") | |
| matches = entity_service.detect_shared_entities("bank_a", "bank_b") | |
| assert len(matches) == 1 | |
| assert matches[0]["entity_type"] == "customer" | |
| class TestEntityProfile: | |
| def test_build_profile(self, entity_service: EntityResolutionService) -> None: | |
| entity = entity_service.create_entity(EntityType.CUSTOMER, "profile_test", "bank_a") | |
| profile = entity_service.build_entity_profile(entity.id) | |
| assert profile["entity_id"] == entity.id | |
| assert profile["entity_type"] == "customer" | |
| assert "banks_present" in profile | |
| def test_profile_nonexistent_raises(self, entity_service: EntityResolutionService) -> None: | |
| with pytest.raises(ValueError, match="Entity not found"): | |
| entity_service.build_entity_profile("nonexistent") | |
| class TestRelationships: | |
| def test_add_relationship(self, entity_service: EntityResolutionService) -> None: | |
| e1 = entity_service.create_entity(EntityType.CUSTOMER, "c1", "bank_a") | |
| e2 = entity_service.create_entity(EntityType.MERCHANT, "m1", "bank_a") | |
| rel = entity_service.add_relationship( | |
| e1.id, | |
| e2.id, | |
| RelationshipType.TRANSACTS_WITH, | |
| ) | |
| assert rel.source_entity_id == e1.id | |
| assert rel.target_entity_id == e2.id | |
| def test_relationship_appears_in_profile(self, entity_service: EntityResolutionService) -> None: | |
| e1 = entity_service.create_entity(EntityType.CUSTOMER, "c1", "bank_a") | |
| e2 = entity_service.create_entity(EntityType.DEVICE, "d1", "bank_a") | |
| entity_service.add_relationship(e1.id, e2.id, RelationshipType.USES) | |
| profile = entity_service.build_entity_profile(e1.id) | |
| assert profile["relationship_count"] == 1 | |
| class TestPrivacyPreservingIdentifier: | |
| def test_deterministic(self) -> None: | |
| h1 = PrivacyPreservingIdentifier.compute("test@email.com", "customer") | |
| h2 = PrivacyPreservingIdentifier.compute("test@email.com", "customer") | |
| assert h1 == h2 | |
| def test_case_insensitive(self) -> None: | |
| h1 = PrivacyPreservingIdentifier.compute("Test@Email.com", "customer") | |
| h2 = PrivacyPreservingIdentifier.compute("test@email.com", "customer") | |
| assert h1 == h2 | |
| def test_different_types_different_hashes(self) -> None: | |
| h1 = PrivacyPreservingIdentifier.compute("value", "customer") | |
| h2 = PrivacyPreservingIdentifier.compute("value", "merchant") | |
| assert h1 != h2 | |
| def test_hash_length(self) -> None: | |
| h = PrivacyPreservingIdentifier.compute("test", "customer") | |
| assert len(h) == 32 | |