Étend `RE_RPPS` pour tolérer 0 à 3 mots qualificateurs entre `RPPS` et le séparateur `:` ou `-`. Couvre les variantes observées : - RPPS prescripteur : - RPPS du médecin signataire : - RPPS de garde - - N° RPPS : Si un qualificateur est présent, le séparateur (`:` ou `-`) devient obligatoire pour éviter d'aspirer du narratif (faux positif type "Le RPPS est consulté pour vérifier 12345678901 dans la base"). La lambda `_repl_rpps` reconstruit `RPPS : [RPPS]` en sortie : le qualificateur est consommé mais perdu (pas de fuite, choix cosmétique). Cas 005_bacterio_complete passe désormais (retiré de KNOWN_FAILURES). La fuite `10101010101` derrière `RPPS prescripteur :` est masquée. Cohérent avec le cadrage section 10.1 (règle cœur générique applicable à tout établissement de santé français — pas de spécificité locale). Tests : 72 passed, 1 xfailed (avant : 71 passed, 2 xfailed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Gate pytest sur le corpus synthétique de revue humaine (couche 2).
|
|
|
|
Chaque cas dans tests/synthetic_review/cases/ doit produire un texte
|
|
identique à expected.txt, satisfaire ses expectations.json et ne révéler
|
|
aucune fuite via le LeakScanner.
|
|
|
|
Les cas listés dans KNOWN_FAILURES sont marqués xfail(strict=True) :
|
|
ils sont attendus en échec aujourd'hui car ils révèlent des bugs réels
|
|
du moteur. Quand un bug est fixé, le cas correspondant passe → pytest
|
|
signale le xpass strict, ce qui force à retirer son entrée de
|
|
KNOWN_FAILURES.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from tools.run_synthetic_review_corpus import ( # noqa: E402
|
|
CASES_DIR,
|
|
run_case,
|
|
)
|
|
|
|
|
|
KNOWN_FAILURES: dict[str, str] = {
|
|
"009_multi_etablissements": (
|
|
"Fuites résiduelles : suffixe `de Bordeaux` après "
|
|
"[ETABLISSEMENT], CHCB en fin de phrase. À traiter via "
|
|
"admin_rules (étape B suivante)."
|
|
),
|
|
}
|
|
|
|
|
|
def _case_dirs() -> list[Path]:
|
|
if not CASES_DIR.exists():
|
|
return []
|
|
return sorted(path for path in CASES_DIR.iterdir() if path.is_dir())
|
|
|
|
|
|
def _make_param(case_dir: Path) -> "pytest.ParameterSet":
|
|
if case_dir.name in KNOWN_FAILURES:
|
|
return pytest.param(
|
|
case_dir,
|
|
id=case_dir.name,
|
|
marks=pytest.mark.xfail(
|
|
strict=True,
|
|
reason=KNOWN_FAILURES[case_dir.name],
|
|
),
|
|
)
|
|
return pytest.param(case_dir, id=case_dir.name)
|
|
|
|
|
|
def test_synthetic_review_inventory():
|
|
"""Le corpus doit contenir 10 cas (cible de cadrage produit)."""
|
|
assert CASES_DIR.exists(), f"Dossier corpus introuvable : {CASES_DIR}"
|
|
case_dirs = _case_dirs()
|
|
assert len(case_dirs) == 10, (
|
|
f"Attendu 10 cas dans synthetic_review/cases, trouvé {len(case_dirs)} : "
|
|
f"{[c.name for c in case_dirs]}"
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("case_dir", [_make_param(c) for c in _case_dirs()])
|
|
def test_synthetic_review_case(case_dir: Path):
|
|
result = run_case(case_dir)
|
|
assert not result["failures"], (
|
|
f"{case_dir.name} : {', '.join(result['failures'])}\n"
|
|
f"Diff disponible dans {result['output_dir']}/diff.txt"
|
|
)
|