🧪 Développement Piloté par les Tests (TDD)
📖 Définition
TDD (Test-Driven Development) est une méthodologie de développement où vous écrivez d'abord les tests, puis écrivez du code pour réussir ces tests. Il suit le cycle Rouge-Vert-Refactor, améliorant la qualité du code, réduisant les bugs et rendant le refactoring plus sûr. Les tests unitaires vérifient les fonctions ou composants individuels de manière indépendante.
🎯 Analogie Simple
Plan d'Abord
Développement Traditionnel
1. Construire une maison
2. Vérifier après achèvement
3. Trouver des problèmes → Grandes corrections
4. Coût augmente
TDD
1. Dessiner un plan (Écrire un test)
2. Construire selon le plan (Écrire du code)
3. Vérifier (Exécuter le test)
4. Améliorer (Refactoriser)
5. Sûr et précis
⚙️ Fonctionnement
Cycle TDD (Rouge-Vert-Refactor)
🔴 Rouge (Échec)
└─ Écrire un test → Échec (pas de code)
🟢 Vert (Succès)
└─ Écrire un code minimal → Test réussit
🔵 Refactor (Améliorer)
└─ Améliorer le code → Test réussit toujours
Répéter → Amélioration progressive
💡 Exemples Clés
Exemple TDD de Base
// ========== 1. Rouge: Écrire un test (échoue) ==========
test('la fonction add additionne deux nombres', () => {
expect(add(2, 3)).toBe(5);
});
// FAIL - add n'est pas défini
// ========== 2. Vert: Code minimal (réussit) ==========
function add(a, b) {
return a + b;
}
// PASS ✅
// ========== 3. Refactor: Améliorer (si nécessaire) ==========
// Le code est simple, pas d'amélioration nécessaire
Test Unitaire avec Jest
// user.js
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
isValidEmail() {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(this.email);
}
}
// user.test.js
describe('User', () => {
let user;
beforeEach(() => {
user = new User('Jean', 'jean@example.com');
});
test('devrait retourner true pour un email valide', () => {
expect(user.isValidEmail()).toBe(true);
});
test('devrait retourner false pour un email invalide', () => {
user.email = 'invalid-email';
expect(user.isValidEmail()).toBe(false);
});
});
Test Asynchrone
test('fonction async retourne des données', async () => {
const data = await fetchData();
expect(data).toEqual({ name: 'John' });
});
Mocking
// Mock de fonction
const mockCallback = jest.fn(x => x * 2);
[1, 2, 3].forEach(mockCallback);
expect(mockCallback).toHaveBeenCalledTimes(3);
// Mock de module
jest.mock('axios');
test('fetchUser retourne les données utilisateur', async () => {
axios.get.mockResolvedValue({ data: { id: 1 } });
const user = await fetchUser(1);
expect(user).toEqual({ id: 1 });
});
🤔 FAQ
Q1. Avantages de TDD ?
R:
Avantages:
1. Moins de bugs
2. Refactoring sûr
3. Meilleure qualité de code
4. Documentation
5. Confiance
Inconvénients:
1. Investissement de temps initial
2. Courbe d'apprentissage
3. Maintenance des tests
Conclusion: Gain à long terme
Q2. Que Tester ?
R:
// ✅ Devrait tester
1. Logique métier
2. Cas limites
3. Gestion des erreurs
4. APIs publiques
// ❌ Pas besoin de tester
1. Bibliothèques externes
2. Getters/setters simples
3. Détails d'implémentation privée
Q3. Objectif de Couverture ?
R:
# Mesurer la couverture
npm test -- --coverage
# Objectif:
80%+ couverture // Objectif réaliste
100% couverture // Idéal mais peu pratique
# Rappelez-vous:
Haute couverture ≠ Bons tests
Les tests significatifs comptent !
🎬 Résumé
TDD est la base de la qualité logicielle :
- Rouge-Vert-Refactor: Cycle central de TDD
- Tests Unitaires: Rapides et isolés
- Test d'Abord: Les tests guident la conception
- Amélioration Continue: Filet de sécurité pour le refactoring
Les tests sont un investissement pour votre futur vous ! 🧪✨