CRAFTOMANCER ~/parcours/aiguiser-le-craft/les-tests-comme-contrat
Sommaire

AIGUISER LE CRAFT · GUIDE 02 · LECTURE ~7 MIN · WILLIAM LEEMANS

Les tests comme contrat

En chantier Cette section est en cours d'écriture : ce guide est lisible mais pas encore finalisé, son contenu peut évoluer.

Le guide précédent s’achevait sur une consigne : laisser types, tests et exécution filtrer avant vos yeux, parce que votre attention fatigue et pas la leur. Ce guide tient cette promesse pour la pièce maîtresse du dispositif.

Quand un agent écrit le code, le test change de statut. Il n’est plus le filet de sécurité qu’on écrit après coup : c’est la part de la spécification qui s’exécute, le contrat qui fixe ce qui doit être vrai pendant que la machine se charge du comment. Et comme pour tout contrat, la question qui compte n’est pas s’il est signé, mais qui l’a rédigé et qui l’a relu.


De la vérification déclarée à la vérification exécutable

« C’est corrigé. » « Tous les cas limites sont gérés. » « Les tests passent. » Un agent produit ces déclarations avec le même aplomb que son code, et pour la même raison : ce sont des continuations vraisemblables, pas des constats. La sycophantie décrite dans Limites et hallucinations s’applique d’abord aux rapports de succès. Une affirmation de l’agent sur son propre travail a exactement la valeur de preuve d’une affirmation de l’agent sur le vôtre : aucune.

Le test est l’instrument qui convertit cette déclaration en verdict. Il dit le comportement attendu dans une forme à la fois lisible par vous et exécutable par la machine, et son résultat est binaire, reproductible, insensible à la conviction de celui qui l’a produit. C’est la seule réponse qui tienne face à l’asymétrie posée au guide précédent : l’agent produit plus vite que vous ne relisez, mais il ne produit pas plus vite que la suite ne s’exécute.

D’où le changement de statut. Tant qu’un humain écrivait le code, le test coûtait à peu près aussi cher que l’implémentation, et cette économie en faisait une assurance. Souvent négociée, parfois sacrifiée. Quand l’implémentation ne coûte presque rien, ce qui reste rare, c’est la définition exacte de ce qu’elle doit faire. Le test devient cette définition : la forme la plus dense et la moins ambiguë de spécification qu’un modèle puisse recevoir, et la seule qui se vérifie elle-même.

Qui écrit le test tient le contrat

Laisser l’agent écrire l’implémentation et ses tests dans le même geste produit une circularité confortable : les tests documentent ce que le code fait, pas ce qu’il devrait faire. Ils sont générés depuis la même compréhension de la tâche. Si cette compréhension a un angle mort, le code et les tests partagent l’angle mort, et la suite verte certifie l’erreur. Un contrat rédigé par la partie qui doit le remplir n’engage personne.

L’intention doit donc entrer dans le contrat par vous. En pratique, trois niveaux d’implication, à calibrer sur le coût de l’erreur :

  • Sur les chemins critiques, écrivez les tests vous-même, ou au minimum les assertions. Calcul, argent, droits d’accès, migration : c’est ici que votre expertise se condense en quelques lignes exécutables, et c’est un bien meilleur usage de votre temps d’écriture que l’implémentation.
  • Ailleurs, faites rédiger le brouillon par l’agent, mais relisez-le comme une spécification. Un test bien écrit est court, déclaratif, sans logique habile : le relire coûte une fraction de la relecture de l’implémentation. Si vous ne devez lire qu’une chose ligne à ligne dans un diff, lisez les tests. C’est la passe de détail du guide précédent, au meilleur rendement.
  • Dans tous les cas, voyez le test échouer avant de déléguer. Un test que vous n’avez jamais vu rouge ne prouve rien : il peut être tautologique, mal branché, ou tester un comportement déjà présent. Le rouge initial est la signature du contrat.

La boucle rouge-vert, version agent

Le TDD a toujours été défendu pour la pression de conception qu’il exerce. Avec un agent, il gagne un second argument, plus brutal : c’est le seul protocole où la délégation est bornée par construction. La boucle :

  1. Rédigez ou validez le test, constatez le rouge. Le contrat existe, l’écart aussi.
  2. Donnez la commande qui fait foi (« la tâche est finie quand npm test passe ») et laissez l’agent itérer. L’autonomie ne coûte rien ici : chaque essai est jugé par la suite, pas par sa plausibilité, et vous n’avez pas à relire les tentatives intermédiaires.
  3. Traitez le vert comme une autorisation de relire, pas comme une absolution. Le contrat garantit les comportements qu’il énonce, rien d’autre. La passe d’intention et la passe d’intégration du guide précédent restent dues.

