Une grosse partie des projets informatiques finissent par être considérée comme des échecs. Certaines raisons peuvent être dues à des problèmes concernant la partie fonctionnelle ou managériale du projet (un projet mal défini, micro management…).
D’autres raisons comme la mauvaise qualité du code produit par les développeurs peuvent expliquer aussi ces fiascos. Par exemple, au fur et à mesure que le produit se développe, le code change entraînant de plus en plus de bugs. Ces derniers ralentissent le développement et rendent mécontents les clients finaux.
Quand les équipes sont conscientes de ces risques et veulent les minimiser au maximum elles mettent en place une politique de tests. Ils le font pour contrôler le comportement de leur code et ainsi diminuer le nombre de bugs.
Cependant ,on se rend compte que la mise en place d’une politique de tests automatiques dans une équipe non expérimentée sur ce sujet est rarement une promenade de santé. A cause de ces difficultés certaines équipes ou personnes peuvent abandonner la mise en place de cette stratégie.
J’ai donc décidé d’écrire un article pour aider les ingénieurs qui souhaitent mettre en place des tests automatisés dans leurs projets informatiques. Pour plus d’efficacité, je vais partir sur un cas concret rencontré lors du développement de mon projet actuel.
Avant d’aller plus loin, je souhaite expliquer pourquoi faire des tests automatisés est un très bon moyen pour développer rapidement en minimisant le risque de bugs.
Pourquoi faire des tests?
A quoi ça sert?
Le rôle principal d’un test est de valider un comportement. Ce dernier doit être valide aujourd’hui, dans un mois ou après des centaines de modifications de votre code.
Pourquoi est-ce utile?
N’étant pas omniscient, il y a de gros risques que lors d’une modification future, vous cassiez le comportement d’une fonctionnalité. Si vous ne vous en rendez pas compte, vos utilisateurs risquent de le voir. Le coût de la correction sera alors démultiplié. Plus une erreur prend du temps à être détectée plus elle coûte chère. Il est plus facile de modifier le code qui vient d’être écrit que celui qui a été fait y a trois mois dont vous ne vous souvenez plus et qui vous obligera à faire une mise en production risquée.
Quand vous travaillez en équipe, vos collègues ne connaissent pas forcément tout le code applicatif. Une de leur modification peut casser le comportement que vous avez développé il y a quelques mois.
Les tests vont permettre d’éviter ces problèmes.
Meilleure focalisation
En faisant des tests vous allez vous rendre compte que vous avez développé une meilleure focalisation avec ces quelques avantages :

Effets secondaires positifs
En écrivant des tests unitaires, vous allez vous rendre compte que vous allez devoir écrire du code en respectant les principes du Clean Code.
Pourquoi ?
Il est plus facile de tester une classe courte et focus sur un rôle qu’une classe faisant 400 lignes avec plein de responsabilités. De plus en faisant des tests unitaires vous allez devoir isoler certaines parties de votre programme qui appelle par exemple des ressources extérieures (bases de données, url, fichiers…).
Sans vous en rendre compte, votre code produit va être de plus en plus maintenable.
Maintenant que les raisons de l’importance de la pratique du TDD vous ont été partagées, je vous propose de vous présenter l’application et sa feature qui serviront à illustrer la mise en place de cette pratique de développement.
ElectionScenario : l’API en développement
Rapide rappel sur le projet en développement
En parallèle des articles de blog, je développe un simulateur d’élections législatives à partir des résultats des élections 2022 et 2024 composés de plusieurs applications.
Actuellement, je travaille sur l’API qui servira de back au futur front.
Ces simulations se basent sur une des trois règles de scrutins expliqués précédemment :
- Majorité à un tour
- Proportionnelle nationale
- Proportionnelle départementale
L’implémentation de la troisième règle est la feature qui va être utilisée dans cet article pour illustrer le développement en TDD.
Workflow de la simulation d’élections avec la règle « Proportionnelle départementale ».

