"""Tests pour le module de sévérité heuristique (CMA/CMS).""" import pytest from src.config import Diagnostic from src.medical.severity import ( evaluate_severity, enrich_dossier_severity, _detect_severity_markers, _is_heuristic_cma, _load_cma_levels, ) class TestDetectSeverityMarkers: def test_severe_markers(self): niveau, marqueurs = _detect_severity_markers("Pancréatite aiguë sévère") assert niveau == "severe" assert any(m in ("severe", "aigue") for m in marqueurs) def test_moderate_markers(self): niveau, marqueurs = _detect_severity_markers("Insuffisance rénale modérée") assert niveau == "modere" assert "modere" in marqueurs or "moderee" in marqueurs def test_mild_markers(self): niveau, marqueurs = _detect_severity_markers("Anémie chronique bénigne") assert niveau == "leger" assert any(m in ("chronique", "benin", "benigne") for m in marqueurs) def test_no_markers(self): niveau, marqueurs = _detect_severity_markers("Hypertension artérielle") assert niveau == "non_evalue" assert marqueurs == [] def test_severe_overrides_mild(self): """Si 'sévère' et 'chronique' sont présents, 'severe' l'emporte.""" niveau, marqueurs = _detect_severity_markers("Insuffisance cardiaque chronique décompensée") assert niveau == "severe" class TestHeuristicCMA: def test_e11_is_cma(self): assert _is_heuristic_cma("E11.9") is True def test_i48_is_cma(self): assert _is_heuristic_cma("I48.9") is True def test_a41_is_cma(self): assert _is_heuristic_cma("A41.9") is True def test_k85_not_cma(self): assert _is_heuristic_cma("K85.1") is False def test_i10_not_cma(self): assert _is_heuristic_cma("I10") is False def test_empty(self): assert _is_heuristic_cma("") is False assert _is_heuristic_cma(None) is False class TestCMALevels: """Tests pour le lookup CMA officiel ATIH.""" def test_load_cma_levels(self): levels = _load_cma_levels() assert len(levels) > 0 # A01.0 est severity 2 dans cocoa_entries assert levels.get("A01.0") == 2 def test_official_level_4(self): """Un code CMA niveau 4 est bien détecté.""" levels = _load_cma_levels() level4_codes = [k for k, v in levels.items() if v == 4] assert len(level4_codes) > 0 def test_official_level_propagated(self): """evaluate_severity propage le niveau CMA officiel.""" levels = _load_cma_levels() # Prendre un code de niveau 3 code_lv3 = next((k for k, v in levels.items() if v == 3), None) if code_lv3: diag = Diagnostic(texte="Test diagnostic", cim10_suggestion=code_lv3) info = evaluate_severity(diag) assert info.niveau_cma == 3 assert info.est_cma_probable is True def test_heuristic_fallback_level_2(self): """Un code heuristique CMA sans entrée officielle → niveau 2.""" # E11.9 est dans les racines heuristiques ET dans le fichier officiel # Testons avec un code heuristique qui n'est pas dans le fichier officiel diag = Diagnostic(texte="Test", cim10_suggestion="E11.9") info = evaluate_severity(diag) assert info.est_cma_probable is True assert info.niveau_cma >= 2 def test_non_cma_remains_level_1(self): """Un code non-CMA reste au niveau 1.""" diag = Diagnostic(texte="Grippe", cim10_suggestion="J11.1") info = evaluate_severity(diag) if not info.est_cma_probable: assert info.niveau_cma == 1 class TestEvaluateSeverity: def test_cma_code_detected(self): diag = Diagnostic(texte="Diabète type 2", cim10_suggestion="E11.9") info = evaluate_severity(diag) assert info.est_cma_probable is True def test_non_cma_code(self): """Un code non CMA (J11.1 grippe) n'est pas détecté comme CMA.""" diag = Diagnostic(texte="Grippe", cim10_suggestion="J11.1") info = evaluate_severity(diag) assert info.est_cma_probable is False def test_severity_from_text(self): diag = Diagnostic(texte="Sepsis sévère", cim10_suggestion="A41.9") info = evaluate_severity(diag) assert info.niveau_severite == "severe" assert info.est_cma_probable is True def test_combined_text_and_dict_label(self): """Le label du dictionnaire CIM-10 enrichit la détection de sévérité.""" diag = Diagnostic(texte="Embolie pulmonaire", cim10_suggestion="I26.9") info = evaluate_severity(diag) assert info.est_cma_probable is True def test_niveau_cma_in_result(self): """Le champ niveau_cma est toujours renseigné.""" diag = Diagnostic(texte="Sepsis", cim10_suggestion="A41.9") info = evaluate_severity(diag) assert info.niveau_cma >= 1 class TestEnrichDossierSeverity: def test_enriches_das_in_place(self): dp = Diagnostic(texte="Pancréatite aiguë biliaire", cim10_suggestion="K85.1") das = [ Diagnostic(texte="Fibrillation auriculaire", cim10_suggestion="I48.9"), Diagnostic(texte="Obésité", cim10_suggestion="E66.0"), ] alertes, cma_count, cms_count = enrich_dossier_severity(dp, das) # I48.9 = CMA probable assert das[0].est_cma is True assert das[0].niveau_severite is not None # E66.0 = non CMA assert das[1].est_cma is None # Au moins une alerte CMA assert any("CMA" in a for a in alertes) assert cma_count >= 1 def test_dp_severity_set(self): dp = Diagnostic(texte="Sepsis sévère", cim10_suggestion="A41.9") alertes, cma_count, cms_count = enrich_dossier_severity(dp, []) assert dp.niveau_severite == "severe" assert dp.est_cma is True def test_cms_detection(self): """CMS détecté quand CMA + sévérité severe.""" dp = Diagnostic(texte="Pancréatite", cim10_suggestion="K85.1") das = [ Diagnostic(texte="Sepsis sévère", cim10_suggestion="A41.9"), ] alertes, cma_count, cms_count = enrich_dossier_severity(dp, das) assert das[0].est_cma is True assert das[0].est_cms is True assert cms_count == 1 def test_niveau_cma_set_on_das(self): """enrich_dossier_severity propage niveau_cma sur chaque DAS.""" dp = Diagnostic(texte="Pancréatite", cim10_suggestion="K85.1") das = [ Diagnostic(texte="Fibrillation auriculaire", cim10_suggestion="I48.9"), ] enrich_dossier_severity(dp, das) assert das[0].niveau_cma is not None assert das[0].niveau_cma >= 2 def test_alertes_contain_cma_level(self): """Les alertes mentionnent le niveau CMA.""" dp = Diagnostic(texte="Test", cim10_suggestion="K85.1") das = [ Diagnostic(texte="Sepsis", cim10_suggestion="A41.9"), ] alertes, _, _ = enrich_dossier_severity(dp, das) assert any("CMA niveau" in a for a in alertes)