Le Test-Driven Development suit un cycle Rouge-Vert-Refactoring : écrire un test qui échoue, écrire le minimum de code pour le faire passer, puis refactoriser.
Le cycle TDD : Rouge, Vert, Refactoring
Le TDD suit un cycle strict de trois étapes :
1. Rouge : écrire un test qui échoue (parce que la fonctionnalité n'existe pas encore)
2. Vert : écrire le minimum de code pour faire passer le test
3. Refactoring : nettoyer le code en gardant les tests en vert
Ce cycle se répète pour chaque petite partie de la fonctionnalité.
// Phase Rouge : écrire un test qui échoue
test('calculateDiscount applies 10% for code SAVE10', () => {
const result = calculateDiscount(100, 'SAVE10');
expect(result).toBe(90);
});
// Exécuter ce test échoue : calculateDiscount n'est pas définie// Phase Verte : écrire le minimum de code pour passer
function calculateDiscount(price: number, code: string): number {
if (code === 'SAVE10') {
return price * 0.9;
}
return price;
}
// Maintenant le test passe// Phase Refactoring : nettoyer sans casser le test
const DISCOUNT_CODES: Record<string, number> = {
SAVE10: 0.1,
SAVE20: 0.2,
SAVE50: 0.5,
};
function calculateDiscount(price: number, code: string): number {
const discount = DISCOUNT_CODES[code] || 0;
return price * (1 - discount);
}
// Les tests passent encore : le refactoring n'a rien casséBénéfices du TDD qui affectent le QA
Code naturellement testable :Le code écrit en TDD a tendance à avoir des fonctions plus petites avec des entrées et sorties claires, plus faciles à tester à tous les niveaux.
Sécurité de régression :Chaque comportement est protégé par un test. Quand le QA trouve un bug, les développeurs peuvent le reproduire avec un test, le corriger, et le test prévient la régression.
Documentation par les tests :Les tests TDD décrivent ce que le code doit faire dans des scénarios spécifiques. Le QA peut lire les tests pour comprendre le comportement attendu.
Détection plus précoce des bugs :Les problèmes détectés lors de l'écriture des tests unitaires coûtent bien moins cher à corriger que ceux trouvés en QA ou en production.
Behavior-Driven Development (BDD)
Le BDD étend le TDD vers la couche métier. Là où le TDD se concentre sur comment le code fonctionne, le BDD se concentre sur quel comportement est requis.
Les trois amigos, développeur, QA et chef de produit, collaborent pour définir le comportement en format Given/When/Then avant d'écrire du code.
Feature: Discount codes
Scenario: Valid discount code reduces price
Given I have a cart with items totaling $100
When I apply discount code "SAVE10"
Then the total should be $90
And the discount amount should be $10
Scenario: Invalid discount code shows error
Given I have a cart with items totaling $100
When I apply discount code "INVALID"
Then I should see "Invalid discount code"
And the total should remain $100
Scenario: Expired discount code shows error
Given I have a cart with items totaling $100
When I apply discount code "EXPIRED20"
Then I should see "This discount code has expired"Comment le QA peut appliquer l'état d'esprit TDD
Même si vous n'écrivez pas de tests unitaires, vous pouvez appliquer l'état d'esprit TDD.
Écrire les cas de test avant que les tests manuels commencent
Au lieu de faire des tests exploratoires de zéro, rédigez d'abord les comportements attendus :
Feature: Réinitialisation de mot de passe
Ce que j'attends qui soit vrai :
1. Saisir un e-mail valide envoie un e-mail de réinitialisation dans les 2 minutes
2. Saisir un e-mail invalide affiche "E-mail introuvable"
3. Le lien de réinitialisation expire après 24 heures
4. Utiliser un lien expiré affiche "Lien expiré" avec option de demander un nouveau
5. Après une réinitialisation réussie, l'ancien mot de passe ne fonctionne plus
6. Le lien de réinitialisation ne peut être utilisé qu'une seule foisVous avez maintenant un plan de test avant de commencer les tests.
Développement piloté par les tests d'acceptation (ATDD)
Collaborez avec les développeurs pour rédiger des tests d'acceptation avant que la fonctionnalité soit construite :
// Rédigé avant que la fonctionnalité existe
test('checkout with valid card completes purchase', async ({ page }) => {
// Configuration : utilisateur avec articles dans le panier
// ...
// Exécuter le checkout
await page.fill('[data-testid="card-number"]', '4242 4242 4242 4242');
await page.fill('[data-testid="card-expiry"]', '12/28');
await page.fill('[data-testid="card-cvc"]', '123');
await page.click('[data-testid="pay-now"]');
// Résultats attendus
await expect(page).toHaveURL('/order-confirmation');
await expect(page.getByTestId('order-number')).toBeVisible();
await expect(page.getByTestId('success-message')).toContainText('Payment successful');
});Ces tests échouent jusqu'à ce que la fonctionnalité soit construite. Quand ils passent, la fonctionnalité est terminée.
Quand les développeurs pratiquent le TDD : ce que le QA doit savoir
Ce qui change pour le QA
La couverture de tests unitaires existe déjà :Les développeurs ont déjà testé les cas limites au niveau du code. Le QA peut se concentrer sur les points d'intégration, les flux utilisateur et la logique métier, pas sur le comportement des fonctions de base.
Les échecs de tests sont significatifs :Quand la CI d'une équipe TDD casse, c'est précis. "La fonction X retourne une valeur incorrecte pour le cas limite Y" et non pas "l'application est cassée quelque part".
Le refactoring est plus sûr :Avec des tests unitaires complets, le QA n'a pas besoin de retester les fonctionnalités de base après un refactoring : les tests couvrent déjà ça.
Ce que le QA doit encore faire
Tests d'intégration :Les tests unitaires testent les fonctions en isolation. Le QA teste comment les composants fonctionnent ensemble : la base de données, l'API, le frontend, le système d'e-mails.
Tests du point de vue utilisateur :Les développeurs testent "est-ce que le code fonctionne ?". Le QA teste "est-ce que la fonctionnalité est intuitive à utiliser ?"
Découverte de cas limites :Les tests exploratoires du QA trouvent des scénarios qui n'ont pas été spécifiés. Le TDD ne couvre que ce qui a été pensé lors de l'écriture des tests.
Performance et fiabilité :Le TDD ne couvre pas les temps de réponse, les utilisateurs concurrents, ni ce qui se passe sous charge.
TDD pratique pour l'automatisation des tests
Quand vous construisez votre framework de test, appliquez les principes TDD :
// Au lieu d'écrire l'helper complet d'abord, écrivez un test pour ce que vous voulez qu'il fasse
test('login helper should redirect to dashboard after login', async ({ page }) => {
await loginAs(page, 'member'); // Cette fonction n'existe pas encore
await expect(page).toHaveURL('/dashboard');
});
// Maintenant écrivez l'implémentation minimale
async function loginAs(page: Page, role: 'admin' | 'member') {
const credentials = {
admin: { email: 'admin@test.com', password: 'AdminPass1' },
member: { email: 'member@test.com', password: 'MemberPass1' },
};
await page.goto('/login');
await page.fill('[data-testid="email"]', credentials[role].email);
await page.fill('[data-testid="password"]', credentials[role].password);
await page.click('[data-testid="submit"]');
await page.waitForURL('/dashboard');
}Cela prévient la sur-ingénierie. Vous construisez exactement ce qui est nécessaire, et le test confirme que ça fonctionne.
La pyramide de tests dans le contexte TDD
Le TDD façonne directement la pyramide de tests :
/\
/E2E\ ← Automatisation QA (moins, plus lents)
/------\
/ Intégr.\ ← Tests d'intégration (modérés)
/----------\
/ Unitaires \ ← Production TDD (nombreux, rapides)
/--------------\Le TDD produit la large base de tests unitaires. Le QA construit les couches d'intégration et E2E par-dessus. Ensemble, ils forment une pyramide où la plupart des bugs sont détectés à faible coût au niveau unitaire, avec un ensemble plus petit de tests E2E coûteux mais ciblés.
Résumé
- Cycle TDD : Rouge (test qui échoue) → Vert (faire passer) → Refactoring (nettoyer)
- Le TDD produit du code naturellement testable et bien structuré
- Le BDD étend le TDD vers le comportement métier avec les scénarios Given/When/Then
- ATDD : le QA rédige les tests d'acceptation avant que le développement commence ; les tests échouent jusqu'à ce que la fonctionnalité soit construite
- Quand les développeurs pratiquent le TDD, le QA se concentre sur l'intégration, les flux utilisateur et les cas limites
- Appliquer l'état d'esprit TDD à l'automatisation des tests : rédiger l'interface de test d'abord, puis implémenter
Le TDD et le QA sont complémentaires, pas concurrents. Le TDD détecte les bugs de niveau unitaire tôt. Le QA détecte les problèmes d'intégration et d'expérience utilisateur. Ensemble, ils produisent des logiciels qui fonctionnent correctement à chaque niveau.
→ See also: Développement Piloté par les Tests: Le Guide de l'Ingénieur QA | Tests Shift-Left: Ce que Cela Signifie et Comment le Pratiquer | La Pyramide des Tests Expliquée pour les Ingénieurs QA