TDD assisté par IA : comment tester plus vite sans sacrifier la qualité

TDD assisté par IA : comment tester plus vite sans sacrifier la qualité

Workflow concret : TDD assisté par IA en 7 étapes

Voici le workflow que j'utilise quotidiennement pour faire du TDD avec l'IA. Chaque étape est détaillée avec les commandes exactes.

Étape 1 : Définir le contrat (2 min)

Écrivez la signature de la fonction avec un commentaire décrivant le comportement attendu :

// user-service.ts

/**
 * Calcule le prix final d'une commande avec réductions
 * - Applique la réduction membre si applicable (10%)
 * - Applique le code promo si valide
 * - Plafonne la réduction totale à 30%
 * - Arrondit au centime inférieur
 */
function calculateFinalPrice(
  basePrice: number,
  isMember: boolean,
  promoCode?: string
): number {
  // TODO: implémenter
  throw new Error('Not implemented');
}

Étape 2 : Demander les tests à l'IA (30 sec)

Prompt à l'IA :

Génère les tests Jest pour cette fonction calculateFinalPrice.
Couvre les cas suivants :
- Cas nominal sans réduction
- Réduction membre seule
- Code promo seul
- Cumul membre + promo
- Plafond de 30%
- Edge cases (prix 0, prix négatif, code invalide)

Étape 3 : Valider et ajuster les tests (3 min)

L'IA génère quelque chose comme :

// user-service.test.ts

describe('calculateFinalPrice', () => {
  // Cas nominal
  it('should return base price when no discount applies', () => {
    expect(calculateFinalPrice(100, false)).toBe(100);
  });

  // Réduction membre
  it('should apply 10% member discount', () => {
    expect(calculateFinalPrice(100, true)).toBe(90);
  });

  // Code promo
  it('should apply promo code discount', () => {
    expect(calculateFinalPrice(100, false, 'PROMO20')).toBe(80);
  });

  // Cumul
  it('should cumulate member and promo discounts', () => {
    // 100 - 10% (membre) - 20% (promo) = 70
    expect(calculateFinalPrice(100, true, 'PROMO20')).toBe(70);
  });

  // Plafond 30%
  it('should cap total discount at 30%', () => {
    // 100 - 10% (membre) - 25% (promo) = 65, mais cap à 70
    expect(calculateFinalPrice(100, true, 'PROMO25')).toBe(70);
  });

  // Edge cases
  it('should handle zero price', () => {
    expect(calculateFinalPrice(0, true, 'PROMO20')).toBe(0);
  });

  it('should reject negative prices', () => {
    expect(() => calculateFinalPrice(-10, false)).toThrow();
  });

  it('should ignore invalid promo codes', () => {
    expect(calculateFinalPrice(100, false, 'INVALID')).toBe(100);
  });

  // Arrondi
  it('should round down to nearest cent', () => {
    expect(calculateFinalPrice(99.99, true)).toBe(89.99);
  });
});

Votre rôle : Vérifier que les tests correspondent à la spec métier. Ajoutez/modifiez si nécessaire.

Étape 4 : Lancer les tests (RED) (10 sec)

npm test -- --watch user-service.test.ts

Tous les tests doivent échouer (c'est normal, c'est RED).

Étape 5 : Demander l'implémentation à l'IA (1 min)

Prompt :

Implémente calculateFinalPrice pour faire passer tous ces tests.
Utilise ces codes promo valides :
- PROMO20 : 20%
- PROMO25 : 25%
- PROMO10 : 10%

Étape 6 : Valider l'implémentation (GREEN) (2 min)

L'IA génère :

const PROMO_CODES: Record<string, number> = {
  'PROMO20': 0.20,
  'PROMO25': 0.25,
  'PROMO10': 0.10,
};

const MAX_DISCOUNT = 0.30;
const MEMBER_DISCOUNT = 0.10;

function calculateFinalPrice(
  basePrice: number,
  isMember: boolean,
  promoCode?: string
): number {
  if (basePrice < 0) {
    throw new Error('Price cannot be negative');
  }

  if (basePrice === 0) return 0;

  let totalDiscount = 0;

  // Réduction membre
  if (isMember) {
    totalDiscount += MEMBER_DISCOUNT;
  }

  // Code promo
  if (promoCode && PROMO_CODES[promoCode]) {
    totalDiscount += PROMO_CODES[promoCode];
  }

  // Plafonner à 30%
  totalDiscount = Math.min(totalDiscount, MAX_DISCOUNT);

  // Calculer et arrondir
  const finalPrice = basePrice * (1 - totalDiscount);
  return Math.floor(finalPrice * 100) / 100;
}

