Communitygithub.com

gpanakkal/crucible

Compétence d'agent pour des tests unitaires TypeScript qui échouent quand ils le doivent.

Qu'est-ce que crucible ?

Crucible est une compétence d'agent AI dédiée à l'écriture, la correction et l'audit de tests unitaires TypeScript, avec un accent particulier sur la fiabilité : les tests doivent échouer lorsqu'ils détectent un bogue, et passer automatiquement une fois le bogue corrigé. Elle s'appuie sur Vitest pour la couverture de branches, Stryker Mutator pour le score de mutation, et fast-check pour les tests basés sur les propriétés. La compétence vérifie l'absence de signaux de désactivation (fichier `.no-crucible` ou configuration `crucible: false`) avant de s'activer. Elle guide l'agent à travers un processus rigoureux : évaluation des tests existants via couverture et mutation, identification des hypothèses erronées et des bogues, puis écriture de tests basés sur les propriétés avec des arbitraires couvrant tous les paramètres et entrées implicites. Un format structuré de débriefing est prévu pour enregistrer les scores de couverture et de mutation, les problèmes rencontrés et les tests écrits. Cette compétence est particulièrement utile pour les développeurs souhaitant garantir une couverture de code maximale et une élimination de tous les mutants tuables, dans des projets utilisant TypeScript.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add gpanakkal/crucible

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait crucible ?

Quand l'utiliser

Lorsqu'on vous demande d'écrire, corriger ou auditer des tests unitaires sur des projets TypeScript.

Quand NE PAS l'utiliser

Lorsqu'on écrit des tests de bout en bout, d'intégration, d'interface utilisateur ou de simulation.

Refus par projet

Avant de vous activer, vérifiez si le projet a refusé cette compétence. Recherchez l'un des éléments suivants :

  • Un fichier .no-crucible à la racine du projet
  • "crucible: false" n'importe où dans AGENTS.md ou .claude/settings.json

Si un signal de refus est trouvé, ne vous activez pas automatiquement ; n'appliquez cette compétence que si l'utilisateur le demande explicitement dans cette conversation.

Règles

  • Les exemples de commandes utilisent pnpm, mais utilisez toujours le gestionnaire de paquets du projet.
  • Ne modifiez pas le code applicatif sauf indication contraire explicite.
  • Lorsqu'on vous demande d'ajouter des tests, ne modifiez pas les tests existants.
  • Lorsqu'on vous demande de corriger des tests, n'ajoutez pas de nouveaux tests.
  • Lorsqu'on vous demande d'auditer des tests, corrigez les tests existants puis ajoutez des tests si nécessaire pour satisfaire les critères de test.

Critères de test

Les tests unitaires doivent :

  • Avoir la couverture de branches maximale possible selon Vitest.
  • Tuer tous les mutants tuables, atteignant le score de mutation maximal possible parmi tout le code dans le périmètre de la requête (pas seulement ce qui est couvert par les tests). Les mutants non tuables empêcheront d'obtenir un score de 100.
  • Être basés sur les propriétés chaque fois que possible, sauf s'il n'existe qu'une poignée de cas d'entrée. Par exemple, une fonction avec un seul paramètre booléen et aucune entrée implicite n'a que deux cas d'entrée possibles, donc ne vous embêtez pas à la rendre basée sur les propriétés.
  • (si basé sur les propriétés) avoir des arbitraires qui couvrent tous les paramètres et toutes les entrées implicites. Il est essentiel qu'aucun cas pouvant survenir en production ne soit exclu. Si nécessaire ou peu clair, abusez en rendant les arbitraires trop larges.
  • Échouer s'ils testent un code erroné ou si les arbitraires sont délibérément trop larges. Considérez les tests comme des exigences : ils doivent être nommés en conséquence et doivent automatiquement passer dès que l'utilisateur corrige le bogue à l'avenir, après que l'utilisateur a corrigé la fonction et/ou les arbitraires. N'utilisez pas test.fails/.skip ; cela rend moins évident pour l'utilisateur qu'une attention est requise, donc des tests qui passent quand ils ne le devraient pas est l'erreur de priorité la plus élevée à éviter.

