J'ai une anecdote pertinente sur quelque chose qui se passe en ce moment pour moi. Je suis sur un projet qui n'utilise pas TDD. Nos gens d'AQ nous font avancer dans cette direction, mais nous sommes une petite tenue et cela a été un long processus.
Quoi qu'il en soit , j'utilisais récemment une bibliothèque tierce pour effectuer une tâche spécifique. Il y avait un problème concernant l'utilisation de cette bibliothèque, il m'a donc été essentiellement demandé d'écrire une version de cette même bibliothèque par moi-même. Au total, cela a fini par représenter environ 5 000 lignes de code exécutable et environ 2 mois de mon temps. Je sais que les lignes de code sont une mauvaise métrique, mais pour cette réponse, je pense que c'est un indicateur de grandeur décent.
Il y avait une structure de données particulière dont j'avais besoin qui me permettrait de garder une trace d'un nombre arbitraire de bits. Étant donné que le projet est en Java, j'ai choisi Java BitSet
et l'ai modifié un peu (j'avais également besoin de pouvoir suivre les 0
s principaux , ce que BitSet de Java ne fait pas pour une raison quelconque .....). Après avoir atteint une couverture d'environ 93%, j'ai commencé à écrire des tests qui mettraient en fait à l'épreuve le système que j'avais écrit. J'avais besoin de comparer certains aspects de la fonctionnalité pour m'assurer qu'ils seraient assez rapides pour mes besoins finaux. Sans surprise, l'une des fonctions que j'avais outrepassées de l' BitSet
interface était absurdement lente lorsqu'il s'agissait de grands ensembles de bits (des centaines de millions de bits dans ce cas). D'autres fonctions remplacées reposaient sur cette seule fonction, il s'agissait donc d'un col de bouteille énorme .
Ce que j'ai fini par faire, c'était d'aller à la planche à dessin et de trouver un moyen de manipuler la structure sous-jacente de BitSet
, qui est a long[]
. J'ai conçu l'algorithme, j'ai demandé à mes collègues leur avis, puis j'ai commencé à écrire le code. Ensuite, j'ai exécuté les tests unitaires. Certains d'entre eux se sont cassés, et ceux qui l'ont fait m'ont indiqué exactement où je devais chercher dans mon algorithme afin de le réparer. Après avoir corrigé toutes les erreurs des tests unitaires, j'ai pu dire que la fonction fonctionne comme il se doit. À tout le moins, je pouvais être aussi convaincu que ce nouvel algorithme fonctionnait aussi bien que l'algorithme précédent.
Bien sûr, ce n'est pas à l'épreuve des balles. S'il y a un bogue dans mon code que les tests unitaires ne vérifient pas, je ne le saurai pas. Mais bien sûr, ce même bogue aurait pu également se trouver dans mon algorithme plus lent. Cependant , je peux dire avec une grande confiance que je n'ai pas à me soucier de la mauvaise sortie de cette fonction particulière. Les tests unitaires préexistants m'ont fait gagner des heures, voire des jours, à essayer de tester le nouvel algorithme pour s'assurer qu'il était correct.
C'est le point d'avoir des tests unitaires indépendamment de TDD - c'est-à-dire que les tests unitaires le feront pour vous dans TDD et en dehors de TDD tout de même, lorsque vous finirez par refactoriser / maintenir le code. Bien sûr, cela devrait être associé à des tests de régression réguliers, des tests de fumée, des tests flous, etc., mais les tests unitaires , comme son nom l'indique, testent les choses au niveau atomique le plus petit possible, ce qui vous indique où les erreurs sont apparues.
Dans mon cas, sans les tests unitaires existants, je devrais en quelque sorte trouver une méthode pour garantir que l'algorithme fonctionne tout le temps. En fin de compte, cela ressemble beaucoup à des tests unitaires , n'est-ce pas?