Après avoir analysé et compris ce workflow, il faut se poser la question en quoi les tests et le TDD vont m’aider au développement de cette feature.
Après avoir vu le fonctionnel de notre feature, et compris l’importance des tests unitaires, il est temps de voir comment intégrer ces derniers dans notre processus de développement dans le développement de notre feature.
Comment faire?
Vous venez de prendre la décision que vous voulez faire des tests unitaires. Je vous en félicite, c’est une très bonne nouvelle. Comme vous ne savez pas par où commencer, je vous propose de continuer à lire cet article pour avoir un exemple de programme développé avec des tests.
Padawan des tests
D’abord, renseignez-vous exactement sur les définitions des termes suivants :
Pour commencer le développement TDD et vos premiers tests unitaires en étant débutant je vous donne deux conseils :
- Faites-vous accompagner par un senior sachant faire des tests unitaires et développer en TDD. Il vous vulgarisera les concepts, vous fera gagner du temps d’apprentissage et vous corrigera en cas d’erreur.
- Pour vos premiers essais commencer pendant votre temps libre ou au travail si vous pouvez faire de la veille technique, en faisant des Katas (https://codingdojo.org/kata/). Ce sont des petits exercices pouvant être réalisés en TDD. Puis après avoir fait plusieurs katas, il va falloir utiliser le TDD et les Tests unitaires dans le développement de vrais projets. Vous pouvez soit le faire sur vos projets pros ou soit sur vos projets persos avec un enjeu business ou fonctionnel.
Pour ma part j’ai plus ou moins utilisé les deux méthodes pour acquérir de l’expérience sur le TDD et les tests unitaires. J’ai commencé par m’auto former puis ma façon de faire a évolué grâce aux échanges avec des gens plus seniors que moi sur le sujet et par l’expérimentation sur mes projets, pros et persos.
Comment faire du TDD?
Dans la partie 2, je vous ai décrit la nouvelle feature à développer. Elle est composée de plusieurs sous features. Si je veux réaliser son développement comment je fais ? Est-ce que je développe en TDD en premier les sous-features et après, je fais la classe qui les appelle ou je commence par le haut pour ensuite faire les développements secondaires ?
Pour répondre à ces questions, je vais vous présenter trois façons dont vous pouvez coder les tests.
Inside Out
Votre but est de commencer par développer des features ou des sous features indépendantes. Vous ne pouvez pas commencer par quelque chose qui appelle une autre fonction ou classe qui n’a pas été programmée en TDD.
Si on reprend l’exemple au-dessus, vous pouvez développer la feature 2 si ses sous features (a, b, c…) ont été développées en TDD avant.
Pour vous aider voilà un schéma qui va vous aider pour comprendre l’ordre de développement de toutes les features.

Comme le montre le schéma, on commence soit par une fonctionnalité qui n’a pas de sous-fonctionnalités ou soit par des sous-features indépendantes en terminant par celles qui sont dépendantes.
Est-ce que cette méthode est ultime ? Non. Voici un tableau qui selon moi expose ses points forts et faibles
| Avantages | Inconvénients |
| Si un test est KO, on sait rapidement où l’erreur a eu lieu et quoi d’être corrigé | On ne teste pas forcément, correctement le workflow complet de la feature |
| Facile à tester les cas exceptionnels, car on peut le faire là où ils se produisent. | Comme on commence par des petites features, on peut facilement se perdre dans le développement et développer des sous features qui ne seront pas utilisés ultérieurement. |
| Petits tests faciles à comprendre | Multiplication des tests unitaires |
| Si le code change et non le fonctionnement, on doit reprendre les tests. |
Outside In
Ici, on va plus se concentrer par tester la feature principale et non sur les sous features. Pourquoi ? Comme la feature principale appelle les sous features, si ses tests sont verts ça veut dire que toutes les sous features fonctionnent correctement.

D’abord, on développe le cas passant de la feature principale. Ensuite, on travaille sur la feature principale, puis ses sous features et … jusqu’à ce que tout soit développé.
Quand on a terminé de développer le cas passant, on créait de nouveaux tests pour ajouter de nouveaux cas fonctionnels. Ainsi, on modifie tout le code produit pour répondre à tous les cas.
Quand vous développez la feature principale vous n’allez pas forcément créer les futures classes qui vont être codées pour les sous features. Vous pouvez créer du code qui renverra des données « faites à la main ». Plus tard quand la sous-feature sera terminée, vous utiliserez le code qui appelle la sous-feature.
Selon moi voici un tableau résumant les avantages et les désavantages de cette solution.
| Avantages | Inconvénients |
| Tests plus fonctionnels donc si le code change peu d’impact voir aucun sur les tests | En cas de tests KO, vous mettrez du temps à trouver où est l’erreur comme vous ne tester pas toutes les sous-classes |
| Workflow testé | Vos tests peu nombreux risquent d’être volumineux et longs à écrire, car vous devrez couvrir à un seul endroit tous les cas. |
| On ne développe pas des features inutiles |
Troisième solution : double loop TDD
Chaque façon de faire possède des avantages et des inconvénients comme le montre les tableaux.
Comment faire pour trouver une méthode qui allie les avantages du inside out et du outside in ? En faisant le double loop TDD comme le montre ce workflow:

Comme on peut le voir dans cette méthode, on commence par le test de la feature principale puis on développe cette dernière. Ensuite, on se met à coder en TDD la feature 1, puis la 2 ….
Dans ce cas, les différents cas à tester ne seront pas contenus dans les tests de la feature principale, mais dans les tests de la feature concernés par ces différents cas.
Voici un tableau illustrant les avantages et les inconvénients de cette méthode :
| Avantages | Inconvénients |
| Si un test est KO, on sait rapidement où l’erreur a eu lieu et quoi d’être corrigée | Beaucoup de tests à écrire |
| Facile à tester les cas exceptionnels, car on peut le faire là où ils se produisent. | Si le code change et non le fonctionnement, on doit modifier les tests |
| Petits tests faciles à comprendre | |
| Workflow testé | |
| On ne développe pas de features inutiles |
Et moi qu’est ce que j’en pense et qu’est ce que je choisis?
Dans mon apprentissage des tests, j’ai commencé par le Inside Out. Cependant, j’ai eu de gros problèmes :
- J’avais beaucoup de bugs à corriger quand je développais le workflow qui allait orchestrer toutes les fonctionnalités codées.
- Je développais de features inutiles, car je me concentrais d’abord sur une feature isolée sans savoir si elle sera utilisée dans le worflow final.
Je ne suis pas assez convaincu par la solution 2. Pour moi, il est important de comprendre rapidement pourquoi un test est KO. Si ce dernier appelle la terre entière, vous allez mettre du temps à le corriger.
J’utilise la solution 3 depuis plusieurs mois. Je la trouve super même si je rends compte qu’elle prend du temps et qu’elle est verbeuse.
Peut-être que dans un projet futur, je partirai uniquement sur la solution 2 pour challenger mon avis.
Après avoir expliqué pourquoi il faut faire des tests, quelles features allaient être développés et quelles façons d’écrire allaient être choisis, il nous manque plus qu’à commencer à développer notre feature en TDD.
Mise en pratique
Il est de temps d’utiliser le TDD pour développer nos propres features. Je vous propose de mettre en pratique en partant sur la fonctionnalité 2 :
«À partir des données récupérées, on va parcourir chaque département français pour faire plusieurs tâches permettant de trouver les élus. »
Voici le workflow de développement :
1 – Créer le squelette de la classe et de sa méthode principale

2 – Créer le premier test sans le résoudre.
Comme vous pouvez le voir, le test est KO.
3 – Maintenant, il faut résoudre ce test de la manière la plus simple possible. Pour se faire, on va écrire du code en dur.

Comme on peut le voir le test est résolu.

4 – Comme on le voit dans la partie 2, cette fonctionnalité possède des sous-fonctionnalités. Maintenant, on va commencer par le développement de la sous-feature « On compte combien de députés possède ce département ». Elle sera développée dans la classe « GetCandidatesByDepartmentGroupedByDistrict.

5 – Maintenant, on va développer le premier test qui sera bien sur KO

6 – Nous partons sur uniquement un seul test, car les cas d’utilisations de cette classe ne varient pas. On peut donc écrire le code qui va résoudre ce test :

Puis on relance les tests et on voit que tout fonctionne.

7 – Maintenant on va faire la même chose pour toutes les autres sous-fonctionnalités. Après les avoir développées et les avoir faites appelées par la classe CongressPersonByDepartment permettant de faire fonctionner la feature principale, le code final de la feature ressemble à ça :

Pour être sûr que tout soit couvert, on a écrit plusieurs tests pour plusieurs types de département :

J’ai essayé de vous montrer comment j’avais développé cette fonctionnalité en faisant du TDD. Ce n’était pas parfait, mais j’espère que ca vous aider à vous lancer dans le développement piloté par les tests.
En faisant du TDD, vous allez avoir deux challenges :
- La construction de vos jeux de données
- La validation de vos tests
Ces deux besoins peuvent devenir rapidement verbeux, longs à écrire et embêtant à maintenir. Pour cela, je vous propose quelques petites astuces vous permettant d’être efficace.
Comment avoir des données de tests rapidement et pouvoir valider efficacement nos tests ?
Dans cette partie, je vous propose de vous aider pour trouver des astuces pour avoir rapidement vos données à tester et des méthodes pour valider vos tests.
Les données
Quand on apprend le TDD, on vous montre des tests assez simples. Ils valident une valeur ou un objet simple. Cependant, en réalité vous allez devoir faire des tests sur des objets complexes.
Dans mon projet par exemple, quand je veux tester la simulation d’une élection en mode proportionnelle départementale, j’ai besoin d’un objet « election_result » constitués d’une multitude de sous-objets comme on le voit ci-dessous :

Si je devais créer cet objet à la main, cela me prendrait beaucoup de temps et d’énergie. Il faut trouver un moyen pour avoir la possibilité de créer des objets complexes utilisables assez rapidement.
JSON
En utilisant la déserialisation JSON, on peut facilement créer des objets complexes pour nos tests.
Tout d’abord on créé notre objet JSON en s’aidant de ce site super pratique JsonFormatter.

Puis il suffit de minifier ce JSON comme le site Jsonformatter permet de le faire. On stocke le json minifié dans une variable. Il suffit de le déserialiser dans un objet python pour pouvoir l’utiliser dans nos tests comme le montre cet exemple :


Ce code est facilement modifiable pour être réutilisable.
Assert
Un moment, vous allez devoir vérifier que l’objet obtenu après l’exécution de votre test correspond bien au résultat attendu. Si vous avez un long objet à vérifier, il risque de devenir volumineux.
À l’heure actuelle, comme je teste souvent des objets d’un même type, j’ai décidé de créer des méthodes d’assertions que j’appelle à chaque test.
Par exemple dans le test suivant :
Dans ce test, la méthode Select de la classe CongressPersonElected doit sélectionner dans chacun des circonscriptions passées en paramètre le candidat élu. La partie « expected » est une chaîne de caractère regroupant les données du candidat élu attendu avec pour séparateur |.
Pour gagner en clarté, j’ai centralisé l’assertion des CongressPerson à un seul endroit comme on le voit ci-dessous :
![]()

Cette façon de faire les assert n’est pas la meilleure. On pourrait utiliser la serialisation JSON et comparer les deux chaînes de caractères. Peut-être que j’utiliserai cette façon d’asserter dans un prochain projet.
Grâce à toutes ces améliorations, on va gagner du temps, et rendre nos tests plus lisibles et maintenables.
Avant de conclure cet article, je voudrais échanger sur les limites du TDD que je pratique. Même si je trouve cela très efficace et je pense que cela devrait une pratique maîtrisée et pratiquée par les équipes de dev. Elle n’est pas magique et possède aussi des défauts que j’ai envie de vous partager.
Rien n’est jamais parfait
Si j’ai bien fait mon travail, je vous ai convaincu de faire du TDD pour réaliser vos logiciels rapidement sans bug. Comme la perfection n’existe pas, il est temps de parler des défauts de cette méthode.
Pas partout
L’implémentation et l’efficacité du TDD dépendent énormément du contexte. Prenons deux exemples :
- Embarqué : Si vous souhaitez l’implémenter pour ce genre de projet, vous risquez d’échouer. En effet, cette méthode de développement n’a pas été prévu pour ce genre de projet. Je ne dis pas que c’est impossible, mais c’est très difficile. Il va falloir trouver des solutions à des contraintes qui n’existent pas dans l’informatique de gestion.
- CRUD : si votre projet est un simple CRUD sans règle business, pourquoi faire du TDD ? Généralement, dans ce genre de projet, vous avez des simples mapper et des appels à une BDD à développer. Le faire en TDD n’est pas forcément utile.
Bienvenue en enfer
Si vous n’avez pas un ego surdimensionné ou si vous n’êtes pas victime du biais Effet Dunning-Kruger vous allez vous rendre compte que maîtriser le TDD va vous prendre beaucoup de temps et d’énergie. Vous allez commettre des erreurs qui risquent de vous décourager mais aussi d’amoindrir l’efficacité de cette méthode de développement. Vous allez devoir persister dans votre progression pour voir les bienfaits du TDD.
Après plusieurs années de pratique, je dois encore progresser pour avoir une meilleure maîtrise. Par exemple, je veux faire un projet uniquement en outside-in pour le maîtriser et me faire une meilleure idée sur cette méthode.
Si votre entreprise ne vous permet pas de le pratiquer, vous allez devoir le faire sur votre temps libre dans vos propres projets.
Mon conseil, soyez patients, pratiquez et petit à petit, vous allez voir vos progrès en devenant plus efficace.
Opposition
Une des principales difficultés que vous allez rencontrer va être de convaincre votre entourage professionnel d’utiliser cette méthode de développement. Vous allez vite vous rendre compte que vous allez avoir trois types d’opposants :
- Vos collègues plus juniors. Comme dit juste avant, faire du TDD efficacement nécessite du temps et de l’énergie. Pour une personne junior, l’effort à produire sera beaucoup plus important. Vous allez donc devoir les accompagner pendant leur apprentissage si vous voulez que le TDD soit bien utilisé. Ça va donc vous prendre encore plus temps et d’énergie. Ils peuvent aussi s’y opposer à cause des difficultés liées à l’apprentissage.
- Vos collègues pensant être « senior ». Dans notre profession assez masculine, vous avez beaucoup de développeurs qui ont un problème avec leur ego. Ils ont besoin de se sentir bon et se surestiment beaucoup. Comme ils pensent être les meilleurs, ils ont beaucoup de difficultés à se remettre en cause pour s’améliorer. Ils ne comprennent pas pourquoi il faut faire du TDD alors qu’ils codent déjà tellement bien. Comme l’apprentissage de cette méthodologie est compliquée, s’ils éprouvent de la difficulté, ils risquent de vouloir lâcher l’affaire, car ils penseront que le problème vient du TDD et non d’eux.
- Vos manageurs. Quand vous n’êtes pas un ingénieur en développement logiciel, comprendre l’intérêt du TDD peut être compliqué surtout si la personne qui vous l’explique n’est pas un pro de la communication. Certaines personnes ont la volonté de tout contrôler dans leurs équipes comme la façon dont travaille leurs développeurs. Comme ils auront du mal à saisir la puissance du TDD, ils vont s’y opposer, car selon eux, ça vous fera perdre du temps pour votre projet.
Si vous voulez que le TDD soit adopté dans votre équipe, vous allez devoir convaincre ces trois types de profils. Comme je ne suis pas un roi de la diplomatie, je ne peux pas vous conseiller sur la façon de le faire. Je peux juste vous dire que montrer l’exemple et la patience sont des bonnes méthodes pour convaincre vos adversaires.
Il est temps de conclure cet article assez long. J’espère que vous n’êtes pas perdu ou assommé après cette lecture assez intense. Je souhaite qu’il aide les personnes qui veulent se lancer ou s’améliorer dans le TDD. Le meilleur conseil que je pourrai répéter pour terminer est de pratiquer et d’échanger sur votre façon de faire. En pratiquant, vous allez vous améliorer et en échangeant vous allez apprendre de nouvelles façons de faire.
Prochainement, je vous parlerai de la mise en place de l’architecture hexagonale sur le back d’ElectionScenario.

