</> 23/04/2026 · vibe coding

Tests automatisés générés par IA : stratégie qui évite la dette de tests

WebCreatid · 23 avril 2026

Tests automatisés générés par IA : stratégie qui évite la dette de tests

Les tests générés par IA sont devenus triviaux à produire en 2026 : Claude Code génère 50 tests unitaires en deux minutes, Copilot complète vos descriptions Vitest pendant que vous tapez, et la moindre fonction reçoit son fichier .test.ts miroir. Le problème : générer 5 000 tests pauvres ne réduit pas votre dette technique, il la déplace. Cet article propose une stratégie en quatre niveaux, avec ce qui se délègue à l’IA et ce qui reste humain, plus une section dédiée au code sensible où l’envoi vers le cloud est exclu.

Image hero pour: tests automatises generes ia strategie

Le piège de la génération naïve

Demander « génère-moi tous les tests qui manquent » à un assistant IA produit deux pathologies. La première : des tests qui re-décrivent l’implémentation au lieu de vérifier le contrat. Tout passe au vert, et toute refonte casse cinq fichiers de tests sans bug réel. La seconde : des tests qui valident le cas heureux, ignorent les cas limites, et donnent une fausse impression de couverture. Le rapport de coverage indique 92 %, mais les chemins critiques sont vides.

Martin Fowler rappelle dans Practical Test Pyramid que la valeur d’un test ne se mesure pas à sa quantité. La génération naïve, dépourvue de cadre, produit du legacy à grande vitesse. La stratégie en quatre niveaux corrige cette dérive.

La stratégie en 4 niveaux

Chaque niveau a son rôle, son ratio IA/humain, son outil de prédilection.

NiveauType de testDélégation IAPilotage humainOutil 2026
1UnitairesÉlevée (autonomie cadrée)Spec et cas limitesVitest, Jest + Copilot
2IntégrationMoyenne (supervisée)Choix des doublures et fixturesVitest, MSW
3End-to-endFaible (assistance)Scénarios métierPlaywright + Claude Code
4PropriétéTrès faible (exécution seule)Invariants, oraclesfast-check, Hypothesis

Niveau 1 : Tests unitaires : IA en autonomie

Pour une fonction pure dont vous fournissez la spec en commentaire, l’IA produit des tests utiles. Donnez-lui le contrat (entrées attendues, sortie attendue, invariants) et la liste explicite des cas limites. Le ratio IA dominante fonctionne ici parce que l’oracle est trivial : la spec est l’oracle. Pour la mise en place du compagnon de génération, voyez notre guide complet Claude Code (pilier).

Niveau 2 : Tests d’intégration : IA supervisée

Le test d’intégration vérifie l’interaction entre plusieurs modules. L’IA peut écrire le boilerplate (mocks, fixtures, setup/teardown), mais le choix de la frontière du test reste humain. Décider quoi mocker et quoi laisser réel est une décision d’architecture. Une IA qui mock trop crée des tests qui passent toujours, qui mocke trop peu produit des tests lents et flaky.

Niveau 3 : Tests e2e : IA en assistance, dev pilote

Les tests end-to-end avec Playwright décrivent des scénarios métier. C’est la zone où l’IA aide à la transcription du scénario en code, mais où elle ne doit pas inventer le scénario. Un dev pilote, l’IA assiste. Claude Code excelle en mode pilote-IA pour traduire une description en sélecteurs robustes. Pour structurer la collaboration équipe, le workflow Git d’équipe avec Claude Code est notre guide latéral.

Niveau 4 : Tests de propriété : pure pensée humaine, exécution IA

Un test de propriété (property-based testing avec fast-check pour TypeScript ou Hypothesis pour Python) vérifie qu’un invariant tient sur des entrées générées aléatoirement. Trouver les bons invariants demande une réflexion humaine sur le métier. Une fois l’invariant formulé, l’IA peut écrire le générateur de cas et l’oracle. Mais l’invariant lui-même n’est pas délégable. C’est le niveau qui distingue les équipes mûres.

Patterns à demander à l’IA

Patterns de tests a demander a l IA

« Tests qui échouent d’abord »

Demandez à l’IA d’écrire d’abord le test qui doit échouer, avant l’implémentation. Vérifiez qu’il échoue vraiment. C’est une garantie cheap que le test mesure quelque chose. La quasi-totalité des tests générés naïvement passent dès la première exécution sur du code existant, signe qu’ils ne testent rien.

