Le TDD, une méthodologie controversée

La question peut paraître étonnante, déconcertante voir incompréhensible pour ceux dont TDD rime avec Agilité. Pourtant, si l’Agilité n’est rien de plus qu’un terme décrivant le fait d’adapter les outils et méthodologies aux besoins d’un projet ; le principe de Test Drivent Development est justement l’une de ces notions parfois « survendues » comme étant Agile. 

Vraiment ? Cet article va servir à mettre en exergue les différents aspects du TDD et de déterminer, via des retours d’expériences de nos consultants, si cette méthodologie est essentielle à la réussite d’un projet dit Agile ou si elle n’apporte finalement qu’un confort, une caution technique auprès des porteurs de projet. 

Bon à savoir : le TDD est aussi régulièrement identifiable sous le nom de cycle Red-Green-Refactor.

Introduction au TDD

Nous avons demandé à plusieurs de nos consultants de définir ce qu’est véritablement le TDD, et les réponses sont diverses et variées comme vous allez pouvoir en juger. Si une majorité définit le TDD comme étant une « méthodologie de travail qui garantit des logiciels de qualité et qui répondent parfaitement aux besoins initiaux« , une minorité intéressante (3 interrogés sur 8) distingue le TDD comme étant un « gros buzz word. C’est un peu sur-vendu comme étant une méthode Agile« . 

Si les termes sont forts, le fond de pensée de nos consultants est finalement plutôt clair lorsqu’ils s’attardent sur le constat que, « finalement, le TDD suit la logique de l’Agile, ce sont beaucoup de mots pour définir une simple logique. Le Craft doit venir tout seul, c’est tout simplement du bon sens. Cela fait partie des principes à suivre pour limiter ta réflexion sur tes problématiques. C’est une aide logistique, rien de plus. »

Dans la même optique d’association du TDD à l’Agile, l’un de consultants, François, tient à rappeler que l’agilité – comme son nom l’indique – consiste essentiellement à adapter les différentes technologies, outils, méthodologies et parties du projet afin que celui-ci avance rapidement, qu’il produise un code maintenable et que les développeurs se sentent investis. Par la même occasion, il considère qu’à « force de faire trop de tests unitaires sur les petits composants, cela augmente les risques de perte de temps puis que, si refactoring il doit y avoir, il faudra alors refaire l’ensemble des tests.« 

Principe et démonstration

Le principe du TDD est simple, basique. Cette méthodologie permet de simplifier le code source d’un projet en développement au maximum. La pratique est simplissime, les tests unitaires doivent être rédigés avant le code et basés sur l’ensemble des éléments de la fonctionnalité implémentée. Attention tout de même, le TDD doit être obligatoirement et automatiquement associé au langage de programmation usité. D’ailleurs, bien que rarement explicité par les chefs de projet, le TDD est régulé par trois lois principales, à savoir :

Loi n°1 : « Vous ne pouvez pas écrire un code de production tant que vous n’avez pas écrit un test unitaire qui échoue »‘ »

Loi n°2 : « Vous ne pouvez pas écrire plus d’un test unitaire que nécessaire pour échouer, et ne pas compiler revient à échouer. »

Loi n°3 : « Vous ne pouvez pas écrire plus de code de production que nécessaire pour que le test actuellement en échec réussisse. »

Pour les néophytes du TDD, il est aisément possible de métaphoriser son principes avec des images de la vie quotidienne. Le TDD permet de valider en amont l’ensemble des features qui permettront ensuite à ton code d’être maintenable et scalable. Ainsi, la comparaison avec un échafaudage qui te permet d’avancer étage par étage dans la construction d’une maison est l’exemple parfait. Sinon, tu peux considérer le TDD comme étant un guide. Si tu en respectes les codes, le TDD te permet – tout comme une gouttière au bowling – de suivre un chemin tout tracé vers un code maintenable, propre et pour lequel les échecs seront quasi-inexistants (bugs). 

Enfin, imagine une vision finale de ton code si ce dernier a été réalisé sans les tests. La comparaison correspondante peut être un château de cartes, si tu ne penses pas à y mettre de la colle, il finira par s’écrouler à cause de son instabilité. Il en est de même pour ton code si tu ne souhaites pas que celui-ci devienne rapidemment un code legacy.

TDD, simple méthodologie de test ou levier obligatoire face au code legacy ?

Face au code legacy, le TDD est une technique que beaucoup considèrent comme essentielle. Cependant, il est nécessaire de bien comprendre qu’il est presque impossible de faire du TDD sur un code legacy qui possède de trop nombreuses fonctionnalités. Il faut alors prioriser les fonctionnalités à modifier et surtout vérifier quelles autres features sont touchées lors d’un changement de processus technique. Les tests sont là pour ça mais le TDD n’est réellement utile que lorsqu’il est utilisé à partir du début du projet et jusqu’à la dernière ligne de code.

Si l’organisation autour du TDD possède des défauts pour beaucoup de Product Owner, c’est notamment en raison de son coût temporel et technique. En effet, il est nécessaire pour tous les développeurs souhaitant utiliser le TDD de passer du temps sur l’intégration des tests avant de lancer une feature. Bien que chronophage et coûteux, le TDD va avoir un effet non négligeable sur la maintenabilité d’un code et être LA solution à adopter pour une vision à long terme.

