353 lines
9.1 KiB
Python
353 lines
9.1 KiB
Python
"""
|
|
Tests for CodeMapper.
|
|
|
|
Validates: Requirements 13.2, 13.3
|
|
"""
|
|
|
|
import pytest
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
import tempfile
|
|
import yaml
|
|
|
|
from src.pipeline_mco_pmsi.referentiels import CodeMapper, CodeMapping
|
|
|
|
|
|
def test_code_mapper_initialization():
|
|
"""Test CodeMapper initialization."""
|
|
mapper = CodeMapper()
|
|
assert mapper.mappings_dir is not None
|
|
assert len(mapper.cim10_mappings) == 0
|
|
assert len(mapper.ccam_mappings) == 0
|
|
|
|
|
|
def test_add_mapping():
|
|
"""
|
|
Test adding a code mapping.
|
|
|
|
Validates: Requirement 13.2
|
|
"""
|
|
mapper = CodeMapper()
|
|
|
|
mapping = CodeMapping(
|
|
obsolete_code="J45.0",
|
|
current_code="J45.00",
|
|
obsolete_label="Asthme à prédominance allergique",
|
|
current_label="Asthme à prédominance allergique, non précisé",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split",
|
|
notes="Code divisé"
|
|
)
|
|
|
|
mapper.add_mapping(mapping, "cim10")
|
|
|
|
assert "J45.0" in mapper.cim10_mappings
|
|
assert mapper.cim10_mappings["J45.0"].current_code == "J45.00"
|
|
|
|
|
|
def test_map_obsolete_code():
|
|
"""
|
|
Test mapping an obsolete code to current code.
|
|
|
|
Validates: Requirement 13.2
|
|
"""
|
|
mapper = CodeMapper()
|
|
|
|
mapping = CodeMapping(
|
|
obsolete_code="J45.0",
|
|
current_code="J45.00",
|
|
obsolete_label="Asthme",
|
|
current_label="Asthme précisé",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split"
|
|
)
|
|
|
|
mapper.add_mapping(mapping, "cim10")
|
|
|
|
# Map obsolete code
|
|
current = mapper.map_code("J45.0", "cim10")
|
|
assert current == "J45.00"
|
|
|
|
# Current code returns None
|
|
current = mapper.map_code("J45.00", "cim10")
|
|
assert current is None
|
|
|
|
|
|
def test_add_alias():
|
|
"""
|
|
Test adding a code alias.
|
|
|
|
Validates: Requirement 13.3
|
|
"""
|
|
mapper = CodeMapper()
|
|
|
|
mapper.add_alias("K29.70", "K29.7", "cim10")
|
|
|
|
assert "K29.70" in mapper.cim10_aliases
|
|
assert mapper.cim10_aliases["K29.70"] == "K29.7"
|
|
|
|
|
|
def test_map_alias_code():
|
|
"""
|
|
Test mapping an alias code to canonical code.
|
|
|
|
Validates: Requirement 13.3
|
|
"""
|
|
mapper = CodeMapper()
|
|
|
|
mapper.add_alias("K29.70", "K29.7", "cim10")
|
|
|
|
# Map alias
|
|
canonical = mapper.map_code("K29.70", "cim10")
|
|
assert canonical == "K29.7"
|
|
|
|
|
|
def test_is_obsolete():
|
|
"""Test checking if a code is obsolete."""
|
|
mapper = CodeMapper()
|
|
|
|
mapping = CodeMapping(
|
|
obsolete_code="J45.0",
|
|
current_code="J45.00",
|
|
obsolete_label="Asthme",
|
|
current_label="Asthme précisé",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split"
|
|
)
|
|
|
|
mapper.add_mapping(mapping, "cim10")
|
|
|
|
assert mapper.is_obsolete("J45.0", "cim10") is True
|
|
assert mapper.is_obsolete("J45.00", "cim10") is False
|
|
|
|
|
|
def test_get_mapping_info():
|
|
"""Test getting detailed mapping information."""
|
|
mapper = CodeMapper()
|
|
|
|
mapping = CodeMapping(
|
|
obsolete_code="J45.0",
|
|
current_code="J45.00",
|
|
obsolete_label="Asthme",
|
|
current_label="Asthme précisé",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split",
|
|
notes="Test note"
|
|
)
|
|
|
|
mapper.add_mapping(mapping, "cim10")
|
|
|
|
info = mapper.get_mapping_info("J45.0", "cim10")
|
|
assert info is not None
|
|
assert info.current_code == "J45.00"
|
|
assert info.reason == "split"
|
|
assert info.notes == "Test note"
|
|
|
|
|
|
def test_track_label_change():
|
|
"""
|
|
Test tracking label changes.
|
|
|
|
Validates: Requirement 13.3
|
|
"""
|
|
mapper = CodeMapper()
|
|
|
|
mapper.track_label_change(
|
|
code="K29.7",
|
|
old_label="Gastrite, sans précision",
|
|
new_label="Gastrite non précisée",
|
|
referentiel_type="cim10",
|
|
effective_date=datetime(2024, 1, 1)
|
|
)
|
|
|
|
history = mapper.get_label_history("K29.7", "cim10")
|
|
assert len(history) == 1
|
|
assert history[0]["old_label"] == "Gastrite, sans précision"
|
|
assert history[0]["new_label"] == "Gastrite non précisée"
|
|
|
|
|
|
def test_load_mappings_yaml(tmp_path):
|
|
"""
|
|
Test loading mappings from YAML file.
|
|
|
|
Validates: Requirement 13.2
|
|
"""
|
|
# Create test mapping file
|
|
mapping_file = tmp_path / "test_mappings.yaml"
|
|
data = {
|
|
"referentiel_type": "cim10",
|
|
"mappings": [
|
|
{
|
|
"obsolete_code": "J45.0",
|
|
"current_code": "J45.00",
|
|
"obsolete_label": "Asthme",
|
|
"current_label": "Asthme précisé",
|
|
"effective_date": "2024-01-01T00:00:00",
|
|
"reason": "split",
|
|
"notes": "Test"
|
|
}
|
|
],
|
|
"aliases": [
|
|
{"alias": "K29.70", "canonical": "K29.7"}
|
|
]
|
|
}
|
|
|
|
with open(mapping_file, "w") as f:
|
|
yaml.dump(data, f)
|
|
|
|
mapper = CodeMapper()
|
|
count = mapper.load_mappings("cim10", mapping_file)
|
|
|
|
assert count == 1
|
|
assert "J45.0" in mapper.cim10_mappings
|
|
assert "K29.70" in mapper.cim10_aliases
|
|
|
|
|
|
def test_save_mappings_yaml(tmp_path):
|
|
"""Test saving mappings to YAML file."""
|
|
mapper = CodeMapper()
|
|
|
|
mapping = CodeMapping(
|
|
obsolete_code="J45.0",
|
|
current_code="J45.00",
|
|
obsolete_label="Asthme",
|
|
current_label="Asthme précisé",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split"
|
|
)
|
|
|
|
mapper.add_mapping(mapping, "cim10")
|
|
mapper.add_alias("K29.70", "K29.7", "cim10")
|
|
|
|
# Save to file
|
|
output_file = tmp_path / "output_mappings.yaml"
|
|
mapper.save_mappings("cim10", output_file)
|
|
|
|
assert output_file.exists()
|
|
|
|
# Load and verify
|
|
with open(output_file, "r") as f:
|
|
data = yaml.safe_load(f)
|
|
|
|
assert data["referentiel_type"] == "cim10"
|
|
assert len(data["mappings"]) == 1
|
|
assert len(data["aliases"]) == 1
|
|
|
|
|
|
def test_get_statistics():
|
|
"""Test getting mapping statistics."""
|
|
mapper = CodeMapper()
|
|
|
|
# Add multiple mappings with different reasons
|
|
mapper.add_mapping(
|
|
CodeMapping(
|
|
obsolete_code="J45.0",
|
|
current_code="J45.00",
|
|
obsolete_label="Asthme",
|
|
current_label="Asthme précisé",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split"
|
|
),
|
|
"cim10"
|
|
)
|
|
|
|
mapper.add_mapping(
|
|
CodeMapping(
|
|
obsolete_code="I25.1",
|
|
current_code="I25.10",
|
|
obsolete_label="Cardiopathie",
|
|
current_label="Cardiopathie précisée",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="split"
|
|
),
|
|
"cim10"
|
|
)
|
|
|
|
mapper.add_mapping(
|
|
CodeMapping(
|
|
obsolete_code="K29.0",
|
|
current_code="K29.00",
|
|
obsolete_label="Gastrite",
|
|
current_label="Gastrite aiguë",
|
|
effective_date=datetime(2024, 1, 1),
|
|
reason="renamed"
|
|
),
|
|
"cim10"
|
|
)
|
|
|
|
mapper.add_alias("K29.70", "K29.7", "cim10")
|
|
|
|
stats = mapper.get_statistics("cim10")
|
|
|
|
assert stats["total_mappings"] == 3
|
|
assert stats["total_aliases"] == 1
|
|
assert stats["mappings_by_reason"]["split"] == 2
|
|
assert stats["mappings_by_reason"]["renamed"] == 1
|
|
|
|
|
|
def test_ccam_mappings():
|
|
"""Test CCAM code mappings."""
|
|
mapper = CodeMapper()
|
|
|
|
mapping = CodeMapping(
|
|
obsolete_code="YYYY001",
|
|
current_code="YYYY002",
|
|
obsolete_label="Ancien acte",
|
|
current_label="Nouvel acte",
|
|
effective_date=datetime(2025, 1, 1),
|
|
reason="renamed"
|
|
)
|
|
|
|
mapper.add_mapping(mapping, "ccam")
|
|
|
|
assert "YYYY001" in mapper.ccam_mappings
|
|
assert mapper.map_code("YYYY001", "ccam") == "YYYY002"
|
|
assert mapper.is_obsolete("YYYY001", "ccam") is True
|
|
|
|
|
|
def test_multiple_label_changes():
|
|
"""Test tracking multiple label changes for same code."""
|
|
mapper = CodeMapper()
|
|
|
|
# First change
|
|
mapper.track_label_change(
|
|
code="K29.7",
|
|
old_label="Gastrite",
|
|
new_label="Gastrite, sans précision",
|
|
referentiel_type="cim10",
|
|
effective_date=datetime(2023, 1, 1)
|
|
)
|
|
|
|
# Second change
|
|
mapper.track_label_change(
|
|
code="K29.7",
|
|
old_label="Gastrite, sans précision",
|
|
new_label="Gastrite non précisée",
|
|
referentiel_type="cim10",
|
|
effective_date=datetime(2024, 1, 1)
|
|
)
|
|
|
|
history = mapper.get_label_history("K29.7", "cim10")
|
|
assert len(history) == 2
|
|
assert history[0]["effective_date"] == "2023-01-01T00:00:00"
|
|
assert history[1]["effective_date"] == "2024-01-01T00:00:00"
|
|
|
|
|
|
def test_load_nonexistent_file():
|
|
"""Test loading from nonexistent file raises error."""
|
|
mapper = CodeMapper()
|
|
|
|
with pytest.raises(FileNotFoundError):
|
|
mapper.load_mappings("cim10", Path("/nonexistent/file.yaml"))
|
|
|
|
|
|
def test_unsupported_file_format(tmp_path):
|
|
"""Test loading unsupported file format raises error."""
|
|
mapper = CodeMapper()
|
|
|
|
bad_file = tmp_path / "test.txt"
|
|
bad_file.write_text("test")
|
|
|
|
with pytest.raises(ValueError, match="Unsupported file format"):
|
|
mapper.load_mappings("cim10", bad_file)
|