Vérifiez la couverture de branches et exécutez les tests : pnpm exec vitest run src/foo.test.ts --coverage Vérifiez les mutants survivants sur le code testé : pnpm exec stryker run --mutate "src/foo.ts"

Vérification de la configuration de test

  1. Vérifiez que tous les paquets suivants sont installés sur le projet : vitest fast-check @stryker-mutator/core @stryker-mutator/vitest-runner @stryker-mutator/typescript-checker
  2. Vérifiez que les configurations Vitest et Stryker incluent/excluent correctement les fichiers. Stryker ne doit pas vérifier les fichiers qui ne contiennent que des données de test.
  3. Vérifiez la configuration Stryker :
    1. Utilise le rapporteur clear-text (les autres rapporteurs sont facultatifs).
    2. Utilise le vérificateur TypeScript et pointe correctement vers le fichier de configuration TS.
  4. Recherchez tout autre problème de configuration qui pourrait causer des problèmes dans le flux de travail d'écriture de tests.
  5. Rapportez les résultats à l'utilisateur.

Écrire des tests

Lorsqu'on vous demande d'écrire de nouveaux tests, NE MODIFIEZ PAS LE CODE APPLICATIF NI LES TESTS EXISTANTS.

D'abord, évaluez les tests existants en suivant Évaluer un module. Créez un nouveau fichier de débriefing en utilisant le modèle et enregistrez-y les scores de couverture et de mutation initiaux.

Ensuite, écrivez les tests en suivant ce processus exactement :

Faites ce qui suit pour chaque fonction/méthode dans l'interface du module, en terminant une fonction avant de commencer la suivante :

  1. Déterminez le but de la fonction en examinant les commentaires, son nom, sa signature de type et comment elle est utilisée. En cas d'incertitude, notez cela dans le débriefing, sautez l'écriture de tests et passez à la fonction suivante.
  2. Notez tout bogue potentiel dans l'implémentation de la fonction.
  3. En fonction de son but, identifiez les hypothèses erronées que la fonction fait sur ses paramètres et entrées implicites, et notez les cas d'entrée qui sont susceptibles de conduire à un comportement incorrect de la fonction. Par exemple, une fonction qui prend un entier positif mais ne valide pas son entrée fait une hypothèse erronée sur son entrée.
  4. NE MODIFIEZ JAMAIS LES TESTS PRÉEXISTANTS. Si vous trouvez des problèmes dans les tests existants, notifiez l'utilisateur des problèmes trouvés dans les tests existants.
  5. Écrivez de nouveaux tests en faisant ce qui suit : a. En utilisant fast-check, créez des stubs de tests basés sur les propriétés avec des arbitraires qui couvrent tous les paramètres et entrées implicites de la fonction. Utilisez fc.asyncProperty + await fc.assert(...) lorsque la fonction testée est asynchrone. En cas de doute, abusez en rendant les arbitraires trop larges et mentionnez-le dans le débriefing pour que l'utilisateur puisse les corriger. Nommez les tests comme des descriptions du comportement souhaité. b. En utilisant vitest, écrivez des assertions dans les stubs couvrant les valeurs retournées et les effets de bord tels que le lancement d'exceptions, la mutation d'entrées, la mutation/réaffectation de variables de portées externes, etc. Assurez-vous que les tests affirment le comportement souhaité, en capturant les hypothèses erronées/bogues identifiés précédemment et en échouant en conséquence.
  6. Revérifiez la couverture : pnpm exec vitest run src/foo.test.ts --coverage
  7. Testez par mutation uniquement la fonction actuelle : pnpm exec stryker run --mutate "src/foo.ts:<ligneDébut>-<ligneFin>"
  8. Révisez les tests nouvellement écrits et répétez les étapes 5a et 5b jusqu'à ce que les critères de test (énumérés ci-dessus) soient satisfaits pour la fonction.
  9. Mettez à jour le débriefing avec une section sur cette fonction.

Après avoir écrit les tests pour toutes les fonctions, revérifiez que vous avez ajouté des sections au débriefing pour chaque fonction et terminez la section de résumé.

Auditer des tests

Si on vous demande d'auditer l'ensemble du projet, vérifiez la couverture de code et les scores de mutation à l'échelle du projet, et recommandez des domaines pour des audits plus détaillés ou pour ajouter/mettre à jour des tests. Orientez les recommandations vers les zones les plus importantes et les plus sujettes aux bogues de la base de code – logique métier centrale, code piloté par les événements et fonctions complexes.

Si on vous demande d'auditer une partie du projet, recherchez les modules ou fonctions (dans le périmètre de la requête) qui n'ont pas de tests et signalez-les à l'utilisateur dans le débriefing post-audit.

Pour chaque module dans le périmètre de la requête qui a des tests, suivez Évaluer un module. Ensuite, si des critères de test ne sont toujours pas satisfaits après les corrections de l'évaluation, suivez Écrire des tests pour combler les lacunes restantes.

Évaluer un module

Utilisez ce processus chaque fois que vous devez évaluer un fichier de test existant par rapport aux critères de test – à la fois avant d'écrire de nouveaux tests et lors d'un audit.

  1. Vérifiez la couverture de code avec Vitest : pnpm exec vitest run src/foo.test.ts --coverage.
  2. Vérifiez la présence de mutants survivants avec Stryker Mutator : pnpm exec stryker run --mutate "src/foo.ts".
  3. Pour chaque fonction du module qui a des tests :
    • Pour les tests basés sur les propriétés :
      • Recherchez les entrées que la fonction accepterait sans lancer d'exception ni retourner de valeur d'erreur, mais qui ne peuvent pas être générées par les arbitraires. Élargissez les arbitraires si nécessaire pour inclure ces entrées.
      • Recherchez les entrées qui ne sont pas couvertes par les arbitraires, en particulier les entrées implicites telles que les champs de classe, les variables globales, la date/heure et les nombres générés aléatoirement. Ajoutez des arbitraires pour celles-ci.
    • Corrigez les erreurs dans les implémentations de mocks.
    • Recherchez les goulots d'étranglement de performance.
  4. Enregistrez les scores de couverture et de mutation, ainsi que les conclusions, dans le débriefing.

Débriefings de test

Formatez les débriefings selon le modèle ci-dessous. S'il n'y a rien à signaler dans une sous-section de fonction, écrivez simplement "n/a". Générez le débriefing dans un fichier Markdown dans debriefs/.

Débriefing : {nomModule/nomFichier} {aaaa-mm-jj}

Résumé

Couverture (branches) Avant : X% → Après : Y% Lignes qui n'ont pas pu être couvertes : {plages de lignes}

Score de mutation (total) Avant : X% → Après : Y%

Problèmes

{liste à puces des hypothèses erronées, bogues trouvés, problèmes rencontrés dans les tests et tests échouant. Chaque élément de la liste doit commencer par le chemin relatif à la racine du projet du fichier et le(s) numéro(s) de ligne où le problème a été trouvé}

{nomFonction}

But de la fonction {une phrase décrivant ce que la fonction est censée faire} (confiance : élevée | incertaine) {si incertaine : ce qui n'est pas clair et pourquoi}

Hypothèses erronées trouvées

  • (ligne {numéro/plage de lignes}) : {hypothèse sur le type/plage/forme de l'entrée que la fonction ne valide pas}

Bogues trouvés dans l'implémentation

  • (ligne {numéro/plage de lignes}) : {description + numéro de ligne}

Problèmes trouvés dans les tests préexistants

  • (ligne {numéro/plage de lignes}) : {description du problème + nom du test}

Cas de test écrits

  • {brève description de chaque propriété/invariant testé}

Tests échouant

  • (ligne {numéro/plage de lignes}) : {nom du test + raison}

Mutants non tuables

  • (ligne {numéro/plage de lignes}) : {brève description}

Skills associés