Files
t2a_v2/tests/test_ghm.py
dom a58398f5d4 feat: cache Ollama + parallélisation ThreadPool + filtrage DAS renforcé + modules GHM/CPAM/export RUM
- Cache persistant JSON thread-safe pour les résultats Ollama (invalidation par modèle)
- Parallélisation des appels Ollama (ThreadPoolExecutor, 2 workers)
- 6 nouvelles règles de filtrage DAS parasites (doublons, ponctuation, OCR, labo, fragments)
- Client Ollama centralisé (mode JSON natif + retry)
- Module GHM (estimation CMD/sévérité)
- Module contrôle CPAM (parser + contre-argumentation RAG)
- Export RUM (format RSS)
- Viewer enrichi (détail dossier)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 13:44:34 +01:00

190 lines
6.0 KiB
Python

"""Tests pour le module d'estimation GHM."""
import pytest
from src.config import ActeCCAM, Diagnostic, DossierMedical
from src.medical.ghm import estimate_ghm, find_cmd, _detect_type_ghm, _compute_severity
class TestFindCMD:
def test_k85_hepatobilaire(self):
cmd, libelle = find_cmd("K85.1")
assert cmd == "07"
assert "hépatobiliaire" in libelle.lower() or "pancréat" in libelle.lower()
def test_j18_respiratoire(self):
cmd, _ = find_cmd("J18")
assert cmd == "04"
def test_n17_renal(self):
cmd, _ = find_cmd("N17")
assert cmd == "11"
def test_n40_genital_masculin(self):
cmd, _ = find_cmd("N40")
assert cmd == "12"
def test_f10_toxicomanie(self):
cmd, _ = find_cmd("F10")
assert cmd == "20"
def test_z00_facteurs(self):
cmd, _ = find_cmd("Z00")
assert cmd == "23"
def test_k40_digestif(self):
cmd, _ = find_cmd("K40")
assert cmd == "06"
def test_b20_vih(self):
cmd, _ = find_cmd("B20")
assert cmd == "25"
def test_t25_brulures(self):
cmd, _ = find_cmd("T25")
assert cmd == "22"
def test_s72_traumatismes(self):
cmd, _ = find_cmd("S72")
assert cmd == "21"
def test_code_with_dot(self):
cmd, _ = find_cmd("K85.1")
assert cmd == "07"
def test_code_lowercase(self):
cmd, _ = find_cmd("k85.1")
assert cmd == "07"
def test_empty_code(self):
cmd, libelle = find_cmd("")
assert cmd is None
assert libelle is None
def test_none_code(self):
cmd, libelle = find_cmd(None)
assert cmd is None
assert libelle is None
def test_short_code(self):
cmd, libelle = find_cmd("K8")
assert cmd is None
class TestDetectTypeGHM:
def test_chirurgical(self):
actes = [ActeCCAM(texte="Cholécystectomie", code_ccam_suggestion="HMFC004")]
assert _detect_type_ghm(actes) == "C"
def test_interventionnel(self):
actes = [ActeCCAM(texte="Échographie", code_ccam_suggestion="ZCQM001")]
assert _detect_type_ghm(actes) == "K"
def test_medical_no_actes(self):
assert _detect_type_ghm([]) == "M"
def test_medical_no_code(self):
actes = [ActeCCAM(texte="Biopsie", code_ccam_suggestion=None)]
assert _detect_type_ghm(actes) == "M"
def test_chirurgical_overrides_interventionnel(self):
actes = [
ActeCCAM(texte="Écho", code_ccam_suggestion="ZCQM001"),
ActeCCAM(texte="Cholécystectomie", code_ccam_suggestion="HMFC004"),
]
assert _detect_type_ghm(actes) == "C"
class TestSeverityLevels:
def test_no_cma_level_1(self):
das = [Diagnostic(texte="HTA", cim10_suggestion="I10")]
niveau, cma, cms = _compute_severity(das)
assert niveau == 1
def test_two_cma_level_2(self):
das = [
Diagnostic(texte="FA", cim10_suggestion="I48.9", est_cma=True),
Diagnostic(texte="IRA", cim10_suggestion="N17.9", est_cma=True),
]
niveau, cma, cms = _compute_severity(das)
assert niveau == 2
assert cma == 2
def test_one_cms_level_3(self):
das = [
Diagnostic(texte="Sepsis sévère", cim10_suggestion="A41.9", est_cma=True, est_cms=True),
]
niveau, cma, cms = _compute_severity(das)
assert niveau == 3
assert cms == 1
def test_two_cms_level_4(self):
das = [
Diagnostic(texte="Sepsis", cim10_suggestion="A41.9", est_cma=True, est_cms=True),
Diagnostic(texte="IRA", cim10_suggestion="N17.9", est_cma=True, est_cms=True),
]
niveau, cma, cms = _compute_severity(das)
assert niveau == 4
assert cms == 2
def test_three_cma_level_3(self):
das = [
Diagnostic(texte="FA", cim10_suggestion="I48.9", est_cma=True),
Diagnostic(texte="IRA", cim10_suggestion="N17.9", est_cma=True),
Diagnostic(texte="Diabète", cim10_suggestion="E11.9", est_cma=True),
]
niveau, cma, cms = _compute_severity(das)
assert niveau == 3
assert cma == 3
class TestEstimateGHM:
def test_chirurgical_with_cma(self):
dossier = DossierMedical(
diagnostic_principal=Diagnostic(texte="Cholécystite", cim10_suggestion="K80.1"),
actes_ccam=[ActeCCAM(texte="Cholécystectomie", code_ccam_suggestion="HMFC004")],
diagnostics_associes=[
Diagnostic(texte="FA", cim10_suggestion="I48.9", est_cma=True),
Diagnostic(texte="IRA", cim10_suggestion="N17.9", est_cma=True),
],
)
ghm = estimate_ghm(dossier)
assert ghm.cmd == "07"
assert ghm.type_ghm == "C"
assert ghm.severite == 2
assert ghm.ghm_approx == "07C??2"
assert ghm.cma_count == 2
def test_medical_sans_actes(self):
dossier = DossierMedical(
diagnostic_principal=Diagnostic(texte="Pneumonie", cim10_suggestion="J18.9"),
)
ghm = estimate_ghm(dossier)
assert ghm.cmd == "04"
assert ghm.type_ghm == "M"
assert ghm.severite == 1
assert ghm.ghm_approx == "04M??1"
def test_dp_absent(self):
dossier = DossierMedical()
ghm = estimate_ghm(dossier)
assert ghm.cmd is None
assert ghm.ghm_approx is None
assert any("DP absent" in a for a in ghm.alertes)
def test_dp_sans_code(self):
dossier = DossierMedical(
diagnostic_principal=Diagnostic(texte="Douleur thoracique"),
)
ghm = estimate_ghm(dossier)
assert ghm.cmd is None
assert any("sans code" in a for a in ghm.alertes)
def test_dp_symptomatique(self):
dossier = DossierMedical(
diagnostic_principal=Diagnostic(texte="Douleur thoracique", cim10_suggestion="R07.4"),
)
ghm = estimate_ghm(dossier)
assert ghm.cmd == "23"
assert any("symptomatique" in a for a in ghm.alertes)