Lancez les tests : tout doit passer (GREEN).

Étape 7 : Refactorer si nécessaire (REFACTOR) (2 min)

Demandez à l'IA :

Ce code fonctionne. Peux-tu suggérer des améliorations
de lisibilité ou de performance ?

Temps total : ~10 minutes (vs 30-45 min en TDD traditionnel)


Le Test-Driven Development (TDD) est depuis longtemps considéré comme une pratique d'élite en développement logiciel. Red-Green-Refactor, tests unitaires avant le code, couverture maximale... Mais en 2025, avec l'arrivée des assistants IA comme GitHub Copilot, Claude Code ou Cursor, faut-il encore suivre religieusement ces principes ? Spoiler : oui, mais différemment.

Le TDD Traditionnel : Rappel des Fondamentaux

Le Cycle Red-Green-Refactor

Pour ceux qui débarquent, voici le TDD en 30 secondes :

  1. Red : Écrire un test qui échoue (la fonctionnalité n'existe pas encore)
  2. Green : Écrire le code minimal pour faire passer le test
  3. Refactor : Nettoyer le code tout en gardant les tests verts

Exemple classique en JavaScript :

// 1. RED - Test écrit en premier
test('should calculate sum of two numbers', () => {
  expect(sum(2, 3)).toBe(5);
});

// 2. GREEN - Implémentation minimale
function sum(a, b) {
  return a + b;
}

// 3. REFACTOR - Améliorer si nécessaire
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}

Les Promesses du TDD

Le TDD promettait :

  • Code plus robuste : Les tests forcent à penser aux edge cases
  • Design émergent : Écrire les tests d'abord améliore l'architecture
  • Refactoring sans peur : Les tests garantissent la non-régression
  • Documentation vivante : Les tests montrent comment utiliser le code

La Réalité sur le Terrain

Mais avouons-le, le TDD pur et dur a toujours été difficile :

  • Courbe d'apprentissage raide : Les juniors galèrent à écrire de bons tests
  • Ralentissement initial : On code 2-3x plus lentement au début
  • Discipline extrême requise : Facile de céder à la tentation de coder d'abord
  • Tests fragiles : Un refactoring peut casser des dizaines de tests
  • Débat sans fin : Mocks vs stubs, couverture à 100%, test unitaire vs intégration...

Résultat : dans la vraie vie, peu d'équipes font vraiment du TDD strict. On écrit souvent les tests après coup, ou pire, pas du tout.

L'IA Change la Donne

Ce que les Assistants IA Apportent

1. Génération de tests instantanée

Avec GitHub Copilot ou Claude Code, l'IA génère automatiquement les tests. Vous écrivez une fonction, tapez "test" et appuyez sur Tab.

2. Edge cases automatiquement couverts

L'IA pense à des cas que vous auriez oubliés :

  • Chaînes vides
  • Valeurs nulles/undefined
  • Caractères spéciaux
  • Nombres très grands/petits
  • Cas limites spécifiques au domaine

3. Refactoring assisté

Vous refactorisez une fonction ? L'IA adapte automatiquement les tests correspondants.

4. TDD inversé possible

Nouveau workflow :

  1. Décrire ce que doit faire la fonction (en commentaire)
  2. L'IA génère les tests
  3. L'IA génère l'implémentation
  4. Vous validez et ajustez

Ce que l'IA ne doit JAMAIS faire en TDD

L'IA est un accélérateur puissant, mais certaines responsabilités doivent rester humaines. Voici les lignes rouges à ne jamais franchir.

1. Définir les comportements métier

L'IA ne connaît pas votre domaine. Elle peut générer des tests syntaxiquement corrects mais fonctionnellement faux.

// L'IA pourrait générer ça :
it('should apply discount to premium users', () => {
  expect(calculateDiscount('premium', 100)).toBe(90); // 10% ?
});

// Mais votre règle métier dit :
// - Premium Gold : 15%
// - Premium Silver : 10%
// - Premium Bronze : 5%
// L'IA n'a aucun moyen de le savoir !

Règle : VOUS définissez les cas métier, l'IA génère les assertions.

2. Valider les tests sans les lire

Piège classique : L'IA génère 20 tests, vous les acceptez tous en bloc.

