Le cycle rouge-vert-refactor
Le gain du jour : exécuter le cycle rouge → vert → refactor trois fois de suite sur un exemple minuscule, et sentir la différence avec « coder puis tester après coup ».
Le cycle
Le TDD n’est pas « écrire des tests ». C’est un cycle discipliné, répété en boucles très courtes :
- Rouge — écrire un test qui échoue, pour un comportement qui n’existe pas encore.
- Vert — écrire le code le plus simple possible qui fait passer le test (tricher est permis).
- Refactor — nettoyer le code, tests toujours au vert.
Règle d’or : jamais plus d’un test qui échoue à la fois. Si deux tests sont rouges, on est allé trop vite.
Dans un vrai projet, le test s’écrit dans un fichier test_*.py et se lance avec pytest. Ici,
sur cette page, on simule le même geste : le champ tests ci-dessous joue le rôle du fichier de
test (assert nu, comme pytest les réécrit), et tu écris le code de production juste au-dessus.
Lis d’abord l’assertion, imagine-la « rouge », puis écris le code minimal pour la faire passer.
Kent Beck, Test-Driven Development: By Example — le livre qui a défini ce cycle. Les premiers chapitres suffisent pour aujourd’hui.
L’exemple : un compte bancaire minimal
On construit une classe CompteBancaire avec juste assez de comportement pour voir le cycle
tourner : un solde qui démarre à zéro, un dépôt, un retrait qui refuse si le solde est insuffisant.
Tour 1 — solde initial
Rouge : assert compte.solde == 0 échouerait avec NameError si CompteBancaire n’existait
pas encore — c’est le bon type d’échec, pas une faute de frappe dans le test.
Vert : le code le plus simple qui satisfait ce test.
Tour 2 — un dépôt
Rouge d’abord : imagine compte.deposer(50) sans que la méthode existe → AttributeError.
Vert : ajoute juste ce qu’il faut, rien de plus (pas de retirer par anticipation).
Tour 3 — retrait refusé
Refactor. Relis les trois tours : rien ne crie encore « dupliqué » ou « confus » à ce stade — trois tours, c’est court. Le réflexe à ancrer aujourd’hui : après chaque vert, on regarde s’il y a lieu de nettoyer, même si souvent la réponse est non.
Remarque le style classiciste ici : aucun double de test (mock), aucun stub. CompteBancaire
est un objet réel, on vérifie son état (solde) après l’action — c’est la vérification par
état dont parle Martin Fowler dans « Mocks Aren’t
Stubs », par opposition au style
mockiste qui vérifie des appels plutôt que de l’état.
Vérifie ta compréhension
Laquelle des trois étapes du cycle autorise explicitement à écrire du code « en trichant » (valeur en dur, par exemple) ?
Pourquoi un NameError est-il un « bon » rouge, contrairement à un rouge causé par une faute de frappe dans le test ?
À toi de jouer
Ajoute un 4ᵉ tour, toi-même, dans l’éditeur ci-dessous : un dépôt d’un montant négatif doit lever
une exception MontantInvalide. Écris d’abord le test (le champ tests), imagine-le rouge, puis
seulement écris le code.
Une fois vert, relis les 4 exercices : y a-t-il une duplication qui mériterait un refactor (par exemple factoriser la création du compte, ou la vérification de montant) ? Pose la question ici si un point du cycle reste flou — c’est exactement le rôle de ce dialogue.
🗂 Fiche de référence associée : Cycle TDD & pytest — antisèche.