Introduction à TDD et BDD

De Wiki Agile du @GroupeCESI
Aller à : navigation, rechercher

Auteur : Cucumber
Source : Introduction to TDD and BDD


Traducteur : Fabrice Aimetti
Date : 26/02/2019


Traduction :

Cukeup-seb.jpg

Cet article comporte quatre sous-sections.

  • TDD
  • BDD
  • Différences
  • xDD

Nous allons commencer par une introduction au TDD. Je vais vous en parler assez rapidement, car je suppose que la plupart d'entre vous qui lisez ces lignes en font déjà. Ensuite, je passerai un peu plus de temps sur le BDD, puis j'aborderai ce qui les différencie, avant de devenir un peu plus philosophe avec xDD.

Qu'est-ce que TDD ?

Write-failing-test.png

C'est le cycle TDD classique, popularisé dans le livre de Nat Pryce et Steve Freeman : Growing Object-Oriented Software, Guided by Tests. On le décrit généralement comme l'action de "écrire un test qui échoue" puis faire passer le test avec succès et ensuite refactorer le code ; et vous continuez à tourner dans cette boucle. C'est le cycle du TDD, c'est très simple. Il y a trois énoncés simples ; il y a des flèches colorées entre eux. Mais à l'intérieur de ce schéma, il y a beaucoup de complexité ou du moins beaucoup de subtilités.

Tdd-bullet-points.png

Voici une autre façon de le représenter et d'y réfléchir. Bien que "écrire un test qui échoue" soit correct en tant que procédure, cela reste assez déroutant parce que ce n'est pas ce que vous essayez de faire ; l'idée n'est pas de faire un test qui échoue. Ce que vous essayez de faire, c'est d'imaginer la prochaine étape que vous voulez faire, c'est de faire évoluer l'implémentation de façon nécessaire et suffisante pour créer de la valeur. On le reformule souvent comme "écrire la spécification suivante". En gros, votre prochain test est votre prochaine spécification sur la façon dont le logiciel devrait se comporter... et parce que vous ne l'avez pas encore fait, le logiciel va échouer... mais vous n'êtes pas là pour écrire un test qui échoue.

La seconde étape est de faire rapidement passer le test avec succès. L'intention n'est pas de tout concevoir parfaitement ; c'est de faire passer le test avec succès. L'ensemble de vos tests passe de l'échec à la réussite totale, et maintenant que tous vos tests sont réussis, il est possible de refactorer le code en toute sécurité. L'intention ici n'est pas d'obtenir la meilleure conception ; c'est de les passer au vert rapidement, et maintenant qu'ils sont tous au vert, vous pouvez les regarder et vous demander "comment puis-je améliorer cette conception ?", et vous pouvez améliorer la conception en toute sécurité grâce au refactoring.

La troisième chose, c'est le refactoring. La boucle de refactoring dans le livre de Nat et Steve est en fait un cycle. Vous pouvez le dessiner de bien d'autres façons, mais l'idée est que vous ne vous contentez pas de vous lancer et refactorer pour dire que vous avez terminé ; vous vous lancez, vous regardez et voyez ce que vous aimeriez changer et vous le changer. Vous vous assurez que le test est encore vert, et vous regardez le code à nouveau et vous vous demandez "Y a-t-il un autre changement que je veux faire ?" ou "est-ce que ce refactoring a introduit une autre chose que je souhaite faire ?". Il s'agit d'un multi-processus en soi ; il ne s'agit pas d'une seule étape.

Ce sont les trois phases du TDD.

Une chose sur laquelle il faut s'attarder très brièvement est le mot "refactoring" parce que lorsque je parle à des développeurs, "refactoring" est souvent mal compris. Lorsque vous refactorez, vous ne changez pas le comportement du code. Vous ne refactorez jamais pour ajouter une nouvelle fonctionnalité. Vous pouvez refactorez pour mettre le code source dans un état où vous voulez qu'il soit afin que vous puissiez ajouter une nouvelle fonctionnalité mais :

Le refactoring, par définition, ne modifie pas le comportement du code observable de l'extérieur.


Qu'est-ce que le BDD ?

Comme je l'ai expliqué assez rapidement, le TDD est bien limité, circonscrit, confiné. Le BDD, cependant, ne l'est pas ; c'est un peu bizarre. Personne ne sait exactement ce que cela signifie. Matt Wynne, qui travaille avec moi chez Cucumber Limited et qui travaille en BDD depuis un certain temps, a essayé d'en distiller les principes. C'est lui qui a trouvé cette phrase :

Les praticiens du BDD explorent, découvrent, définissent, puis éliminent le comportement souhaité des logiciels à l'aide de conversations, d'exemples concrets et de tests automatisés.