// Test généré par l'IA - DANGEREUX
it('should handle special characters', () => {
  const result = sanitize('hello<script>');
  expect(result).toBe('hello<script>'); // FAUX ! XSS non détecté
});

Règle : Chaque test doit être relu et compris avant d'être accepté.

3. Décider de la stratégie de mock

L'IA mock souvent trop ou pas assez :

// L'IA génère souvent :
jest.mock('./database');
jest.mock('./logger');
jest.mock('./cache');
jest.mock('./auth');
// Résultat : test qui ne teste plus rien de réel

// Vous devez décider :
// - Database : mock (trop lent)
// - Logger : spy (vérifier les appels)
// - Cache : vrai (rapide, important pour le comportement)
// - Auth : mock (dépendance externe)

Règle : La stratégie de mock est une décision d'architecture, pas de génération.

4. Fixer les tests qui échouent

Quand un test échoue, l'IA propose souvent de modifier le test plutôt que le code :

// Test original
it('should return 100 for premium user', () => {
  expect(getPrice('premium')).toBe(100);
});

// Test échoue : getPrice retourne 95

// L'IA suggère : "Modifier le test pour 95"
// MAUVAIS ! Le bug est dans getPrice, pas dans le test

Règle : Un test RED signifie "corrige le code", pas "corrige le test".

5. Supprimer des tests "redondants"

L'IA peut suggérer de supprimer des tests qu'elle juge redondants :

// L'IA pourrait dire : "Ces deux tests sont redondants"

it('should reject empty email', () => {
  expect(validate('')).toBe(false);
});

it('should reject whitespace-only email', () => {
  expect(validate('   ')).toBe(false);
});

// NON ! Ce sont deux cas différents avec des bugs potentiels différents

Règle : La redondance apparente peut cacher des edge cases critiques.

6. Choisir les priorités de test

L'IA ne sait pas ce qui est critique pour votre business :

// L'IA génère tout avec la même priorité :
// - Test formatage de date
// - Test calcul de taxes
// - Test couleur du bouton

// Mais pour vous :
// - Calcul de taxes = CRITIQUE (argent, légal)
// - Formatage date = IMPORTANT (UX)
// - Couleur bouton = NICE TO HAVE

Règle : Vous priorisez, l'IA exécute.

7. Écrire les tests d'intégration et E2E

Les tests d'intégration nécessitent une compréhension du système global :

// L'IA peut aider pour :
it('should call the API endpoint', () => { ... }); // Unitaire

// Mais pas pour :
it('should complete a full checkout flow with payment', () => {
  // Setup base de données test
  // Créer un utilisateur
  // Ajouter des produits au panier
  // Simuler le paiement (sandbox Stripe)
  // Vérifier la commande en DB
  // Vérifier l'email envoyé
  // Vérifier le stock décrémenté
  // ...
});

Règle : Tests E2E = connaissance système = humain.

Récapitulatif : la matrice de responsabilité

TâcheHumainIA
Définir les comportements métier100%0%
Écrire les assertions techniques20%80%
Valider chaque test100%0%
Décider de la stratégie de mock100%0%
Générer les edge cases30%70%
Fixer les tests RED100%0%
Tests d'intégration/E2E80%20%
Refactoring des tests50%50%

Le Nouveau TDD : Assisté par IA

Workflow Hybride Recommandé

Voici comment je pratique le TDD en 2025 avec l'IA :

Pour les fonctions simples (90% des cas)

  1. Écrire la signature de la fonction avec un commentaire JSDoc
  2. Demander à l'IA de générer les tests
  3. Vérifier les tests (RED)
  4. Demander l'implémentation ou la coder soi-même (GREEN)
  5. Refactorer avec l'IA (REFACTOR)

Pour la logique complexe métier

Là, je garde le TDD pur :

  1. J'écris moi-même les tests (domaine métier = connaissance humaine)
  2. L'IA m'aide à implémenter
  3. L'IA suggère des tests supplémentaires que j'aurais ratés

Avantages du TDD Assisté par IA

1. Vitesse décuplée

Avant : 30 minutes pour écrire fonction + tests

