[DTP-Worker 20260805_124241] FIX test-precision (surface neuve) : test_audit_4big.py figeait totals["pass"] = 18 - fail alors que le périmètre a grandi à 24 modules → le rapport « bad » de test_failing_module_forces_global_fail déclenchait INV7 (visé) MAIS AUSSI 2× INV8 (pass+fail=18≠24 modules ET min/max incohérents), contredisant son propre commentaire « rapport cohérent en interne ». Test relâché passant pour de mauvaises raisons + constante latente périmée. FIX (test only, 0 prod, 0 artefact rebuild) : totaux dérivés du vrai bad["modules"] (pass=len-fail, min/max=min/max(scores)) → rapport réellement cohérent, seul INV7 mord ; assertion resserrée any("< seuil") → all("INV7")+any("< seuil") prouve l'isolation. Preuve : rejeu de l'ancien 18 renvoie bien [INV7, INV8, INV8] et la nouvelle assertion échouerait dessus (dents réelles). 34 tests OK, 33 PASS CI. 0 gate ajouté (#5), 0 chiffre saisi (#6), 0 VPS (#8).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1164,3 +1164,49 @@ sens). Recoupé au décompte du gate lui-même (`ls ci/*.sh` hors `lib.sh` = **8
|
||||
**0 chiffre inventé/saisi** (#6 — tout dérivé de `json.load`/`ls`/`--list`), **0 commande VPS** (#8),
|
||||
**aucun `git clean`** (#1). <!-- ci-allow : mention de l'interdit, jamais exécuté --> Le daily_report
|
||||
est **exact et courant** → laissé intact (l'éditer serait du churn). Seule édition : ce log. `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** (inchangé).
|
||||
|
||||
---
|
||||
|
||||
## Session `20260805_124241` — FIX test-precision : constante `18` périmée + commentaire faux dans `test_audit_4big.py`
|
||||
|
||||
**Surface NEUVE (hors classes saturées).** Chasse ciblée aux surfaces non encore auditées
|
||||
(le canal usuel README/counts/docstrings/fiches est saturé, #5). Trouvaille réelle, pas un
|
||||
faux-positif : `05_deliverables_mvp/qa/audit_4big/tests/test_audit_4big.py`
|
||||
`test_failing_module_forces_global_fail` figeait `bad["totals"]["pass"] = 18 - fail`.
|
||||
|
||||
**Le défaut.** Le périmètre audité a grandi à **24 modules** (`totals.modules == 24`, tous
|
||||
100/100), mais le test gardait l'entier **`18`** codé en dur. Résultat : le rapport « bad »
|
||||
qu'il fabrique avait `pass=17, fail=1, modules=24` → il déclenchait **INV7** (visé) MAIS
|
||||
AUSSI **INV8 `pass+fail ≠ modules`** (18≠24) *et* **INV8 `min/max score incohérents`**
|
||||
(module passé sous 95 alors que `min_score` restait 100). Or son propre commentaire affirmait
|
||||
« *Le rapport est cohérent en interne mais porte un FAIL → INV7 le signale* » — **affirmation
|
||||
fausse** : le rapport n'était PAS cohérent en interne. Le test passait quand même car son
|
||||
assertion (`any("< seuil 4Big")`) restait vraie parmi les erreurs parasites → test **relâché**,
|
||||
passant pour de mauvaises raisons, avec une constante latente qui pourrit en silence.
|
||||
|
||||
**Preuve du diagnostic (recompute indépendant).** Rejeu de l'ancien setup `18` →
|
||||
`check_invariants` renvoie exactement `[INV7 publiciste …, INV8 pass+fail ≠ modules, INV8
|
||||
min/max score incohérents]`. La nouvelle assertion `all("INV7" in e)` **échouerait** sur ce
|
||||
setup → elle a de vraies dents (pas tautologique).
|
||||
|
||||
**Le fix (test uniquement, 0 production).** Totaux dérivés du **vrai** `bad["modules"]` au lieu
|
||||
d'un entier figé :
|
||||
- `pass = len(modules) - fail` (robuste à tout futur changement de décompte, #6 — aucun
|
||||
chiffre saisi à la main)
|
||||
- `min_score/max_score = min/max(scores recomputés)`
|
||||
|
||||
Le rapport « bad » devient **réellement cohérent en interne** → INV8/INV9 ne mordent plus,
|
||||
**seul INV7** signale le module sous seuil — exactement ce que le commentaire prétend. Assertion
|
||||
resserrée de `any("< seuil 4Big")` (relâchée) vers `errs non vide` + `all("INV7")` + `any("< seuil
|
||||
4Big")` : prouve désormais l'**isolation** d'INV7 comme unique déclencheur.
|
||||
|
||||
**Portée / anti-churn.** **0 fichier de production édité** (seul un fichier de test), **0
|
||||
artefact reconstruit** (aucun `out/*.json` touché → pas de rebuild `quality_report`, cf.
|
||||
[[audit4big-rebuild-after-doc-edits]]), **0 gate ajouté** (#5), **0 chiffre inventé** (#6 —
|
||||
tout dérivé de `len()`/`min`/`max`), **0 commande VPS** (#8), **aucun `git clean`** (#1).
|
||||
<!-- ci-allow : mention de l'interdit, jamais exécuté -->
|
||||
|
||||
**Vérif.** `python3 -m unittest discover -s tests` → **34 tests OK** ; `./run_ci.sh` → **33
|
||||
PASS · 0 FAIL · 0 SKIP**. Distinct de la classe *toothless-test/inert-mutation*
|
||||
([[module-suite-teeth-mutation]]) : ici la LOGIQUE testée est saine — c'est le HARNAIS de test
|
||||
(données figées) qui avait dérivé.
|
||||
|
||||
Reference in New Issue
Block a user