Il y a beaucoup de mots sur cette page et en fait, si vous louchez un peu, tout devient flou. Il y a des choses intéressantes ici, mais pour être bref, le BDD est une approche à 3 niveaux.

Le premier niveau est d'amener les développeurs, les testeurs et les gens du métier à se parler entre eux. C'est l'origine du BDD. Tous ceux qui pensent "nous faisons du BDD parce que nous utilisons "Given", "When", "Then" n'ont (souvent) pas compris. "Given", "When", "Then" n'a rien à voir avec BDD. BDD signifie Behaviour-Driven Development (développement piloté par le comportement) et l'intention réelle est d'essayer de déterminer ce que votre client ou votre métier/entreprise attend du logiciel avant de commencer à travailler sur celui-ci. La première façon d'y parvenir est de réellement collaborer avec ces personnes.

Le deuxième niveau, une fois que nous avons obtenu cette collaboration, c'est de la documenter d'une façon qui soit significative pour tous ceux qui l'examinent, qui pourraient y jeter un coup d'oeil plus tard et qui voudraient peut-être y apporter des commentaires. Généralement, cela se fait en utilisant un langage universel. Les gens utilisent souvent les mots "Given" (étant donné), "When" (lorsque), "Then" (alors), mais ce n'est pas nécessaire. L'idée est que nous avons collaboré et qu'il s'agit d'une compréhension partagée. Cela nous a permis de nous assurer qu'il y a un objectif de collaboration que nous essayons d'atteindre, et une fois que nous avons réussi à collaborer, cela vaut la peine d'essayer de le documenter de telle façon que personne n'ait besoin d'être dans la salle au même moment, pour que l'apprentissage partagé puisse être diffusé. Enfin, si cela convient à nos équipes et à nos projets, nous automatisons nos tests pour piloter le comportement.

Nous collaborons, nous documentons cette collaboration sous une forme de spécification, puis nous automatisons cette spécification pour piloter l'implémentation.


Cucumber n'est pas BDD

Matt et moi travaillons tous les deux pour Cucumber Ltd mais dans sa description il n'y a aucune mention de Cucumber où que ce soit. Cucumber ne fait pas partie du BDD. Cucumber est quelque chose qui a été créé pour aider les gens à automatiser d'une manière spécifique. Si je reviens au livre de Nat et Steve, ils utilisent JUnit tout au long de leur livre pour automatiser les tests d'acceptation. Cela dépend entièrement de votre organisation, de la façon dont vous voulez pratiquer le BDD.

La manière classique, en utilisant Cucumber et SpecFlow et tout autre outil qui utilise une syntaxe semi-structurée appelée Gherkin, c'est de documenter et de définir ces spécifications. Vous finirez par avoir ce qu'on appelle des fichiers feature.

Feature-file.png

Les fichiers feature sont simplement des fichiers texte. Ils ont une semi-structure, il y a une syntaxe, et les mots-clés sont en bleu. L'intention est que n'importe qui de votre domaine devrait être capable de lire vos fichiers feature et de comprendre exactement quelle est l'intention du système.

Ci-dessus vous avez un exemple de fichier feature. Il y a un nom en haut qui indique la feature, un texte qui indique le comportement ou les critères d'acceptation, et en dessous, un certain nombre de scénarios qui montrent comment le système se comporte dans certaines situations. L'important ici, c'est que les exemples que vous pourriez donner lorsque vous collaborez soient documentés sous la forme de scénarios. Les critères d'acceptation, qui sont les règles, la manière dont le système doit se comporter, sont saisis dans le texte en haut et l'important ici est que les user stories, sur lesquelles beaucoup d'équipes Agiles s'accrochent, ne sont que des choses jetables une fois implémentées et elles devraient être mises à la poubelle.

TDD et BDD : différences et oppositions

Passons aux différence. Nous avons expliqué TDD et BDD. Les gens disent souvent : "Mais alors, quelle est la différence entre eux ?"

Les gens continuent encore en demandant : "J'ai aussi entendu parler du Test-Driven Development (ATDD : Développement piloté par les tests d'acceptation). Qu'est-ce que c'est ? Quand dois-je l'utiliser ? Est-ce que c'est différent ?". La réalité est que vous pouvez trouver des sites Web qui vous diront quand utiliser quoi et dans quel environnement. On a posé la question suivante à Liz Keogh, qui travaille avec Dan North qui a inventé le terme BDD : "quelle est la différence entre toutes ces choses ?"

Sa réponse est : ce sont des noms différents pour les mêmes choses.


