Les tests en général et le TDD en particulier ont tendance à bousculer un peu les développeurs au début. On n'en comprend pas vraiment la puissance avant de s'y être frotté pendant un petit moment. Résultat, cela laisse place à quelques objections que vous avez sûrement envie de formuler !
Ici, je me propose de répondre aux doutes que vous avez peut-être ressentis à la découverte des tests. Alors, allez-y shootez vos meilleures questions !
Un petit jeu de question-réponse
Les tests ralentissent le développement, car ça fait plus de code à rédiger.
Oui si vous n'allez travailler qu'une heure sur ce projet...
Ensuite, les tests vous font gagner beaucoup de temps. Vous allez diminuer drastiquement le temps passé à chercher les bugs d'une part. D'autre part, vous travaillerez toujours sur du code propre grâce à la refactorisation que l’on peut faire sans risque. Donc le code est plus facile à lire et comme vous le savez maintenant, la majorité du travail de développeur consiste à lire du code. Donc votre code étant plus facile à lire, le développement est plus rapide.
Oui mais refactoriser c’est retravailler, ce ne serait pas mieux d’avoir le code correct du premier coup ?
Prévenez-moi quand vous savez comment on fait ça. Mais je pense que ce n’est pas possible ! Rédiger du code est un processus créatif. Et comme tout processus créatif, on a jamais l'œuvre parfaite du premier coup. Un peintre fait des esquisses avant de se lancer dans son œuvre, un musicien répète ses musiques avant de les jouer parfaitement, un journaliste fait des brouillons avant de publier son article.
Le code est simplement soumis à la même règle, donc si vous souhaitez produire du code de qualité, vous devez refactoriser !
Les tests testent le code en production. Mais les tests sont aussi du code. Alors qui teste les tests ?
En voilà une bonne question ! Les tests et le code en production sont imbriqués étroitement. Et donc ce qui teste les tests, c'est le code en production.
C'est comme un château de cartes, certaines penchent vers la droite, c'est le code, d'autres vers la gauche, c'est le test. Chaque carte de test soutient une carte de code et inversement.
Je suis d'accord que les tests prouvent la présence de bugs quand ils sont rouges. Mais en revanche, une suite de tests toute verte ne prouve pas l'absence de bug.
En effet, mais ce n’est pas notre but et d’ailleurs ce n’est pas faisable. On ne fait que créer un parachute pour ne pas avoir peur de changer le code. Et comme avec un parachute, il peut y avoir des accidents. Mais si cela permet d’avoir 99 % de chances de ne pas en avoir, ça vaut le coup d’en avoir un sur le dos, non ?
Le TDD incite les gens à suivent des règles, mais pas à réfléchir.
Le TDD, c’est une discipline. La discipline permet dans le feu de l’action de gagner du temps en éliminant le besoin de prendre certaines décisions. Pour autant, il faut toujours prendre du recul pour analyser ce que l’on est en train de faire, si le code est efficace et clair et parfois même il faut savoir remettre en question la discipline. Donc oui, le TDD vous permet d’éviter de réfléchir pour vous concentrer sur ce qui importe : l'architecture de votre code.
Si on doit travailler avec un gros paquet de code qui n’est pas testé, comment fait-on ?
Bonne question ! Le problème, c’est que pour tester, il faut que le code soit bien organisé, découplé et testable. Et si ce n’est pas le cas, il faut refactoriser. Mais sans tests, on ne sait pas si notre refactorisation ne va pas casser quelque chose. Donc pour tester, il faut refactoriser et pour refactoriser, il faut des tests. Quelle est la solution de ce problème ?
Il faut trouver une partie du code que l’on peut tester sans changer trop de choses. Ensuite, on utilise ces tests comme garants pour commencer une refactorisation qui va nous permettre de créer de nouveaux tests, et en suivant cette logique, on peut étendre la couverture de tests à toute la base de code. Idéalement, il faudrait commencer à tester au moment de rajouter une nouvelle fonctionnalité, comme ça on est sûr de ne rien casser et au fur et à mesure, on étend les tests.
On ne peut pas tester l’interface utilisateur !
En effet, il est difficile de tester l’interface utilisateur. Par exemple, on ne peut pas facilement tester qu’un bouton soit rouge ou vert. En revanche, on peut tester que le booléen qui décide de la couleur du bouton a la bonne valeur.
Pour cela, il faut séparer la logique de l’affichage de l’affichage en lui-même. Dans notre exemple, la logique qui donne la valeur au booléen ne doit pas avoir lieu dans la même classe que celle qui donne la couleur au bouton. En MVC, tout se fait dans le contrôleur donc on est coincé, mais je vous invite à aller jeter un œil à d’autres architectures comme le MVVM, VIPER ou Clean.
Mais tester, c’est difficile ! On est des programmeurs, pas des testeurs.
Vous êtes avant tout des programmeurs professionnels et si vous ne faites pas de tests, c’est que vous ne l’êtes pas. C’est un parti pris fort alors laissez-moi vous expliquer en détail les raisons qui le motive.
Un logiciel est un système extrêmement sensible. Je peux modifier une ligne de code au bon endroit et causer le crash de toute l'application. Il existe très peu de systèmes aussi sensibles. Si j'enlève un clou dans une maison, elle ne va pas s'effondrer. Si je tue une de vos cellules, vous n'allez pas mourir.
Il existe pourtant un système aussi sensible : la comptabilité. Une erreur de comptabilité peut causer la ruine d'une entreprise et mettre ses dirigeants en prison. Seulement cette science est bien plus âgée que l'informatique et donc elle a eu le temps de résoudre son problème d'hyper sensibilité.
Il y a 700 ans a été inventée la comptabilité à double entrée. En comptabilité à double entrée, tout est entré deux fois, du côté de l'actif et du côté du passif. L'actif et le passif suivent des logiques mathématiques très différentes. Mais à la fin, les deux valeurs du passif et de l'actif doivent être égales. Si elles ne le sont pas, il y a une erreur. Ce système permet donc de détecter les erreurs extrêmement rapidement avec une très grande certitude.
En programmation, ce sont les tests et le code qui forment une double entrée. Les deux ensemblent permettent de détecter très rapidement les erreurs et d'assurer la solidité globale du système.
Aucun comptable ne se passe de la double entrée. Est-ce que les programmeurs doivent être moins professionnels que les comptables ? Est-ce que leurs erreurs ont moins d’impacts sur l’entreprise ? Je pense que la réponse est non dans les deux cas.
Qui plus est, les comptables rentrent les données du côté de l’actif et du passif en même temps. C’est exactement ce que nous faisons en TDD.
En résumé
Quand vous partagez votre code avec votre client ou votre boss, vous devez être sûrs de vous. Imaginez un cuisinier qui envoie son plat sans être sûr de l’avoir assaisonné correctement. Ce ne serait pas professionnel. Si le client trouve un bug, c’est que vous avez fait une erreur. Ça peut arriver mais ça doit être rare et l’occasion pour vous de remettre en question une partie de vos pratiques.