Maintenant : 5 minutes (l'IA fait le gros du travail)

2. Qualité des tests améliorée

L'IA pense à des cas edge que même les seniors oublient : encodages spéciaux (UTF-8, émojis), fuseaux horaires, concurrence, limites mémoire.

3. TDD accessible aux juniors

Avant : "Comment je teste ça ?"

Maintenant : L'IA montre des exemples de tests, le junior apprend en observant

4. Documentation automatique

Les tests générés par l'IA incluent souvent des descriptions claires.

Les Pièges à Éviter

1. Faire Confiance Aveuglément à l'IA

Problème : L'IA peut générer des tests qui passent mais ne testent pas vraiment.

Solution : Toujours relire et compléter les tests générés.

2. Tests Trop Couplés à l'Implémentation

L'IA a tendance à tester l'implémentation plutôt que le comportement. Préférez tester le comportement observable plutôt que les détails internes.

3. Sur-Génération de Tests

L'IA peut générer 50 tests pour une fonction simple. Savoir dire stop.

Règle : Viser la couverture des comportements, pas la couverture de code à 100%

4. Oublier les Tests d'Intégration

L'IA excelle en tests unitaires, mais les tests d'intégration restent souvent manuels.

Cas Concrets : Avant/Après

Exemple 1 : API REST

Avant (TDD pur, 2h de travail) :

  1. Écrire tous les tests d'endpoints
  2. Implémenter les routes
  3. Débugger les tests qui cassent
  4. Refactoriser

Maintenant (TDD assisté IA, 30min) :

  1. Définir le schéma OpenAPI
  2. L'IA génère les tests basés sur le schéma
  3. L'IA génère le code boilerplate
  4. Je complète la logique métier
  5. L'IA suggère des tests de sécurité (injection SQL, XSS)

Exemple 2 : Parser de données

Avant : Galère à imaginer tous les formats d'entrée possibles

Maintenant : Vous demandez à l'IA de générer des tests pour un parser CSV gérant les virgules dans les champs quotés, différentes fins de ligne (LF, CRLF), lignes vides, UTF-8 avec BOM... L'IA génère 20+ tests couvrant tous ces cas en 10 secondes.

L'Avenir du TDD

TDD Génératif

Demain (déjà en beta sur certains outils) :

  1. Vous décrivez le besoin en langage naturel
  2. L'IA génère une suite de tests complète
  3. L'IA propose plusieurs implémentations
  4. Vous choisissez la meilleure ou hybridez
  5. L'IA génère les tests de régression automatiquement

TDD Prédictif

L'IA analysera votre historique de bugs en production et générera préventivement des tests pour les scénarios à risque.

TDD Collaboratif

L'IA deviendra un pair programmer pour le TDD, analysant le contexte et suggérant les tests pertinents avant même que vous les écriviez.

Mon Avis Après 6 Mois de TDD + IA

Ce qui Fonctionne Vraiment

  • Tests unitaires simples : L'IA est meilleure que moi
  • Couverture edge cases : L'IA pense à des trucs loufoques mais réels
  • Tests de régression : Génération instantanée après un bug
  • Apprentissage : Les juniors progressent 3x plus vite

Ce qui Nécessite Encore l'Humain

  • Tests métier complexes : L'IA ne connaît pas votre domaine
  • Tests end-to-end : Trop de contexte, trop de setup
  • Choix d'architecture de tests : Faut-il mocker ce service ou non ?
  • Tests de performance : L'IA suggère mais ne comprend pas vos contraintes

La Vraie Révolution

Le TDD assisté par IA ne remplace pas la discipline du TDD. Il l'amplifie.

Avant : Seuls les développeurs disciplinés faisaient du TDD

Maintenant : Tout le monde peut faire du TDD car la friction a disparu

C'est comme passer de l'escalade libre à l'escalade avec assurance : le but est le même (monter), mais l'un est accessible à tous, l'autre réservé aux experts.

Conclusion : Le TDD n'est Pas Mort, il Mute

Le titre était volontairement provocateur. Le TDD n'est pas mort, il évolue.

Le TDD de 2025 :

  • Tests écrits avec l'IA, pas par l'IA
  • Focus sur le comportement métier (humain) + edge cases techniques (IA)
  • Cycle Red-Green-Refactor accéléré par l'assistance
  • Tests comme conversation avec l'IA

Ce qui ne change pas :

  • L'importance de tester
  • La valeur des tests comme documentation
  • Le refactoring sans peur grâce aux tests
  • La nécessité de comprendre ce qu'on teste

La vraie question n'est plus "Faut-il faire du TDD ?" mais "Pourquoi ne pas faire de TDD maintenant que c'est si facile ?"


Et vous, utilisez-vous l'IA pour vos tests ? Quel est votre workflow ? Partagez en commentaire !