dimanche 9 janvier 2011

Tests unitaires

Mais comment ai-je pu coder pendant des années sans tests unitaires? Ce truc, c'est LA pratique qui a augmenté mon rendement, m'a permis de mieux dormir la nuit, et m'a sauvé la vie (professionnelle, tout du moins) plus d'une fois.

Il y a quelques années, j'avais eu entre les mains un bouquin sur le développement orienté tests (le TTD, "Test Driven Development"), et j'avais douté leur déclaration qu'une fois touché aux tests unitaires, on ne pouvait plus s'en passer. Eh bien, ils avaient raison. Une fois utilisés correctement, les avantages sont tels qu'il devient évident que l'on ne peut vivre sans.

Cependant, utilisés à mauvais escient, ils peuvent faire plus de mal que de bien. Il y a donc quelques règles à garder à l'esprit quand on se lance à écrire du code.

  • Les tests unitaires influencent le design. Il est rare qu'un bout de code quelconque, une fois atteint une complexité minimale, puisse être testé tel quel. Lorsque l'on sait que l'on va devoir tester le code, l'on tend à diminuer les effets de bord, à découpler ses routines, à écrire des interfaces afin de pouvoir "moquer" ses objets. Ça tombe bien, ce sont le genre d'habitudes qui améliorent la qualité du code!

  • Corollaire du point précédent: il est généralement difficile d'ajouter des tests unitaires à un projet existant. Le projet dépend probablement de fichiers de configuration non moqués, force les logs vers un fichier, cause à la base de données, n'est pas séparé par bibliothèques indépendantes, dépend d'une GUI, dépend de l'horloge, écrit ses résultats dans un fichier Excel, etc. Demander tout à coup aux développeurs de "tester toute la codebase mais sans y toucher" est voué à l'échec. Pour approcher un gros projet non testé, il va falloir doucement, au fur et à mesure des nouvelles fonctionnalités ou des corrections de dysfonctionnements, tenter d'abstraire et de découpler pour pouvoir tester le changement. Au fur et à mesure que le code évolue, le nombre de tests augmente, et la qualité du produit avec.

  • Il existe un point où la loi des rendements décroissants entre en ligne. À moins de coder pour la NASA ou autre cas où la qualité doit être absolue, l'abus de tests unitaires rend le code plus difficile à changer (car il risque de casser une batterie de tests). Le développeur peu scrupuleux (et, croyez le ou non, il y en a!), plutôt que de plonger dans les abîmes de la perplexité, se laisse aller à sa paresse naturelle et désactive les tests urticants. Avant peu, les 3/4 des tests ont été éliminés, et ne testent plus rien du tout (point bonus aux développeurs qui désactivent les tests en commentant l'intérieur de chaque routine, afin que leur forfait n'apparaisse pas dans les statistiques de chaque build).

  • À contrario, l'utilité des tests augmente exponentiellement avec leur nombre. Quelques tests sur les fonctionnalités de base ne vont probablement jamais casser, et quand bien même un bug se serait glissé dans le code, il aurait été rapidement trouvé. Tandis qu'une batterie de tests sur les fonctionnalités centrales mais plus complexes vont trouver beaucoup plus de régressions. C'est pour cela qu'il peut être difficile de convaincre certains développeurs: n'ayant rien vu venir après avoir coder leur petite dizaine de tests, ils n'en voient pas l'intérêt. Il faut persévérer!


Le test, c'est comme le chocolat: un incomparable sentiment de plénitude lorsque la dose est bonne.

Aucun commentaire: