Il y a dix ans, je développais des applications sans tests automatisés.

J'écrivais un bout de code, et je testais le résultat à l'aide de mon navigateur, de mon clavier et de ma souris, en cliquant sur des boutons ou des liens et en remplissant des formulaires, afin de voir si j'obtenais le comportement attendu.

Une fois ma tâche terminée, je testais d'autres parties de l'application que celle directement concernée par le code que je venais d'écrire pour vérifier que je n'avais pas créé de régressions.

Sauf que j'étais loin de tester la totalité de l'application, car ce processus était ennuyeux et laborieux, et en conséquence, malgré un développement déjà très normé et industrialisé à l'époque, les régressions étaient nombreuses.

De plus, je passerais sur les bugs que je pouvais laisser passer, notamment lorsque mon code était confronté, en production, a des situations que je n'avais pas prévu.

Maintenant, je travaille d'une tout autre manière.

Je commence par écrire mon test, qui place le code que je vais ensuite écrire dans l'une des situations dans laquelle il sera exécuté en production.

Je lance ensuite mon test en tapant sur une touche de mon clavier, sans quitter mon éditeur, et je rédige ensuite le code qui permet au test de passer au vert, suivant l'expression consacré, et cela uniquement s'il était au rouge, toujours suivant l'expression consacré.

Et, pour passer au vert, j'écris juste la quantité de code nécessaire et suffisante permettant à mon code de passer le test, et de plus très facilement, car bien souvent, l'algorithme a implémenter est en filigrane dans le test.

De plus, à tout moment, je suis capable de détecter les régressions que j'aurais pu éventuellement introduire, toujours en appuyant sur une seule touche de mon clavier et sans quitter mon éditeur.

Aujourd'hui, je code donc plus rapidement, puisque je n'ai pas besoin de basculer en permanence de mon éditeur à mon navigateur, je suis plus productif car le test guide mon développement, et mon code est plus fiable.

Dans ces conditions, je m'interroge donc sur la nature du facteur qui ferait que je couterais plus cher aujourd'hui qu'il y a 10 ans, indépendamment évidemment de l'inflation économique et de l'expérience que j'ai acquise.

J'ajouterais que les méthodes agiles sont plébiscitées actuellement car elles permettent, et c'est démontré, de mieux respecter à la fois les délais et les budgets.

Or, ces méthodes préconisent toutes l'utilisation de tests automatisés lors du développement.

Je ne peux donc m'empêcher de penser que l'écriture de tests a, au minimum, un coût nul, à la fois en terme de temps et d'argent, dans le développement d'un projet.

Car s'ils est indéniable que les tests prennent du temps à écrire, en contrepartie, ils sécurisent le développement, ce qui permet au développeur de se concentrer exclusivement sur la production d'un code fiable et de qualité.

De plus, si d'aventure un bug survient, les tests facilitent sa résolution en facilitant sa reproduction et donc sa localisation, et de plus, ils permettent de s'assurer que la correction n'a pas engendré un autre problème.

Le coût financier qui semble donc à première vue induit par l'écriture des tests est donc largement compensé par les avantages, le confort, pour reprendre le terme d'Amaury, qu'ils apportent au développeur.

Faut-il pour autant tout tester ?

De mon point de vue, les tests ne servent pas uniquement à détecter les régressions et à aider au développement, ils sont également un indicateur de qualité.

Or, qu'est-il possible de déduire, en terme qualitatif, d'un code couvert, par exemple, à 50% par des tests ?

La réponse est absolument rien !.

Le code couvert par les tests sera certainement de bonne qualité, mais le développeur n'a aucun indicateur lui permettant de jauger la qualité du code non couvert.

Si cela se trouve, ce code non testé est un nid de bugs qui fera tomber l'application lors de la mise en production... ou pas !

Bien souvent, dans ce genre de situation, la justification donnée à l'absence de tests est que le code est simple et évident, et qu'en conséquence, il n'est pas utile de le tester, puisque les bugs, s'il y en avait, seraient immédiatement visibles.

C'est oublier trop rapidement que ce qui peut sembler simple à un développeur ne l'est pas forcément pour un autre développeur et que surtout, l'erreur est humaine.

Je ne compte plus les erreurs induites par une faute de frappe que les tests unitaires ont détecté pour moi dans mon code, et cela même dans des méthodes ou des fonctions composées d'une seule ligne.

Je ne parlerais pas non plus des erreurs provoquées par l'utilisation d'un < à la place d'un ≤, ou d'autres joyeusetés de ce genre.

De plus, c'est également oublier un peu vite que le code d'une application évolue en permanence, et que ce qui semble simple et trivial aujourd'hui ne le sera peut être plus demain, car le besoin aura évolué, et que ce qui était non critique hier doit être extrêmement fiable aujourd'hui.

C'est donc la raison pour laquelle je dis, en bon extrémiste, qu'un maximum de tests doivent être écrit, car c'est le seul moyen d'avoir une indication de la qualité du code tout en pouvant le faire évoluer dans les meilleurs conditions, et cela même si, effectivement, comme le souligne Amaury, les tests ne sont que de la poudre aux yeux, car ils peuvent laisser passer des bugs.

En effet, le fait que les tests ne soient pas une réponse parfaite au problème des bugs n'est pas une justification valable pour ne pas tester tout ce qui peut l'être, bien au contraire.

Je vais faire une analogie qui pourra sembler osée, mais, tout comme les tests ne sont pas une arme absolue contre les bugs, le préservatif n'est pas une arme absolue contre les MST.

Tout comme les tests peuvent laisser passer des bugs, le préservatif peut se rompre et ainsi permettre l'infection de son porteur.

