mutation-test

Par n8n-io · n8n

Exécute les tests de mutation Stryker sur un seul fichier source et retourne un rapport structuré, économe en tokens, qui peut être transmis en pipeline à une boucle de suivi « strengthen tests ». À utiliser quand l'utilisateur dit /mutation-test, « mutation test this file », ou vient de modifier des tests et veut vérifier qu'ils testent bien un comportement réel. Périmètre limité à un seul fichier — les exécutions de mutation sur l'ensemble du package sont hors scope.

npx skills add https://github.com/n8n-io/n8n --skill mutation-test

Tests de mutation — fichier unique

Enveloppe pnpm --filter=<pkg> mutate <file> et analyse summary.json dans une structure compacte et structurée adaptée aux itérations suivantes « renforcer les mutants survivants ».

Quand utiliser

  • L'utilisateur invoque explicitement : /mutation-test <path>, « teste la mutation de ce fichier », « vérifie l'efficacité de mes tests sur X »
  • L'utilisateur vient de modifier un fichier de test et veut savoir si ses assertions sont pertinentes
  • Boucle de suivi après un verdict red — transmettre la sortie structurée à une itération de « correction »

Ne pas utiliser cette skill pour :

  • Les exécutions de mutation sur l'ensemble du package ou du repo — fichier unique seulement
  • Les questions sur le pourcentage de couverture (utiliser le workflow de couverture existant)
  • Les fichiers en dehors de packages/workflow/ — Stryker n'est câblé que là pour l'instant

Entrées

Un argument obligatoire : le fichier source à muter, soit comme chemin relatif au repo, soit comme chemin relatif au package. Exemples qui signifient tous la même chose :

  • packages/workflow/src/cron.ts
  • src/cron.ts (suppose packages/workflow)
  • workflow/src/cron.ts (suppose packages/)

En cas d'ambiguïté, demander à l'utilisateur une seule fois quel package ; ne pas deviner.

Étapes

  1. Résoudre le package + le chemin source relatif. Aujourd'hui seul n8n-workflow (packages/workflow) a Stryker câblé. Si l'utilisateur passe un fichier en dehors, le signaler et arrêter — ne pas fabriquer de sortie.

  2. Exécuter Stryker avec sortie réduite :

    pnpm --filter=n8n-workflow mutate <package-relative-src> 2>&1 | tail -40

    tail -40 écarte le spam de la barre de progression de Stryker ; les chiffres pertinents + la liste des survivants atterrissent toujours dans les ~30 dernières lignes. Codes de sortie : 0 = succès, 1 = sous le seuil (toujours valide, summary.json existe), 2 = erreur d'usage, 3 = échec de Stryker (pas de summary.json).

  3. Si le code de sortie est 3, afficher la sortie réduite à l'utilisateur, suggérer de vérifier que les dépendances du workspace sont construites (pnpm build), et arrêter. Ne pas fabriquer de rapport.

  4. Lire packages/workflow/reports/mutation/summary.json — jamais raw.json. raw.json fait 600 KB+ et n'est pas nécessaire pour la boucle de renforcement. summary.json contient déjà chaque mutant survivant avec sa localisation, son remplacement, le nom du mutateur et les noms des tests qui ont couvert la ligne.

  5. Plafonner covering_tests à 3 par survivant. Si un mutant a été couvert par plus de 3 tests, conserver les 3 premiers et ajouter +N more comme compte. Les noms au-delà de 3 consomment des tokens sans ajouter de signal actionnable — la boucle de renforcement a besoin de savoir quel test étendre, pas tous.

  6. Calculer minimum_kills_needed pour atteindre le seuil :

    killed_now = summary.overall.counts.killed + summary.overall.counts.timeout
    valid_total = killed_now + summary.overall.counts.survived + summary.overall.counts.noCoverage
    needed = ceil((threshold/100) * valid_total) - killed_now

    Cela indique à la boucle suivante le nombre minimum de survivants à éliminer pour basculer de red à green. Plafonner au nombre de survivants.

  7. Afficher la structure compacte décrite ci-dessous. Garder la prose à une ligne de titre ; le reste est le bloc JSON.

Forme de sortie

Une ligne de titre, puis un bloc JSON fencé. Rien d'autre — pas de préambule, pas de commentaire par survivant, pas de tri des risques (c'est le travail de la boucle suivante).

[red|green] <score>% (seuil <T>%) — <N> survivants ; il faut en éliminer ≥<K> pour passer au vert.

```json
{
  "verdict": "red",
  "target": "packages/workflow/src/augment-object.ts",
  "package": "n8n-workflow",
  "score": 76.74,
  "threshold": 80,
  "delta_to_threshold": 3.26,
  "minimum_kills_needed": 5,
  "counts": {
    "killed": 99,
    "survived": 28,
    "no_coverage": 2,
    "timeout": 0
  },
  "survivors": [
    {
      "id": "77",
      "mutator": "ConditionalExpression",
      "location": "src/augment-object.ts:95:6",
      "original": "value === null",
      "replacement": "false",
      "covering_tests": [
        "augmentObject should handle null values",
        "augmentObject should handle nested nulls"
      ],
      "covering_tests_overflow": 0
    }
  ]
}
```

Trier le tableau survivors par location (numéro de ligne croissant, puis colonne) pour que la boucle de renforcement traite les survivants de haut en bas du fichier.

Contraintes

  • Pas de raw.json — ne jamais le lire ou le présenter. summary.json est la seule entrée.
  • Pas de rapport HTML — ne pas open raw.html ou coller de liens vers lui. Si l'utilisateur veut explorer visuellement, il le demandera.
  • Pas de tri automatique — ne pas catégoriser les survivants en « vrai bug » ou « assurance refactoring ». C'est une étape d'analyse distincte qui doit se faire sur demande, pas par défaut. Cela maintient le coût en tokens prévisible.
  • Pas de « je vais régénérer vos tests maintenant » — cette skill rapporte l'écart. Utiliser n8n:strengthen-tests pour des modifications d'assertions.

Suites courantes (ne pas faire sauf si demandé)

  • L'utilisateur dit « corrige ceux-ci » → lancer une boucle de renforcement en utilisant la sortie JSON comme entrée. Lire la source de covering_tests, proposer des changements par mutant, relancer la skill pour vérifier.
  • L'utilisateur dit « explique le survivant #N » → récupérer ce mutant de summary.json, afficher ses ~5 lignes environnantes du fichier source, aucune analyse au-delà de ce que contient summary.json.
  • L'utilisateur demande « quel est le seuil ? » → 80% provisoirement ; voir scripts/mutation-health/README.md pour la justification.
  • L'utilisateur dit « exécute-le sur les fichiers modifiés » → pas encore câblé. Suggérer git diff pour trouver les candidats, puis invoquer cette skill par fichier.

Connexes

  • scripts/mutation-health/README.md — l'histoire plus large de l'observabilité soutenue par BQ
  • packages/workflow/stryker.config.mjs — la configuration Stryker que cette skill pilote

Skills similaires