medgraph-engine/tests/test_basic.py

177 lines
6.2 KiB
Python

"""Basic tests for MedGraph Engine core components."""
import os
import sys
import json
import pytest
# Add parent dir to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class TestParser:
"""Test PDF parser and chunking logic."""
def test_normalize_name(self):
from extract_entities import normalize_name
assert normalize_name(" Otitis Media Aguda ") == "otitis media aguda"
assert normalize_name("hipertensión...") == "hipertensión"
assert normalize_name(" múltiples espacios ") == "múltiples espacios"
assert normalize_name("") == ""
def test_strip_accents(self):
from dedup_entities import strip_accents
assert strip_accents("hipertensión") == "hipertension"
assert strip_accents("diagnóstico") == "diagnostico"
assert strip_accents("farmacología") == "farmacologia"
assert strip_accents("normal") == "normal"
def test_has_accents(self):
from dedup_entities import has_accents
assert has_accents("hipertensión") is True
assert has_accents("hipertension") is False
def test_pick_canonical(self):
from dedup_entities import pick_canonical
nodes = [
{"nombre": "hipertension", "freq": 10, "sinonimos": []},
{"nombre": "hipertensión", "freq": 5, "sinonimos": ["HTA"]},
]
canon = pick_canonical(nodes)
assert canon["nombre"] == "hipertensión" # prefers accented
def test_find_accent_groups(self):
from dedup_entities import find_accent_groups
entities = [
{"nombre": "hipertensión"},
{"nombre": "hipertension"},
{"nombre": "diabetes"},
]
groups = find_accent_groups(entities)
assert len(groups) == 1
assert "hipertension" in groups
assert len(groups["hipertension"]) == 2
class TestChunking:
"""Test chunking parameters and structure."""
def test_chunk_config_values(self):
from parser_v2 import TARGET_SIZE, MIN_SIZE, MAX_SIZE, OVERLAP_SIZE
assert TARGET_SIZE == 280
assert MIN_SIZE == 150
assert MAX_SIZE == 380
assert OVERLAP_SIZE == 60
assert MIN_SIZE < TARGET_SIZE < MAX_SIZE
def test_parent_config(self):
from parser_v2 import PARENT_WINDOW, MAX_PARENT_WORDS
assert PARENT_WINDOW == 3
assert MAX_PARENT_WORDS == 1200
class TestExtraction:
"""Test entity extraction validation logic."""
def test_validate_entity_types(self):
from extract_entities import ENTITY_TYPES
expected = {
"patologia", "estructura_anatomica", "procedimiento",
"farmaco", "grupo_farmacologico", "agente", "signo",
"sintoma", "metodo_dx", "hallazgo", "parametro",
}
assert ENTITY_TYPES == expected
def test_validate_relation_types(self):
from extract_entities import RELATION_TYPES
assert "CAUSADA_POR" in RELATION_TYPES
assert "SE_TRATA_CON" in RELATION_TYPES
assert "SE_DIAGNOSTICA_CON" in RELATION_TYPES
assert "ASOCIADA_A" in RELATION_TYPES
def test_type_to_label_mapping(self):
from extract_entities import TYPE_TO_LABEL
assert TYPE_TO_LABEL["patologia"] == "Patologia"
assert TYPE_TO_LABEL["farmaco"] == "Farmaco"
assert TYPE_TO_LABEL["estructura_anatomica"] == "EstructuraAnatomica"
def test_validate_extraction_filters_invalid(self):
from extract_entities import _validate_extraction
data = {
"entidades": [
{"nombre": "otitis media", "tipo": "patologia", "sinonimos": []},
{"nombre": "x", "tipo": "patologia", "sinonimos": []}, # too short
{"nombre": "valid", "tipo": "INVALID_TYPE", "sinonimos": []}, # bad type
{"nombre": "", "tipo": "patologia", "sinonimos": []}, # empty
],
"relaciones": []
}
result = _validate_extraction(data, {"id": "test", "libro_id": "test"})
assert len(result["entidades"]) == 1
assert result["entidades"][0]["nombre"] == "otitis media"
class TestCanonicalization:
"""Test entity canonicalization logic."""
def test_canonicalize_merges_duplicates(self):
from extract_entities import canonicalize_entities
extractions = [
{
"entidades": [
{"nombre": "otitis media", "tipo": "patologia", "sinonimos": ["OMA"]},
],
"relaciones": [],
"chunk_id": "c1",
},
{
"entidades": [
{"nombre": "otitis media", "tipo": "patologia", "sinonimos": []},
],
"relaciones": [],
"chunk_id": "c2",
},
]
entities, relations = canonicalize_entities(extractions)
# Should merge into 1 entity
otitis = [e for e in entities if e["nombre"] == "otitis media"]
assert len(otitis) == 1
assert otitis[0]["freq"] == 2
assert "OMA" in otitis[0]["sinonimos"]
class TestAPIConfig:
"""Test API configuration basics."""
def test_env_example_exists(self):
assert os.path.exists(
os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env.example")
)
def test_requirements_no_vertexai(self):
req_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "api", "requirements.txt"
)
with open(req_path) as f:
content = f.read()
assert "vertexai" not in content.lower()
assert "aiplatform" not in content.lower()
def test_docker_compose_exists(self):
assert os.path.exists(
os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "docker-compose.yml")
)
def test_docker_compose_no_real_credentials(self):
compose_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "docker-compose.yml"
)
with open(compose_path) as f:
content = f.read()
assert "changeme" in content
assert "AIzaSy" not in content
if __name__ == "__main__":
pytest.main([__file__, "-v"])