TDD — Test-Driven Development¶
Le cycle Red/Green/Refactor — écrire le test avant le code pour piloter la conception.
Le principe¶
TDD inverse l'ordre habituel : au lieu d'écrire le code puis les tests, vous ecrivez d'abord le test, puis le minimum de code pour le faire passer, puis vous refactorez.
Ce n'est pas une méthode de test — c'est une méthode de conception. Le test vous force a définir l'interface avant l'implémentation.
Le cycle Red/Green/Refactor¶
graph LR
R["🔴 Red<br/>Ecrire un test<br/>qui echoue"] --> G["🟢 Green<br/>Ecrire le minimum<br/>pour que ca passe"]
G --> RF["🔵 Refactor<br/>Nettoyer sans<br/>changer le comportement"]
RF --> R 1. Red — écrire un test qui échoué¶
Ecrivez un test pour le prochain comportement que vous voulez ajouter. Le test doit échouer pour une raison claire (fonction inexistante, résultat incorrect — pas une erreur de syntaxe).
2. Green — faire passer le test¶
Ecrivez le minimum absolu de code pour que le test passe. Pas d'optimisation, pas de generalisation, pas de gestion d'erreurs superflue. Si le test attend 4, ecrivez return 4. Le prochain test forcera la generalisation.
3. Refactor — nettoyer¶
Le test passe. Maintenant, nettoyez le code et les tests sans changer le comportement. Eliminez la duplication, renommez, extrayez des fonctions. Les tests verts vous donnent un filet de sécurité.
Ne sautez pas le refactor
Le refactor est la partie la plus souvent negligee. Sans lui, le code "Green" accumule de la dette technique. Le cycle sans refactor produit du code qui marche mais qui est illisible.
Baby steps¶
Le TDD fonctionne par petits increments. Chaque cycle ajoute un seul comportement.
Exemple : validation d'email¶
Cycle 1 — une adresse valide :
Cycle 2 — rejeter une adresse sans @ :
Cycle 3 — rejeter une adresse sans domaine :
def is_valid_email(email: str) -> bool:
if "@" not in email:
return False
local, domain = email.split("@", 1)
return len(domain) > 0
Chaque test force une generalisation. Le code emerge des tests, pas d'une conception à priori.
TDD comme outil de conception¶
Design emergent¶
En TDD, vous ne concevez pas l'architecture en amont — vous la decouvrez à travers les tests. Le test vous oblige à :
- définir l'API avant l'implémentation
- penser aux cas d'utilisation avant les cas techniques
- garder les unites petites et decouples (sinon les tests sont penibles a écrire)
Les signaux du test¶
| Signal dans le test | Ce que ca révélé sur le code |
|---|---|
| Test difficile à écrire | L'unite a trop de responsabilités |
| Beaucoup de mocks nécessaires | Couplage fort entre composants |
| Setup complexe (10+ lignes d'arrangement) | L'objet a trop de dépendances |
| Test fragile (casse quand on refactore) | Le test vérifié l'implémentation, pas le comportement |
Quand pratiquer le TDD¶
Le TDD n'est pas toujours le bon outil. Voici un guide pragmatique :
| Situation | TDD recommande ? |
|---|---|
| Logique métier complexe (calculs, règles) | Oui |
| Algorithme avec cas limites | Oui |
| API publique / interface de librairie | Oui |
| Code exploratoire / prototype | Non |
| Intégration avec un service externe | Non (mock ou intégration test) |
| Code UI / layout | Non (test après) |
| Script one-shot | Non |
Le bon reflexe
Si vous hesitez, posez-vous la question : "est-ce que je sais définir le comportement attendu avant d'écrire le code ?" Si oui → TDD. Si non → explorez d'abord, testez ensuite.
Les erreurs courantes¶
| Erreur | Correction |
|---|---|
| Écrire plusieurs tests avant de coder | Un seul test à la fois |
| Écrire plus que le minimum en Green | Si le test passe, arretez. Le prochain test guidera |
| Sauter le Refactor | C'est la moitie de la valeur du TDD |
| Tester des détails d'implémentation | Testez le quoi, pas le comment |
| Vouloir 100% de couverture via TDD | TDD couvre la logique métier, pas les getters/setters |
Outils¶
| Outil | Langage | Lien |
|---|---|---|
| pytest | Python | pytest.org |
| JUnit 5 | Java | junit.org/junit5 |
| Jest | JavaScript | jestjs.io |
| Vitest | JS/TS | vitest.dev |
| go test | Go | pkg.go.dev/testing |
| RSpec | Ruby | rspec.info |
Pour les exemples détaillés par langage, consultez les tutoriels :