Que fait test-suite-doctor ?
Réduisez une suite de tests surdimensionnée (par exemple, plus de 2 000 tests, dont une grande partie générée par IA) en une petite suite de haute qualité tout en conservant une part configurable de la couverture réelle — mesurée, pas devinée.
Règles strictes
- Les métriques avant les opinions. Ne proposez jamais de supprimer un test avant que
collectetminimizeaient produit un plan. Lire le code d'un test et le juger « inutile » n'est pas une preuve — un test d'apparence anodine peut être le seul à couvrir une branche. - Le plan est une proposition, pas un verdict. La couverture ne peut pas voir les contrats d'API, les cas de régression documentés ou les invariants de propriété. Chaque candidat à la suppression est examiné (étape 3) avant d'être supprimé.
- Travaillez sur une branche. Avant de supprimer quoi que ce soit, vérifiez que l'arbre de travail est propre et créez une branche (par exemple
test-doctor/minimize). Ne supprimez jamais de tests sur un arbre sale ou sur la branche par défaut. - Vérifiez ou annulez. Le travail n'est pas terminé tant que
verifyne sort pas avec le code 0. En cas d'échec, régénérez les tests pour les lacunes signalées et revérifiez — ou restaurez les tests supprimés.
Vérification des prérequis (à faire en premier)
- Node.js ≥ 22 et un package.json utilisant Vitest ou Jest installé localement (
node <chemin-compétence>/dist/cli.mjs collect --help). - Un fournisseur de couverture doit être installé (Vitest :
@vitest/coverage-v8; Jest en intègre un). S'il manque, proposez de l'installer comme dépendance de développement. - La vérification par mutation nécessite en plus
@stryker-mutator/coreconfiguré dans le dépôt cible — elle est facultative, ne l'installez pas sans y être invité. - La suite doit être verte avant de commencer. Si l'exécution de référence signale des échecs, informez l'utilisateur et obtenez son accord sur la manière de les traiter avant de minimiser (les tests en échec fournissent une couverture peu fiable).
Toutes les commandes ci-dessous s'exécutent depuis la racine du dépôt cible ; $COMPETENCE est le répertoire de cette compétence. Les artefacts sont placés dans .test-doctor/ (suggérez de l'ajouter au .gitignore).
Workflow
1. MESURER (script — toujours en premier)
node "$COMPETENCE/dist/cli.mjs" collect --cwd .
Détecte le lanceur, exécute la suite complète une fois pour la couverture de référence, puis réexécute chaque fichier de test isolément en enregistrant les lignes/branches couvertes et le temps d'exécution. Écrit .test-doctor/report.json.
- La granularité par défaut est par fichier de test (l'isolation par test est exacte mais exécute chaque test séparément — proposez
--granularity testuniquement pour les suites petites ou déjà réduites, ou limitées avec--filter). - Sur une suite de 2 000 tests, cela prend du temps ; exécutez-le en arrière-plan et signalez la progression. Prenez les
collectionErrorsdans le rapport au sérieux — ces unités bloquent la minimisation par défaut. Si l'utilisateur choisit explicitement--keep-unmeasured, chaque unité affectée est conservée obligatoirement et le plan est marqué comme non fiable. --filtercrée une référence volontairement limitée : la collecte, la minimisation et la vérification ne couvrent que les fichiers de test correspondants. Mentionnez cette portée dans chaque recommandation ; il ne s'agit pas d'une garantie pour l'ensemble du dépôt.
2. MINIMISER (script)
node "$COMPETENCE/dist/cli.mjs" minimize --coverage-floor 0.97 --target-count 200
Sélection gloutonne par somme pondérée : conserve de manière itérative l'unité qui apporte le plus de nouvelles lignes/branches couvertes par milliseconde d'exécution jusqu'à atteindre le seuil de couverture. Écrit .test-doctor/plan.json et un fichier lisible .test-doctor/plan.md avec une justification pour chaque unité conservée ou supprimée.
- Demandez à l'utilisateur ses seuils s'ils ne sont pas précisés ; les valeurs par défaut sont un seuil de lignes à 0,97, aucun seuil de branches, aucun nombre cible.
--helpliste tous les paramètres. - Conservez d'office les tests de contrat/régression connus :
--keep 'contract' --keep 'regression'(expression régulière sur l'identifiant de l'unité). - Tenez compte du tableau
warningsdu plan — par exemple, seuil de couverture inaccessible ou nécessitant plus d'unités que le nombre cible. Transmettez-les à l'utilisateur textuellement.
3. RÉVISER (jugement — le vôtre)
Lisez references/slop-patterns.md, puis révisez la liste des suppressions dans plan.md :
- Sauvegardez tout test qui vérifie un comportement invisible à la couverture : contrats d'API publique, régressions référençant un identifiant de ticket/bug, formulation de messages d'erreur utilisée par les consommateurs, vérifications de propriétés/invariants. Relancez
minimizeavec des motifs--keepsupplémentaires plutôt que de modifier le plan à la main. - Confirmez que les autres suppressions sont sûres ; classez-les par motif de slop pour que l'utilisateur voie pourquoi chacun est supprimé (le fichier des motifs contient le catalogue).
Révisez ensuite la liste des conservations par rapport à references/quality-rules.md : les tests conservés qui sentent mauvais (mock du mock, tautologies, snapshots vides) sont réécrits sur place — ils gagnent leur couverture, mais ils doivent le faire proprement.
Ce n'est qu'après cette révision que vous supprimez les fichiers/cas de test supprimés sur la branche. Supprimez les fichiers entiers lorsque toutes leurs unités sont supprimées ; modifiez les fichiers lorsque seuls certains tests à l'intérieur sont supprimés (granularité test).
4. RÉGÉNÉRER (jugement — le vôtre)
Exécutez verify une fois (attendez-vous à un échec éventuel) pour obtenir le rapport des lacunes de couverture, puis écrivez de nouveaux tests pour les fichiers sources les plus touchés listés par verify, en suivant references/quality-rules.md : structure AAA, noms basés sur le comportement, un comportement par test, mocks uniquement aux limites externes. Préférez un test solide couvrant un comportement réel visible par l'utilisateur plutôt que trois tests superficiels.
5. VÉRIFIER (script — valide la fin)
node "$COMPETENCE/dist/cli.mjs" verify --coverage-floor 0.97
# optionnellement, pour les modules critiques uniquement (lent) :
node "$COMPETENCE/dist/cli.mjs" verify --mutation --mutate "src/billing/**/*.ts" --mutation-floor 80
Réexécute la suite, exige qu'elle soit verte et que le taux de conservation des lignes par rapport à la référence atteigne le seuil. Code 0 = terminé ; code 1 = corrigez et relancez (régénérez plus de tests, ou restaurez les suppressions) ; code 2 = problème d'environnement, arrêtez et signalez. Les tests de mutation sont facultatifs par module car ils sont lents — proposez-les pour les modules que l'utilisateur juge critiques.
La version 2 établit une référence de la source couverte, de la configuration du lanceur, du fichier de verrouillage, du lanceur et du fournisseur de couverture. Si verify signale une dérive de provenance, collectez une nouvelle référence. Utilisez --allow-provenance-drift uniquement avec l'accord explicite de l'utilisateur et signalez le verdict résultant comme non fiable. Les références héritées v1 nécessitent également la porte de sortie explicite --allow-legacy-baseline.
Compte rendu
Résumez pour l'utilisateur : unités avant → après, conservation des lignes/branches, temps d'exécution avant → après, motifs de slop trouvés (avec compteurs), tests sauvés de la liste des suppressions et pourquoi, tests régénérés, et verdict final de verify. Incluez le chemin vers plan.md pour la piste d'audit complète.
Modes de défaillance
- Lanceur non détecté / ambigu → la CLI sort avec le code 2 et fournit des conseils ; passez
--runnerou--cwd(monorepos : exécutez par package). - Collecte incomplète → corrigez les échecs isolés. Ne les filtrez pas simplement pour faire passer un plan ; un filtre modifie le périmètre déclaré de la référence.
--keep-unmeasuredest la porte de sortie prudente. verifyéchoue toujours après régénération → arrêtez la boucle après environ 3 tentatives ; présentez les lacunes résiduelles fichier par fichier et laissez l'utilisateur décider entre abaisser le seuil et conserver plus de tests.- La suite était rouge avant de commencer → ne « corrigez » pas les échecs non liés en silence ; signalez-les et convenez d'abord du périmètre.