Cas limite explicitement listés

Listez vous-même les cas limites attendus avant la génération : entrée vide, valeur null, dépassement, encodage exotique, concurrence. L’IA générera ce que vous lui donnerez ; sans cette liste, elle se contentera du cas heureux. C’est la différence entre 3 % de bugs trouvés et 35 %.

Tests basés sur la spec, pas sur le code

Donnez à l’IA la spec en langage naturel ou en JSDoc. Évitez de lui donner le code source de la fonction à tester : elle aura tendance à reproduire les bugs existants en les figeant dans les tests. Une bonne pratique : générer la spec avec l’IA, la valider humainement, puis générer les tests à partir de la spec validée.

Avant / après : un même test, deux qualités

Le même utilitaire formatPrice, généré sans contexte puis cadré avec un prompt structuré. La différence se voit en moins de 30 secondes de lecture.

// AVANT - prompt « génère un test pour formatPrice », miroir d'implémentation
import { test, expect } from 'vitest';
import { formatPrice } from './formatPrice';

test('formatPrice retourne 9.99', () => {
  expect(formatPrice(9.99)).toBe('9.99');
});

test('formatPrice retourne 0', () => {
  expect(formatPrice(0)).toBe('0');
});
// APRÈS - prompt cadré : spec + cas limites + locale FR
// « formatPrice(n: number) => string : format monétaire FR (€, espace fine,
//   virgule décimale). Lever une erreur si n < 0. Tester : nominal, zéro,
//   grand entier, négatif rejeté, NaN rejeté. »
import { describe, test, expect } from 'vitest';
import { formatPrice } from './formatPrice';

describe('formatPrice - contrat monétaire FR', () => {
  test.each([
    [9.99, '9,99 €'],
    [0, '0,00 €'],
    [1234.5, '1 234,50 €'],
  ])('formate %s en %s', (input, expected) => {
    expect(formatPrice(input)).toBe(expected);
  });

  test('rejette les valeurs négatives', () => {
    expect(() => formatPrice(-1)).toThrow(/négatif/i);
  });

  test('rejette NaN', () => {
    expect(() => formatPrice(Number.NaN)).toThrow();
  });
});

Le premier bloc passe au vert sans rien tester d’utile : il fige la sortie naïve de l’implémentation. Le second part de la spec, couvre les bords (zéro, grand nombre, négatif, NaN) et formule des assertions sémantiques. Stryker fera survivre les mutations sur le premier, les tuera sur le second.

Patterns à interdire

Mesurer la valeur d’une suite : mutation testing

Le coverage classique trompe. Un fichier couvert à 95 % peut ne rien tester (les lignes sont exécutées, aucun assert ne valide). Le mutation testing répond à cette faille : Stryker (JavaScript/TypeScript) ou PIT (Java) modifient mécaniquement le code (changer un + en -, un < en <=) et vérifient qu’au moins un test échoue. Si aucun test n’échoue, la mutation a survécu : votre suite a un trou.

Sur une suite générée par IA, le score de mutation initial est typiquement entre 40 et 55 %. Une suite manuelle bien pensée tourne à 75-85 %. L’écart révèle la dette de tests réelle. Stryker permet de cibler la session de mutation testing sur les fichiers modifiés dans la PR, ce qui rend l’outil utilisable en CI sans exploser les temps de run.

Le cas du code sensible : générer ses tests en local avec Ollama

Generation de tests en local avec Ollama

Quand l’envoi du code au cloud est exclu (santé, finance, juridique, R&D)

Plusieurs secteurs n’ont pas le droit d’envoyer leur code source à un service cloud. La santé sous HDS, la finance sous DORA, le juridique soumis au secret professionnel, la défense, la R&D propriétaire. Les contrats de confidentialité interdisent généralement tout transit hors de l’infrastructure maîtrisée. Pour ces équipes, Claude API et Copilot cloud ne sont pas des options. Le RGPD (Règlement Général sur la Protection des Données) ajoute une couche pour tout code manipulant des données personnelles.

Choix d’un modèle code-aware en local (Qwen2.5-Coder, DeepSeek-Coder)