Le tips Craftomancer

Un agent optimise le verdict, pas la vertu. Si le chemin le plus court vers le vert passe par l’affaiblissement du contrat (assertion assouplie, cas commenté, skip discret, valeur attendue recopiée depuis la sortie obtenue), certains modèles le prendront, sans malice. Verrouillez la règle : pendant qu’il fait passer les tests, l’agent ne les modifie pas. Et tout diff qui touche à la fois aux tests et au code se relit en commençant par les tests. C’est peut-être une mise à jour légitime du contrat, mais c’est à vous d’en décider.

Reconnaître les tests décoratifs

La défaillance signature des tests générés n’est pas le test faux (il échouerait, on le verrait). C’est le test décoratif : vert, nombreux, et muet. Les espèces les plus courantes :

  • Le test-miroir, qui paraphrase l’implémentation : tout est mocké, et l’assertion vérifie que le mock a bien été appelé avec ce que le code lui passe. Il teste le câblage, jamais le comportement. Il survivra à tous les bugs et cassera à tous les refactorings, l’exact inverse du contrat.
  • Le chemin heureux exhaustif : douze variantes du cas nominal, zéro cas limite. L’agent teste ce qu’il a pensé à implémenter. Ce qu’il a oublié dans le code, il l’a oublié dans les tests, au même endroit.
  • La couverture comme métrique de vanité. La couverture mesure ce qui s’exécute, pas ce qui est promis. Cent pour cent de lignes couvertes par des assertions creuses, c’est cent pour cent de figuration.

Le réflexe de tri tient en deux questions. Lisez le test seul : pouvez-vous dire quel comportement il promet ? Puis pensez en mutant : si on réintroduit le bug, ou qu’on inverse cette condition, ce test hurle-t-il ? Un test qui survivrait au bug qu’il est censé interdire n’est pas un contrat. C’est un décor, et il coûte de la maintenance sans rien garantir.

Le contrat est la mémoire du projet

Un agent n’a pas de mémoire : chaque session repart de zéro, et les consignes répétées dans le chat finissent par sortir de la fenêtre. La suite de tests est l’inverse exact. C’est la mémoire exécutable du projet, la consigne qui ne sort jamais du contexte parce qu’elle ne vit pas dedans : elle s’exécute à chaque itération, quelle que soit la session.

D’où une discipline de capitalisation : chaque bug de production, chaque diff refusé pour une raison de fond devient un test avant de devenir un correctif. Le guide précédent recommandait de régénérer un diff médiocre plutôt que de le rafistoler ; c’est la suite qui rend ce geste bon marché. Régénérer sans contrat, c’est rejouer aux dés. Régénérer sous contrat, c’est réessayer sans risque. Et un test rouge est le meilleur rapport de bug qu’un agent puisse recevoir : reproductible, sans ambiguïté, auto-vérifiant. Toute la spécification du correctif tient dans son exécution.

En pratique

  • Aucune déclaration de succès ne vaut verdict : ce que l’agent affirme, un test doit pouvoir le prononcer.
  • Avant de déléguer une tâche non triviale, fixez le contrat : des tests écrits ou validés par vous, vus rouges au moins une fois.
  • Donnez la commande qui fait foi et laissez l’agent itérer jusqu’au vert. Le vert autorise la relecture, il ne la remplace jamais.
  • Pendant la mise en conformité, l’agent ne touche pas aux tests. Tout diff qui modifie code et tests à la fois se relit en commençant par les tests.
  • Traquez le décoratif : un test dont vous ne savez pas dire ce qu’il promet, ou qui survivrait au bug réintroduit, se supprime ou se réécrit.
  • Capitalisez : chaque bug, chaque refus motivé devient un test. La suite est la mémoire exécutable du projet.

Le contrat garantit que le code tient ses promesses ; il ne dit pas encore ce que contient le colis. Dépendances embarquées, surface exposée, chemins jamais exécutés : c’est l’objet du prochain guide de la Section, comprendre ce qu’on livre.