Il n'y a pas de différence fondamentale entre eux. Ce qui les unit, c'est qu'ils ont tous besoin qu'un groupe de personnes précise comment le logiciel doit se comporter, en collaborant avant son implémentation. C'est ce qui est important, alors c'est peut-être à cela que nous devrions réduire la définition du BDD. L'idée est de travailler à partir d'une vue extérieure, en réfléchissant à la façon dont nous voulons avancer, nous utilisons des exemples pour nous assurer que tous les membres de l'équipe comprennent ce sur quoi nous venons de nous entendre, des exemples concrets avec des données concrètes, et nous écrivons ces exemples dans un langage universel : un langage utilisant des termes dérivés du domaine métier qui sont compris, sans ambiguïté, par tout le monde dans l'équipe.

Concevez vos tests - xDD

La sujet "xDD". De quoi s'agit-il ? La raison pour laquelle on appelle cela "Test-Driven" ou "Behaviour-Driven" ou "Acceptance Test-Driven" est que vous devez spécifier le comportement avant de mener l'implémentation. Il n'y a pas de "nous faisons une sorte de Behaviour-Driven", " nous faisons une sorte de Test-Driven", "nous écrivons les tests dans le sprint". Vous devez d'abord les écrire. C'est de cette façon que les tests pilotent, c'est comme cela que ça devient un processus de conception. C'est la spécification qui échoue, c'est le fait de la voir échouer, qui vous pousse à mener l'implémentation. C'est ce qui pousse le développeur ; c'est ce qu'il utilise pour écrire le code.

Le second D est assez souvent utilisé pour "design" (conception). Je sais que ce n'est pas pour le "design", c'est pour le "développement", mais en fait nous concevons du code. Lorsque nous codons l'automatisation, nous devons penser à la façon dont elle va être utilisée, comment nous allons appeler cette méthode, comment nous allons déclencher ce comportement. En écrivant votre code en réponse à vos tests et en réfléchissant, vous assurez la testabilité, vous obtenez un code qui est testable, un code que vous comprenez. Vous bénéficiez d'un grand nombre d'avantages bien au-delà de la couverture de test.

Il ne s'agit pas de couverture de tests.

Finalement, vous obtenez un refactoring grâce au BDD et au TDD, et vous le faites jusqu'à ce que vous vous sentiez bien. Les gens se disent : "Eh bien, ce serait bien si nous savions quand nous devons refactorer". Faire un logiciel, ce n'est pas "mettre les spécifications en haut, tourner une manivelle et attendre que la bonne solution sorte".

C'est une activité créative et même si je suis sûr que vous détestez qu'on vous prenne pour un créatif, vous êtes un créatif. Vous devez en avoir l'intuition.

Conclusion

BDD, TDD, ATDD, Spécifications par l'Exemple, ... ce sont tous les mêmes. Ils travaillent d'un point de vue extérieur pour aller vers l'intérieur, ils utilisent des exemples pour spécifier comment le système doit se comporter, ces exemples sont ensuite exprimés dans un langage universel que toute l'équipe comprend, y compris les membres non techniques, et ensuite, une fois que vous l'avez automatisé, vous pouvez vérifier, ce qui signifie que vous pouvez savoir quand votre documentation est à jour, cela signifie que vous pouvez voir quand une régression s'est introduite, ce qui signifie que vous voyez le périmètre du système qui a été jusque-là implémenté par l'équipe de développement.

Toutes ces choses vont dans le bon sens.

Mais la question pertinente au moment de décider de la mise en oeuvre d'un test est la suivante : Qui est intéressé par la lecture de ces tests ?

Si vous voulez obtenir des feedbacks de votre métier/entreprise au sujet de quelque chose, si c'est un comportement qui est vraiment important pour votre produit et que votre métier/entreprise va dire "non, ça ne devrait pas fonctionner comme ça", "oui, ça devrait fonctionner comme ça", pensez vraiment à écrire ces tests d'une façon qui leur permette de lire ces tests et de dire "c'est ce que nous voulons". Cucumber, SpecFlow, les outils qui utilisent Gherkin vous permettent de le faire directement dans un langage universel. Cependant, vous n'avez toujours pas besoin de les utiliser, vous pouvez écrire de longues phrases au sein du cadre technique sur lequel vous travaillez et qui pourrait générer cette documentation lisible que vous pouvez partager avec votre métier/entreprise. Vous pouvez le faire dans JUnit, vous pouvez le faire dans CPP Lite, vous pouvez le faire dans n'importe lequel de ces outils ; ce n'est pas un problème.

Ce que vous devez faire, c'est vous assurer que cela s'exprime d'une manière qui vous permette d'obtenir les feedbacks des personnes intéressées, les gens qui ont un enjeu.

Ceci est une retranscription revue et corrigée de la récente présentation de Seb Rose à la conférence de l'ACCU. Vous pouvez visionner la conférence de 15 minutes ici.