A cette vision à long terme se joint la notion de scalabilité du projet et surtout – car l’humain est toujours la pierre angulaire d’un projet –  de cohésion d’équipe. Un code propre et compréhensible par tous permet toujours d’aider l’équipe à avancer plus vite, ensemble et dans la même direction autour d’un projet que chacun peut déterminer comme viable. Il est, de manière officieuse, communément admis qu’à court et moyen terme, l’implémentation du TDD prend jusqu’à 29% du temps quotidien de l’équipe de développeurs. Si le chiffre paraît conséquent, il est à mettre en comparaison avec le temps passé à débuger le projet par la suite. On estime ainsi que le TDD va finalement permettre de diminuer le temps passé au débogage de 30 à 40h par bug.

Techniquement, un projet qui se maintient et progresse de façon quotidienne reste plus challengeant qu’un code legacy ou un projet entièrement en Cycle en V sans respect d’aucune des meilleures pratiques de développement. Logique ? Agile dirons-nous.

Tandis que la notion de Test First (souvent confondue avec le TDD) indique la présence de tests en amont d’une implémentation de feature, le principe du TDD regroupe plusieurs autres aspects comme le design. La méthodologie d’implémentation étant différente, la conception en amont est encore plus précise et permet alors un design de code plus lisible par toutes les équipes et plus maintenable pour les prochains développeurs qui auront à travailler sur ce projet.

Cependant, un projet peut tout à fait fonctionner sans TDD, si tant est que la réussite n’est pas forcément associée à la qualité du code. Autre raison qui laisse à penser que le TDD peut parfois être un simple adjuvant aux autres tests nous vient d’un consultant qui se fie à l’une de ses expériences personnelles : « Etant ingénieur, je travaille sous le lead du pôle business. Mon Product Owner nous a lui-même fourni un jeu de tests. L’avantage de ce jeu de tests est qu’il nous permet de savoir où on se dirige et donc de transformer le TDD en simple confort.« 

Lors de l’observation d’un code legacy, et avant implémentation des nouveaux, il est nécessaire de penser à fracturer ce code en micro-services afin de rendre chacune des fonctionnalités plus qualitative grâce à l’approche TDD. On peut donc dire que, dans un projet legacy, il est essentiel de viser à intégrer le TDD.

Le TDD est-il utile lorsqu’il est le seul outil utilisé ?

De la même façon que les tests unitaires doivent s’adapter à la taille du projet, le TDD doit lui aussi s’adapter à son environnement. En partant de ce postulat, il est nécessaire de connaître les cousins du TDD : ATDD, BDD, DDD. Retrouvez nos articles sur ces principes ici, ici et là.

Il est intéressant de mettre en valeur l’approche TDD grâce aux tests end-to-end et ainsi vérifier la scalabilité et la maintenabilité de toutes les features implémentées. Bien d’autres outils et méthodologies peuvent venir compléter l’approche TDD et son apport sur un projet. Dans une liste non -exhaustive, on peut citer : le BDD, le Pair Programming, les sessions de Clean Code comprenant des reviews communes avec l’apposition d’une nomenclature de code pour les méthodologies ; frameworks de tests unitaires, libraires d’assertion, Nfluent Substitute ou SonarQube pour les outils techniques et DevOps pour les outils se référant à la qualité.

Attention, lorsqu’on parle de framework, il est important de rappeler que n’importe quel framework de tests peut s’appliquer au TDD à partir du moment où cela permet les assertions. Le TDD a cet avantage d’apporter la notion d’humain puisque tout tourne finalement autour de l’organisation et de la logistique du code.

Le TDD et ses risques

S’il est plutôt commun de constater les améliorations intra-équipe grâce à l’ajout de la méthode TDD, plusieurs de nos consultants nous ont fait remonter que la hiérarchier pouvait poser problème quant à l’implémentation de cette méthodologie dans le processus. Comment ? Tout simplement à cause d’une mauvaise communication ou d’une pression négative de la branche marketing ou du Product Owner. Il en résultera donc des problèmes d’accompagnement et de suivi, ce qui limitera la vigilance sur les cas les plus complexes. Il est nécessaire, dans ce cas précis, de se prémunir en faisant en sorte que les chefs de projet comprennent l’importance de ces tests et donnent ensuite l’envie développeurs de « perdre » du temps à leur implémentation. Pour cela, il suffit de valoriser l’apprentissage progressif. Une incompréhension ou un manque de communication risque de mener les projets à leur perte puisqu’elles augmenteront les abandons, l’usure mentale des développeurs et altérera finalement le code lui-même.

D’autres freins existent.

Freins techniques : le code legacy sur une fonction trop énorme est impossible, trop longue et inutile. Chronophage. Si ce n’est pas fait, mettre en place le test end-to-end qui permet de tester front et back.

Freins humains :  Volonté, usure, manque de suivi, manque de considération.

Introduction à l’ATDD

Bien que comprenant le sigle TDD, l’ATDD se rapproche plus de l’approche BDD. Et pourtant. L’ATDD (Acceptance Test-Driven Development) sert tout simplement (comme le TDD) à tracer la route à l’implémentation d’une fonctionnalité par les tests d’acceptations/fonctionnels. Il est, comme ses lointains cousins, représentable par un cycle en 7 étapes : 

  1. Appréhender l’User Story 
  2. Rédiger le test fonctionnel 
  3. Tester sur une feature non codée 
  4. Ecrire la fonctionnalité que vous souhaitez tester 
  5. Relancer le test sur la feature 
  6. Lorsque ça fonctionne, terminer d’écrire la feature comme vous la souhaitez 
  7. Vérifier que l’ensemble fonctionne avec le test en utilisant donc le principe de non-regression