3ème partie - Les risques associés aux tests trop longs

De Wiki Agile du @GroupeCESI
Aller à : navigation, rechercher

Auteur : J. B. Rainsberger
Source : Part 3: The risks associated with lengthy tests
Date : 2009


Traducteur : Fabrice Aimetti
Date : 05/09/2011


Traduction :

Je viens de lire un tweet de Dale Emery qui a attiré une nouvelle fois mon attention sur le thème des tests d'intégration et de leur caractère illusoire.
[Ce tweet a disparu, merci Tweetpaste. Je n'ai plus le lien sur l'original. Je m'en excuse.]
Puisque les praticiens ont tendance à écrire des tests d'acceptation sous forme de tests (d'intégration) de bout en bout, je pense pouvoir sans risque remplacer l'expression "tests d'intégration" par "tests d'acceptation" et conserver l'essence du message de Dale. Je fais cela parce que je ne veux pas que vous concluiez à partir de ce que j'ai l'intention d'écrire que je traite les tests d'acceptation avec le même dédain que je traite les tests d'intégration. J'ai déjà traité de celà quand Eric Lefevre-Ardant nous a présenté à David, Développeur Agile, l'une des personnes que Agile 2009 a posté pour aider les gens à choisir les sessions de la conférence. Bien que je me sois senti flatté qu'il ait choisi ma session parmi celles à laquelle on pouvait assister, il a accidentellement rebaptisé ma session "Les tests d'acceptation sont une arnaque", ce qui a déclenché une mini-tempête dans la sphère Twitter. Pour rester bref : J'aime les tests d'acceptation lorsque nous les écrivons pour confirmer la présence d'une fonctionnalité ; et je les déteste lorsque les programmeurs écrivent des tests d'intégration pour vérifier la conception et le comportement des grandes parties du système, et qu'ils les appellent "tests d'acceptation" pour justifier leur existence.
Revenons à la question de Dale, que je paraphrase : à combien de reprises écrivons-nous des tests d'intégration défectueux, ce qui signifie que l'échec du test indique une erreur dans le test plutôt que dans le code ? Plutôt que de tenter de répondre à cette question, je préfère écrire sur une idée fortement liée : les tests d'intégration échouent nécessairement plus fréquemment et de manière plus coûteuse que les tests isolés sur des objets, même lorsque le code sous-jacent se comporte comme prévu. Pour simplifier un peu le discours, laissez-moi introduire le terme échec injustifié du test pour signifier l'échec d'un test sans anomalie correspondante dans le code. Quand un test incorrect échoue, je baptiserai l'échec d'injustifié.

Le coût des échecs injustifiés de tests


Un échec injustifié a à la fois un coût visible et un coût caché. Nous connaissons le coût visible et immédiat : un échec injustifié me pousse à faire une analyse des causes racines sur un échec qui n'existe pas en réalité, ce qui me coûte un peu et ne me rapporte rien. Ce qui est plus insidieux, cependant, c'est que la persistance de ces faux échecs érode ma confiance dans les tests. J'ai tendance à moins valoriser les tests. Je les exécute moins souvent, et réduisant la valeur réelle obtenue en retour. Avec moins de retour vient moins de confiance dans le code, et un comportement plus conservateur vis-à-vis du code. Je modifie le code moins souvent ; j'évite les changements importants, même quand ils semblent appropriés ; j'accueille moins favorablement les idées, car je ne peux pas aussi facilement prédire le coût des modifications concernées. Je commence à concevoir pour ne pas perdre, plutôt que de concevoir pour gagner. Je ne peux pas quantifier ce coût sur un projet donné, mais je le pressens et nous pouvons le mesurer au fil du temps. Je pense que l'on devrait éliminer les échecs injustifiés de tests lorsque c'est possible, ou du moins lorsque c'est facile, et les tests d'intégration provoquent tout simplement un nombre important d'échecs injustifiés.

Les tests d'intégration échouent de façon injustifié plus souvent


Laissez-moi soutenir cette conjecture avec deux arguments principaux.
Tout d'abord, les tests d'intégration ont tendance à exiger plus de lignes de code que les tests isolés sur des objets. Pour être un peu plus formel, au fur et au mesure que nous écrivons de plus en plus de tests d'intégration et de plus en plus de tests isolés sur des objets dans un système, la durée moyenne des tests d'intégration devient beaucoup plus grande - au moins le double - que la durée moyenne des tests isolés sur les objets correspondants. Si nous acceptons ce principe, et que nous le combinons avec l'autre principe bien admis que plus de code signifie plus d'anomalies ''en général'', cela implique directement que les tests d'intégration ont tendance à avoir plus d'anomalies que les tests isolés sur des objets. Cela signifie que les tests d'intégration échouent de façon injustifiée plus fréquemment que les tests isolés sur des objets.
Ensuite, comme les tests d'intégration reposent sur la justesse de plus d'un objet, il s'ensuit directement qu'une anomalie dans un objet génère davantage d'échecs de tests d'intégration que d'échecs dans les tests isolés sur les objets correspondants. Cette anomalie peut provenir de deux classes d'échecs de tests : ceux qui sont justifiables dans les tests conçus pour vérifier un comportement défectueux, et les injustifiés dans les tests conçus pour vérifier un autre comportement, mais qui exécute le code défectueux.
Vous pouvez imaginer un exemple de ce dernier cas en pensant à un test d'intégration qui vérifie une branche spécifique du code à l'étape 4 d'un processus en 5 étapes. Ce test doit exécuter les étapes 1 à 3 du processus avant d'exécuter l'étape 4, donc si nous avons une anomalie à l'étape 2 du processus, alors ce test échoue de façon injustifié, car il n'a pas activement essayé de vérifier l'étape 2. Alors que l'échec du test peut être justifié par une anomalie à l'étape 2, je baptise cet échec d'injustifié par rapport au comportements à tester, parce que ce test n'a pas pour intention délibérée de tester l'étape 2. Vraisemblablement, nous avons des tests qui ont pour objectif de tester l'étape 2, et qui échoue de façon justifiable.
Les tests d'intégration entraînent alors des échecs injustifiés en exécutant certains comportements potentiellement défectueux sans avoir l'intention de les vérifier. Bien que que je n'appellerais pas cela une anomalie dans le test, le test échoue néanmoins de façon injustifié.
J'ai essayé ici de décrire le problème de l'échec injustifié des tests et d'expliquer comment les tests d'intégration devaient nécessairement entraîner plus d'échecs injustifiés de tests par rapport aux tests isolés sur des objets. J'avoue que je n'ai pas comparé le coût de ces échecs injustifiables de tests par rapport aux coûts correspondants à l'écriture de tests isolés sur des objets. Je ne peux pas espérer réaliser une étude quantitative approfondie sur la question. Au lieu de cela, je veux simplement soulever des questions, faire quelques conjectures, réfléchir sur ces sujets, puis laisser le lecteur décider. J'ai décidé d'écrire davantage de tests isolés sur les objets et moins de tests d'intégration à moins que je ne me trouve dans un contexte radicalement différent de ceux que j'ai vus au cours de ces dix dernières années.