Note de lecture : Unit Testing : Principles, Practices and Patterns, par Vladimir Khorikov

Note : 8 ;Des principes et des guidelines très solides pour concevoir les tests unitaires et les tests d’intégration.

Ce n’est pas le premier ouvrage sur les tests unitaires, bien loin s’en faut ! Mais c’est une belle surprise, même si elle bouscule un peu certaines de mes idées établies sur le sujet. Le but de l’auteur est de faire émerger et poser les principes sous-jacents à la pratique des tests unitaires. On pourrait penser que cela peut se contenter d’un mémoire de 50 pages au plus ? Il n’en est rien.

Au niveau du format, le livre rentre dans la moyenne : 270 pages sur 11 chapitres, le tout divisé en 3 parties inégales. . La première d’entre-elle nous dresse le paysage des tests unitaires sur un peu plus de 60 pages incluant 3 chapitres. La finalité des tests unitaires est l’objet des 20 pages du premier chapitre. C’est un début en douceur où est évoqué la question de l’entropie du code, mais où l’auteur s’attaque surtout au mythe de la couverture de code (à juste titre). Dommage que le mutation testing ne soit pas évoqué, ni ici ni plus tard.

Le second chapitre s’attaque à des principes fondamentaux : qu’est-ce qu’un test unitaire ? Une question moins simple qu’il n’y parait. Outre la granularité délimitant le test unitaire des tests d’intégration ou de bout en bout, c’est surtout le choix de l’école de pensée qui est en cause : école de Londres (parfois appelés tests solitaires) ou école classique ou de Chicago (parfois appelés tests sociaux). L’auteur ne fait pas mystère de sa préférence pour l’approcha classique, mais fait un excellent travail pour déterminer comment chaque approcha traite les différents types de dépendances. Le chapitre s’attaque à l’anatomie interne des tests unitaire. Il n’est guère surprenant que l’auteur fasse la promotion du pattern AAA (Arrange, Act, Assert). Il va plus loin en détaillant les bonnes pratiques sur chacun des volets pour améliorer la lisibilité et la maintenabilité des tests, pour ensuite adresser la question de leur paramétrage.

La seconde partie regroupe 4 chapitres et s’intitule « making the tests working for you », ce qui en dit très peu sur le contenu. Le chapitre 4 est très certainement l’un des plus importants du livre. Il établit l’un des principes majeurs des tests unitaires selon l’auteur, les 4 piliers : protection contre les régressions, résistance au refactoring, feedback rapide et maintenabilité. Les principes 2 et 4 lui permettent d’enfoncer le clou en faveur de l’école classique. C’est un chapitre assez pointu où il est question de rapport signal / bruit et d’analyse de faux positifs et de faux négatifs. Il sert à l’auteur à enfoncer le clou sur l’approche classique. Mocks et stubs, ce n’est pas la même chose, et c’est un des enseignements du chapitre 5. Au-delà de ce point et malgré le peu d’engagement de l’auteur à leur égard, il est question de comprendre pour quels types de dépendances ces artifices sont non seulement utiles mais bien nécessaires. Un propos qui nous conduit aussi vers l’architecture hexagonale, même si le propos s’égare un peu ici.

Au chapitre 6 il est question de 3 styles de test : output-based testing, state-based testing et communication-based testing. J’avoue n’avoir jamais factualisé les choses ainsi. Fort logiquement, ces 3 styles sont évalués selon les 4 piliers, où le premier type de test remporte la palme. En seconde partie de ce chapitre, il est question d’architecture fonctionnelle, qui s’adapter fort bien à l’output-based testing. J’aime beaucoup l’image globale dans laquelle l’auteur inscrit cette architecture au sein d’une architecture hexagonale, entourée d’une « mutable shell ». Car comme l’auteur le souligne, la finalité d’un programme est bien d’avoir un effet de bord. En chapitre très riche en enseignements. Le chapitre 7 nous propose une stratégie pour refactorer les tests en s’appuyant sur un modèle à quatre quadrants. L’approche n’est pas entièrement convaincante, mais reste très intéressante, surtout dans les réflexions qu’elle apporte pour séparer la partie contrôleur des parties algorithmiques.

La 3ème partie a trait aux tests d’intégration. Pour l’auteur les tests d’intégration comprennent les « out of process dependencies », car les « in process » sont comprises dans les tests unitaires dont je finis par trouver l’unité bien volumineuse… En fonction du sous-type de dépendance, gérée ou non-gérée, on intégrera directement le sous-système ou on lui substituera un stub, respectivement. La stratégie est claire et a un sens. Ce sont ensuite les conséquences en terme conception qui seront ensuite explorées. Un chapitre mitigé, mais qui reste d’excellente qualité. Le chapitre 9 « mocking best practices » est très court. Il évoque les stratégies de design pour mocker les interfaces. La stratégie est claire : placer son mock au plus près du sous-système, quitte à refactorer le design en conséquence.

Le chapitre 11 traite spécifiquement du test des bases de données. Les aspects intéressants concernent la gestion des jeux de données et la gestion du modèle de la base et des données de référence. L’auteur expose clairement les approches « state based » et « migration based » en marquant très fortement sa préférence pour l’approche « migration based », ce que je ne partage pas. L’aspect test de la base de données est moins intéressant : on ne teste pas la base de données, mais le code s’appuyant sur la base de données. Le dernier chapitre (qui forme aussi la 4ème partie à lui tout seul) résume des anti-patterns de test unitaires, mais qui finalement ont tous été vus au long des chapitres.

Voilà un ouvrage qui aura su m’étonner. Les tests unitaires sont parmi nous depuis 2 décennies et je pensais en apprendre peu ou sinon juste voir un point de vue différent. Il n’en est rien, l’auteur nous pose des fondations de principes sous-jacents aux tests unitaires tout à fait convaincants. J’aurais aimé des exemples plus « grandeur nature » de ce qu’il appelle « unité de comportement », car ils me semblent emmener les tests unitaires vers des unités bien volumineuses et donc peu discriminantes. D’un autre côté sa grande toile des tests ignore complètement les tests d’acceptation et la granularité des deux me semble rentrer en collision. Bref, je me trouve encore loin de la vérité unique… Un livre qui mérite largement le détour, quoi qu’il en soit.

Unit Testing : Principles, Practices and Patterns, par Vladimir Khorikov

Référence complète : Unit Testing : Principles, Practices and Patterns – Vladimir Khorikov – Manning 2020 – ISBN : 978 1 61729 627 7

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l’aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.