Aller au contenu

Skills

chimera-prove-the-test-discriminates

Un test de régression que vous n'avez jamais vu échouer est une supposition. Recassez le code et regardez-le passer au rouge avant de le committer.

PatronProvenance: cleanStatut: activev0.1.0 · Apache-2.0

Conférée par la personne qui a relu la fiche, et non revendiquée par le fichier lui-même. Une fiche que l'agent distille au cours d'une exécution ayant consommé du contenu non fiable naît contaminée et reste en attente de relecture avant d'être un jour récupérée.

Quand elle vient à l'esprit

  • écriture d'un test de non-régression
  • bug corrigé, test ajouté
  • le test passe, on livre
  • ajouter un test après le correctif

C'est dans À éviter et Vérifier que se trouve d'ordinaire la valeur. À faire est la section que tout le monde écrit.

Le corps de la fiche ci-dessus est une traduction. L'original anglais est ce que la CLI importe, ce que l'agent lit à l'exécution et ce que l'empreinte ci-dessous atteste.

Déclencheur

Vous avez corrigé un bug et écrit un test pour qu'il ne revienne pas. Le test passe. C'est toute la preuve dont vous disposez, et c'est exactement la même preuve que vous auriez si le test ne vérifiait rien du tout au sujet du bug.

Cela vaut surtout quand le test a été écrit après le correctif, car alors le seul code contre lequel le test s'est jamais exécuté est un code d'où le bug a déjà disparu. Cela vaut moins pour un test écrit d'abord, au rouge, dans une boucle TDD — vous l'avez déjà vu échouer, ce qui est tout l'intérêt de la boucle.

Cela ne s'applique pas à un test portant sur un comportement réellement nouveau, où il n'y a pas d'« avant » vers lequel revenir. Là, la vérification discriminante est différente : supprimez la nouvelle implémentation et confirmez que le test échoue sur l'absence, pas sur le bug.

À faire

  1. Identifiez la modification exacte qui constitue le correctif — le hunk, pas le commit. Si le correctif tient en une comparaison changée, c'est cette comparaison que vous allez défaire.
  2. Défaites-la. Mettez le correctif de côté avec git stash, ou remettez la ligne à la main dans sa forme cassée.
  3. Lancez uniquement le nouveau test : pytest tests/test_thing.py::test_the_regression -x.
  4. Lisez l'échec. Ce doit être votre assertion qui échoue, avec un message portant sur le comportement — pas une SyntaxError, pas une erreur de collecte, pas une ImportError venue d'un fichier à moitié restauré. Ceux-là sont rouges pour la mauvaise raison et ne prouvent rien sur le test.
  5. Restaurez le correctif (git stash pop) et confirmez que le même test passe désormais.
  6. Consignez le fait dans la docstring du test : ce qui a été défait, et à quoi ressemblait l'échec. La prochaine personne qui touchera à ce test doit savoir qu'il a bien été exercé contre le bug.

À éviter

Vérifier quelque chose qui est vrai dans les deux mondes. La forme classique :


result = parse_config(raw)
assert result is not None
assert "timeout" in result

Le bug était que timeout revenait sous forme de chaîne "30" au lieu de l'entier 30. Les deux assertions tiennent dans les deux cas. Ce qui discrimine, c'est ce qui a changé :

# RIGHT — fails against the buggy code
assert parse_config(raw)["timeout"] == 30
assert isinstance(parse_config(raw)["timeout"], int)

Évitez aussi de défaire le correctif en commentant une fonction entière ou en supprimant un import pour « le faire échouer vite ». Cela produit une exécution rouge qui se serait produite pour n'importe quel test du fichier, et ne vous apprend donc rien sur celui-ci. Ce qu'on défait doit être le correctif et rien que le correctif.

Et évitez le quasi-échec où le test atteint le code corrigé par un chemin que la production n'emprunte jamais — c'est une autre défaillance, et la carte correspondante est chimera-test-the-wiring-not-the-class.

Vérifier

Une question binaire : avez-vous personnellement vu ce test afficher un échec provoqué par sa propre assertion, face au code non corrigé ?

Si oui, c'est fait. Si la réponse est « il aurait échoué », vous n'avez rien vérifié — cette phrase est une prédiction produite par le même raisonnement qui a écrit le test.

Concrètement :

git stash                 # remove the fix
pytest tests/test_x.py::test_regression   # MUST be red, on your assertion
git stash pop             # restore
pytest tests/test_x.py::test_regression   # MUST be green

Rouge puis vert, les deux observés, sinon le test n'est pas prouvé.

Risque

Certains correctifs ne se défont pas à bon compte : une montée de version de dépendance, une migration de schéma, un fichier supprimé, un changement dans une bibliothèque embarquée. Forcer la restauration y coûte parfois plus cher que le test ne vaut. Le repli honnête est de reconstruire l'entrée qui cassait le code et de vérifier la valeur précise, puis de dire clairement dans la docstring que l'exécution rouge n'a pas été observée — un test non prouvé qui admet ne pas l'être vaut bien mieux qu'un test qui laisse croire qu'il l'a été.

Le vrai danger de cette carte, c'est la restauration que vous oubliez d'annuler. Faire cette danse dans un arbre de travail sale, c'est ainsi qu'une ligne recassée finit committée avec son propre test de régression, la suite au vert parce que vous avez restauré le correctif dans le mauvais fichier. Lancez git diff avant de committer, à chaque fois.

Et un test discriminant ne vaut jamais mieux que la compréhension que vous aviez du bug. Il prouve que le test attrape cette régression. Il ne prouve pas que vous avez corrigé la cause racine plutôt que le symptôme, et traiter un cycle rouge-puis-vert comme une preuve de cela est une affirmation plus grande que ce que la preuve permet.

L'utiliser

La fiche est une donnée. Clonez le dépôt et importez-la par son chemin — ce qui arrive par le réseau est traité comme contaminé et retenu pour approbation, ce qui est le comportement souhaitable et la raison pour laquelle il n'y a pas d'installateur en une ligne ici.

git clone https://github.com/brcampidelli/chimera-agent.git
chimera skills-import chimera-agent/skills/chimera-prove-the-test-discriminates/SKILL.md

Intégrité

SHA-256 du fichier tel qu'il est publié. Qui l'importe peut vérifier que ce qu'il a reçu correspond à ce que cette page affichait.

90d4bf00eb67055008527ee372153b2637fa2feea601ed6760997eda239f0b76

Lire la fiche dans le dépôt