Pour autant, faut-il ne pas l'utiliser, faut-il renoncer à en promouvoir l'utilisation, ou bien, encore plus stupide, n'utiliser que la moitié d'une capote pour faire des économies ?

Jusqu'à preuve du contraire, tout comme le préservatif est la meilleure arme dont nous disposons actuellement contre les MST, les tests automatisés sont le meilleur outil dont nous disposons pour lutter contre les bugs, et il est donc tout simplement stupide de s'en passer sous prétexte que leur efficacité est relative et non absolue.

De plus, comme nous l'avons vu, les tests apportent un confort réel.

Si Amaury semble reconnaître plus ou moins ce fait, il circonscrit ce confort au seul développeur.

Sauf que dans les faits, ce confort s'étend sur toute la chaîne de production, car chaque maillon sait qu'il peut compter sur la qualité du travail des autres.

Le développeur a confiance dans son code, et les autres membres de son équipe de développement savent qu'ils peuvent avoir confiance en son code.

Le responsable du développement a également confiance, car il dispose d'un indicateur de qualité raisonnablement fiable, mis à jour régulièrement et qu'il peut consulter à tout moment.

Le client dispose quand à lui d'un logiciel fiable, avec peu de bugs, et lorsqu'il y en a, ils sont corrigés définitivement et ne réapparaissent pas.

De part la maîtrise du code et du processus de production qu'ils permettent, les tests automatisés sont donc un vecteur de confiance global à la chaîne de production, et non local au développeur.

Enfin, Amaury dit que la politique du test intégral est une politique de fainéant, car elle évite de réfléchir et simple et facile à mettre en œuvre...

Bullshit !

L'écriture de tests unitaires est tout sauf facile pour un développeur, que ce soit au niveau psychologique ou intellectuel, car il demande de la discipline, du courage et une bonne dose de réflexion.

Il lui faut en effet de la discipline et du courage pour réussir à se mettre de manière récurrente en situation d'échec, pour accepter de se mettre en difficulté en écrivant un test qui lui fera réécrire tout ce qu'il a fait précédemment, ou pour coder un test qui lui montrera concrètement qu'il n'a pas fait correctement son travail.

Il lui faut de plus faire travailler ses méninges pour écrire un test qui a du sens, pour répondre aux questions, et elles peuvent être nombreuses, posées par un test, pour arriver à créer l'environnement d'exécution correspondant, ou tout simplement pour trouver ce qu'il faut tester.

Le développeur qui écrit des tests et qui veut le faire correctement est donc bien loin d'être le fainéant qui pense que les tests lui permettront de masquer sa bêtise décrit par Amaury.

C'est au contraire un technicien organisé et très compétent, qui a le soucis du travail bien fait et qui n'hésite jamais à se remettre en cause, à se poser des questions, à exercer son esprit critique, à affronter la réalité et les problématiques très réelles rencontrées lors du développement d'un logiciel.

L'écriture d'un test unitaire de qualité est à mon sens l'exercice le plus difficile qui soit pour un développeur, surtout lorsqu'il est pratiqué quotidiennement, et il ferait d'ailleurs un excellent test pour un entretien d'embauche, car il demande une somme de connaissances et de qualité intellectuelle et mentale que devrait posséder tout bon programmeur.

Supposons maintenant que tout ce qui précède est un tissus de bêtises, car après tout, tout comme Amaury, je n'ai aucune preuve scientifique ou budgétaire de ce que j'avance.

Si produire du code de qualité, c'est à dire exempt de bugs et qui répond aux besoins du client, coûte effectivement plus cher que de faire du code de merde, ne faudrait-il pas, au lieu de ne pas mettre en œuvre les bonnes pratiques qui permettent de faire du bon travail pour des raisons budgétaires, faire comprendre au client que la qualité a un coût, et qu'il a, au final, tout à gagner à mettre la main au porte-monnaie ?

Ou bien faut-il faire de la merde, dépasser les budgets, risquer le procès, mécontenter le client, ternir son image, j'en passe et des meilleurs pour qu'au final personne ne soit satisfait ?

Certes, arriver à faire payer la qualité supposerait une évolution des mentalités à la fois du côté du client et du vendeur, et un certain courage de la part du vendeur, mais je pense que le jeu en vaut largement la chandelle.

Le succès des méthodes agiles montre d'ailleurs qu'il existe des prestataires et des clients capables d'accepter cette démarche, dans laquelle tout le monde est gagnant.

Enfin, depuis le début de ce billet, vous avez peut être remarqué que je parle de tests automatisés ou automatiques, alors qu'Amaury se focalise sur les tests unitaires.

Encore une fois, il oublie trop vite que les tests unitaires ne sont qu'un outils parmi bien d'autres, et qu'ils ne sont qu'une des nombreuses couches composant l'oignon qu'est une usine de développement de qualité.

La couverture intégrale du code par les tests peut s'obtenir de bien des manières, aussi bien à l'aide de tests fonctionnels ou d'interface que de tests unitaires, et je pense de plus que quelque soit leur nature, les tests doivent être joués automatiquement et aussi souvent que possible pour être réellement utiles.

De plus, c'est lorsqu'ils sont utilisés en conjonction avec d'autres outils, tel que l'intégration continue ou la revue de code, qu'ils sont le plus efficaces.

Utilisés seuls, les tests unitaires ont effectivement une utilité moindre, même si elle reste suffisamment significative pour être intéressante, et il est possible que, au niveau financier, le jeu n'en vaille peut être pas la chandelle, mais dans ce cas, plutôt que de rogner sur la qualité en abandonnant les tests, c'est peut être tout une façon de produire et de vendre du code qui est à revoir !