Ollama exécute des modèles en local, sans connexion internet pendant l’inférence. Les modèles code-aware actuels qui tiennent sur une station de travail moderne : Qwen2.5-Coder (versions 7B, 14B et 32B), DeepSeek-Coder V2, et Codestral. Sur un MacBook Pro M3 ou un PC avec 32 Go de RAM, le 14B tourne raisonnablement vite ; pour le 32B, prévoir une carte graphique dédiée. Pour la mise en place complète, voyez notre génération de tests offline avec Ollama et notre stack IA dev 100% locale pour code confidentiel.

Workflow : extraction de signatures → génération offline → validation humaine

L’idée n’est pas d’envoyer 10 000 lignes de code sensible au modèle local, c’est inefficace et inutile. Le workflow gagnant : extraire les signatures de fonctions et les types TypeScript ou les annotations Python, ne donner que ce contrat au modèle, lui demander de générer les tests basés sur la spec extraite, puis valider humainement le fichier produit. Le modèle ne voit jamais l’implémentation. Ce workflow se documente d’ailleurs dans la documentation Claude pour les déploiements multi-environnements.

# Extraction signatures pour génération offline (Node)
npx ts-morph extract --types-only ./src/payment.ts > ./tests/payment.signatures.txt

# Génération en local via Ollama
ollama run qwen2.5-coder:14b < ./tests/payment.signatures.txt \
  --system "Génère des tests Vitest. Pas d'implémentation, uniquement les tests."

# Validation humaine systématique avant merge
git add tests/payment.test.ts
git diff --cached

Pour l’audit de sécurité du code généré (en cloud comme en local), voyez notre auditer la sécurité du code généré par IA et le créer un serveur MCP (sous-pilier) pour automatiser une partie du workflow.

Le workflow d’équipe qui marche

Questions fréquentes

L’IA peut-elle générer des tests vraiment utiles ?

Oui, à condition de la cadrer. Pour les tests unitaires sur une spec claire, le ratio IA dominante fonctionne bien. Pour les tests d’intégration, la supervision humaine reste indispensable. Pour les tests de propriété, l’invariant n’est pas délégable. Le piège est la génération en lot non revue, qui produit du legacy plus vite qu’aucune équipe humaine.

Comment éviter la dette de tests générés par IA ?

Cinq garde-fous : générer test par test, pas en lot ; partir de la spec, pas du code ; lister les cas limites avant de demander la génération ; passer la suite au mutation testing trimestriellement ; revue humaine systématique avant merge.

Quels patterns demander à l’IA pour générer des tests ?

Tests qui échouent d’abord (red puis green), cas limites explicitement listés, tests basés sur la spec et non sur l’implémentation, noms métier descriptifs, assertions sémantiques (pas de snapshot opaque). Demandez aussi à l’IA de proposer les cas limites manquants à votre liste, c’est là où elle apporte de la vraie valeur.

Peut-on générer des tests sur du code sensible sans envoyer dans le cloud ?

Oui, via Ollama avec un modèle code-aware (Qwen2.5-Coder 14B, DeepSeek-Coder V2). Le workflow : extraire les signatures et types, ne donner que la spec au modèle local, valider humainement la sortie. Le modèle ne voit jamais l’implémentation. Adapté aux contextes santé, finance, juridique, défense, R&D où l’envoi vers un service cloud est exclu.

Le mutation testing fonctionne-t-il sur des suites générées ?

Oui, et c’est même son cas d’usage privilégié. Une suite générée par IA affiche typiquement un score de mutation de 40 à 55 %, contre 75-85 % pour une suite manuelle bien pensée. L’écart révèle les trous réels de la couverture. Stryker permet un mode incrémental adapté à la CI.

L’IA aide, le développeur pilote

Trois prises à retenir. Premièrement, la stratégie en quatre niveaux assigne à l’IA un rôle décroissant à mesure que le test gagne en valeur métier. Deuxièmement, le mutation testing reste l’arbitre le plus honnête de la qualité d’une suite. Troisièmement, le code sensible n’est pas une zone interdite à l’IA : Ollama et les modèles code-aware locaux permettent un workflow rigoureux sans transit cloud. Si vous voulez formaliser cette stratégie pour votre équipe, l’équipe WebCreatid peut accompagner le cadrage et la mise en CI ; le formulaire de contact est ouvert.

</> newsletter

Un email quand le prochain paraît.

Rien d'autre.