"""Tests unitaires du module pipeline.referentials. Compatible pytest ET exécution directe (`python tests/test_referentials.py`). Nécessite que la base SQLite ait déjà été construite : python -m pipeline.referentials --build """ from __future__ import annotations import sys from pathlib import Path # Permet l'exécution directe depuis tests/ sans installer le package. sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from pipeline.referentials import ( # noqa: E402 DB_PATH, ghm_to_ghs, get_cim10_libelle, is_valid_ccam, is_valid_cim10, is_valid_ghm, is_valid_ghs, nearest_cim10, ) # --------------------------------------------------------------------------- # CIM-10 # --------------------------------------------------------------------------- def test_cim10_codes_valides(): """Quelques codes courants du référentiel PMSI.""" assert is_valid_cim10("K650") # Péritonite aigüe assert is_valid_cim10("T814") # Infection après acte assert is_valid_cim10("I10") # Hypertension essentielle assert is_valid_cim10("Z515") # Soins palliatifs assert is_valid_cim10("C509") # Tumeur maligne du sein def test_cim10_normalisation(): """Tolère le point décimal (K65.0) et la casse (k650).""" assert is_valid_cim10("K65.0") assert is_valid_cim10("k650") assert is_valid_cim10(" K650 ") def test_cim10_codes_invalides(): assert not is_valid_cim10("") assert not is_valid_cim10("ZZZ99") assert not is_valid_cim10("K6501234") # trop long assert not is_valid_cim10("1234") # ne commence pas par lettre assert not is_valid_cim10("K65X") # suffixe non numérique def test_cim10_libelle(): lib = get_cim10_libelle("K650") assert lib is not None and "éritonit" in lib.lower() or "peritonit" in lib.lower() def test_cim10_nearest_correction_ocr(): # O (lettre) lu au lieu de 0 (chiffre) assert nearest_cim10("K65O") == "K650" # Code déjà valide : renvoyé tel quel assert nearest_cim10("K650") == "K650" # Aucune correspondance à distance <= 1 assert nearest_cim10("ZZZZZ", max_distance=1) is None # --------------------------------------------------------------------------- # CCAM # --------------------------------------------------------------------------- def test_ccam_codes_valides(): assert is_valid_ccam("EBFA012") assert is_valid_ccam("HFCC003") # Bypass gastrique (mentionné dans la V5) assert is_valid_ccam("ebfa012") # casse insensible assert is_valid_ccam("EBFA012-1") # extension PMSI tolérée def test_ccam_codes_invalides(): assert not is_valid_ccam("AAAA000") assert not is_valid_ccam("") assert not is_valid_ccam("EBF012") # 3 lettres au lieu de 4 # --------------------------------------------------------------------------- # GHM # --------------------------------------------------------------------------- def test_ghm_codes_valides(): assert is_valid_ghm("01C031") assert is_valid_ghm("01c031") def test_ghm_codes_invalides(): assert not is_valid_ghm("99Z99Z") assert not is_valid_ghm("") assert not is_valid_ghm("ABCDEF") # --------------------------------------------------------------------------- # GHS et couplage GHM→GHS # --------------------------------------------------------------------------- def test_ghs_valide(): assert is_valid_ghs("22") assert is_valid_ghs("0022") # zéros de tête tolérés assert not is_valid_ghs("99999") assert not is_valid_ghs("") def test_ghm_to_ghs(): ghs = ghm_to_ghs("01C031") assert "22" in ghs # GHM inexistant → liste vide assert ghm_to_ghs("99Z99Z") == [] # --------------------------------------------------------------------------- # Exécution directe (sans pytest) # --------------------------------------------------------------------------- def _main() -> int: import traceback tests = [ ("test_cim10_codes_valides", test_cim10_codes_valides), ("test_cim10_normalisation", test_cim10_normalisation), ("test_cim10_codes_invalides", test_cim10_codes_invalides), ("test_cim10_libelle", test_cim10_libelle), ("test_cim10_nearest_correction_ocr", test_cim10_nearest_correction_ocr), ("test_ccam_codes_valides", test_ccam_codes_valides), ("test_ccam_codes_invalides", test_ccam_codes_invalides), ("test_ghm_codes_valides", test_ghm_codes_valides), ("test_ghm_codes_invalides", test_ghm_codes_invalides), ("test_ghs_valide", test_ghs_valide), ("test_ghm_to_ghs", test_ghm_to_ghs), ] if not DB_PATH.exists(): print(f"ERREUR : base SQLite manquante ({DB_PATH}).") print("Exécute d'abord : python -m pipeline.referentials --build") return 2 failures = 0 for name, fn in tests: try: fn() print(f" [OK ] {name}") except AssertionError as e: print(f" [FAIL] {name} — {e}") failures += 1 except Exception: print(f" [ERR] {name}") traceback.print_exc() failures += 1 print(f"=== {len(tests) - failures}/{len(tests)} tests OK ===") return 0 if failures == 0 else 1 if __name__ == "__main__": sys.exit(_main())