Des chiffres sur le ROI des tests unitaires

Le débat autour du ROI des tests unitaires et du TDD (Test Driven Development) ne date pas d’hier comme cet article du blog Octo de 2008 en témoigne :

https://blog.octo.com/le-roi-du-tdd/

Les questions soulevées sont somme-toute naturelles : même convaincu du bien fondé de cette démarche, il est toujours intéressant d’avoir une estimation de combien coûte cet investissement.
Idem lorsqu’on souhaite démarrer un projet en TDD, comment intégrer cette donnée dans le chiffrage ? Doit-on prévoir +20%, +100%, rien du tout ?
Les chiffres tangibles sont rares, aux questions « concrètement combien ça va me coûter en J/H ? Dans quelle proportion je vais réduire le nombre de bugs ? » on est souvent sans réponses.

Plusieurs études ont pourtant été menées sur le sujet, notamment par Microsoft. Ce dernier a publié en 2009 une étude intitulée “On the Effectiveness of Unit Test Automation at Microsoft”. Nous ferons ici un résumé des points à retenir.

1) Le contexte :

L’étude porte sur la comparaison des bugs obtenus entre la V1 et la V2 d’un projet en C#. La V1 avait été réalisée avec des tests manuels, la V2 a été réalisée en introduisant des tests unitaires automatisés (sans TDD).

On apprécie qu’il s’agisse d’un cas réel de grande envergure : 1 200 KLOC (Kilo Line Of Code) réalisé par une équipe de 32 développeurs et 15 testeurs.
On notera également la durée importante de l’étude : 2 ans.

L’étude comporte 2 volets :

  • Des indicateurs sur l’évolution de la qualité du code
  • Le résultat d’une enquête auprès de l’équipe des développeurs et de l’équipe des testeurs au sujet de leur ressenti vis-à-vis de la mise en place des tests

2) Le nombre de bugs diminue

La 1ère constatation est la diminution du nombre de bugs remontés par l’équipe de tests : -20.9%. En moyenne les développeurs estiment que la mise en place des tests représente 30% de temps de développement en plus.

3) Le type de bugs évolue

Les développeurs se sentent poussés à sortir des scénarios classiques (“happy path”) et vérifier les cas limites avant d’envoyer leur développement aux testeurs.

L’équipe a le sentiment que les bugs ont changé : les erreurs grossières sont moins fréquentes. L’équipe de test doit concevoir des scénarios de test plus évolués et plus réalistes (donc plus proche du comportement d’un véritable utilisateur).  Les testeurs trouvent leur travail moins mécanique et se sentent plus efficaces sur une même période de temps. Les développeurs quant à eux ont le sentiment de produire du code plus robuste.

Concernant les bugs restants, les développeurs les jugent plus faciles à corriger quand ils se situent dans du code testé.

Extrait de « On the Effectiveness of Unit Test Automation at Microsoft » Laurie Williams, Gunnar Kudrjavets, and Nachiappan Nagappan November 2009 © 2009 IEEE

4)Comparaison avec le TDD :

Sur le projet étudié les tests étaient écrits après les développements, tous les 2,3 jours.
D’autres projets Microsoft ont obtenu de meilleurs résultats en écrivant les tests avant le code (Test Driven Development).
Les projets en questions ont expérimenté des diminutions du nombre de bugs allant de -62% à -91% pour à peu prés le même coût en terme de temps investi.

Extrait de « On the Effectiveness of Unit Test Automation at Microsoft » Laurie Williams, Gunnar Kudrjavets, and Nachiappan Nagappan November 2009 © 2009 IEEE

P.S : .38X signifie que pour X bugs trouvés sur la V1, il n’en restait plus que 38% sur la V2. Soit respectivement des diminutions de -62%, -76% et -91%.

5) Les leçons retenues :

  • La mise en place de tests unitaires doit être une volonté du managment.
  • Le cout d’écriture et de maintenance des tests unitaires doit faire parti du budget.
  • La testabilité du code doit faire parti des objectifs de l’architecture et du design de l’application.
  • La couverture du code par les tests doit être mesurée, les résultats doivent être visibles et communiqués.
  • Les tests ne sont pas la propriété des développeurs : chaque membre de l’équipe doit pouvoir contribuer
  • L’exécution de l’ensemble des tests doit être une opération simple et rapide.

12 commentaires sur “Des chiffres sur le ROI des tests unitaires”

  • Article intéressant ! Il manque seulement une donnée importante : le temps moyen de correction d'un test unitaire ! En effet, le ROI deviendrait "efficace" dès lors qu'on aura (dans le scénario windows) l'inéquation suivante (T correspondant à la charge moyenne, en Homme/Mois, de correction des tests) : 0.38*T + 0.3*24 11,6 (soit 48% de la charge initiale !) Je me suis peut-être planté dans mes calculs mais ... si j'ai juste, ça aurait tendance à dire que quand même, le ROI est pas bon du tout ... non ?
  • Re-post (les chevrons ne passent pas bien => je les ai remplacés par des "inférieur à" / "supérieur à") Article intéressant ! Il manque seulement une donnée importante : le temps moyen de correction d'un test unitaire ! En effet, le ROI deviendrait "efficace" dès lors qu'on aura (dans le scénario windows) l'inéquation suivante (T correspondant à la charge moyenne, en Homme/Mois, de correction des tests) : 0.38*T + 0.3*24 "inférieur à" T + 0 Soit textuellement "Le coût de correction des anomalies (réduites) + le coût de développement des tests unitaires est inférieur au coût de correction des anomalies (non réduites) sans tests unitaires". L'inéquation ci-dessus donne un résultat : T "supérieur à" 11,6 (soit 48% de la charge initiale !) Je me suis peut-être planté dans mes calculs mais ... si j'ai juste, ça aurait tendance à dire que quand même, le ROI est pas bon du tout ... non ?
  • D'où sort, dans votre démonstration, la leçon retenue : "La couverture du code par les tests doit être mesurée" ? Cette notion me parait difficile : il n'existe pas une relation binaire (ou bijective ? ) entre code et test unitaire, et en plus on teste souvent en fonction de scénarios d'usage, même pour le test unitaire, non en fonction de la quantité de if ou while dans le code, heureusement. Il faut que la couverture d'usage, si vous me passez l'expression, soit, heu... couverte, sans se focaliser sur la couverture du code, à mon opinion.
  • Pour info, le calcul sur les 2 autres exemples (Visual studio et MSN) donne : T(MSN) > 9 soit environ 19% de la charge projet T(VS) > 6 soit environ 30% de la charge projet On peut alors voir que le ROI pourrait être lié (dans les exemples donnés en tous les cas) à la taille de l'équipe (plus on a de monde dans l'équipe, et plus mettre en place des tests unitaire deviendra bénéfique ... ce qui est compréhensible par rapport à la non reg ... à fortiori lorsque le projet est "gros" comme MSN)
  • @Frédéric : Votre équation est juste, mais la variable calculée n'est pas la même : Le bénéfice attendu des test unitaires est avant tout l'augmentation de la qualité, ici mesurée par la diminution du nombre de bugs. A moyen terme cette qualité accrue permet effectivement un gain de temps dans les développements (quand on attaque des évolutions importantes ou du refactoring de code). Mais à court terme (i.e: pour la version en cours de développement) le principal objectif n'est pas forcément de diminuer le temps de développement. @Hervé : Les leçons retenues sont tirées des conclusions de l'étude. La mesure de la couverture de code correspond dans le tableau à l'information "% block coverage". Les tests unitaires servent réellement à tester autant que possible le code d'une application (réalisés avec des framework tels que JUnit, NUnit, etc) Les tests d'usages que vous évoquez correspondent plutôt à des tests d'intégration, où de recette fonctionnelle (réalisées avec des outils comme Selenium). Ces 2 approches de tests sont complémentaires.
  • @Vincent : Je me doute que les tests unitaires servent à tester le code ; je parlais de l'usage de ce code, en tant que code, pas de l'usage de l'application, ni de l'intégration. Un code, ça s'utilise :-) Tous les jours j'utilise l'API java, moi. Oui, j'ai bien vu pour block coverage, mais enfin de là à passer 3 cellules de tableau en "leçon retenue"...
  • Je ne vois aucun lien entre cette étude et ses conclusions. "La mise en place de tests unitaires doit être une volonté du managment."? TDD est une pratique de professionnel du développement qui ne doit être ni interdite ni pousser par le management. Pourquoi ne pas demander au management combien de classse nous devons créer, où quand utiliser un if plutôt que du polymorphisme? Avec une réduction de 91% des défauts, comment peut on encore croire que TDD a un coût? Cette réduction compense sans commune mesure les 20% de temps supplémentaire pour finir la fonctionnalité. Comme il a été dit un peu partout concernant cette étude, il faut comparer ce qui est comparable : le temps de développement + le temps perdu à corriger les défauts. Et on ne parle pas d'une correction qui arrive 6 mois après, mais bien souvent d'une entropie qui s'installe dès les premières heures de développement. Dans ce cas comment le faire apparaître dans un budget? On fait apparaître les économies que ça apporte? cf point 1 : tdd n'est pas négociable, et son hypothétique coût est alors indissociable du développement lui-même. Un code testé est testable par définition, et TDD est en plus une des meilleurs pratiques de design incrémental. Pourquoi alors introduire une notion d'objectif d'architecture? Au mieux, on peut garder la testabilité comme critère premier de choix de framework. La couverture de code est un chiffre à n'utiliser qu'en interne, comme indicateur pour l'équipe de développement. Il ne veut bien souvent pas dire grand chose d'un point de vue extérieur, et communiquer dessus et finalement plus dangereux qu'autre chose tant il peut être mal interprété. (Comme expliqué dans Clean code). Les tests unitaires sont la propriété des développeurs. Il ne faut pas confondre tests d'acceptation ou fonctionnels, et tests unitaires. Les tests unitaires sont le moyen pour les développeurs d'avoir confiance en leur code, les tests fonctionnels sont le moyen pour les clients d'avoir confiance en l'application. Au moins, je suis d'accord avec la dernière conclusion.
  • @Vincent Je m'aperçois que dans mes commentaires, je mélange temps et charge. La variable T est bel et bien une charge (contrairement à ce que la lettre pourrait laisser entendre). Je me place donc bien sur un axe pécunier pour essayer d'extrapoler un ROI financier. J'entends (et j'adhère bien évidemment) complètement qu'en terme de qualité, le TDD améliore drastiquement les choses... mais je préfère rester "terre à terre" car ce sont généralement sur les chiffres que les décideurs disent "go / nogo".
  • De mémoire (pour avoir lu le papier en anglais il y a environ un an), il me semble que vous faites erreur dans l'interprétation des résultats TDD. Si c'est le cas, "decrease in defects of .38x" voudrait dire qu'on réduit d'environ 38% le nombre de défectuosités. On aurait donc une efficacité de réduction de bugs pour TDD entre 9 et 38%, et non pas entre 91 et 62%. Si vous avez accès au papier, ce serait vraiment sympa de con(in)firmer votre interprétation!
  • Le papier mentionne "The TDD teams realized a significant decrease in defects, from 62% to 91%" au dessus du tableau qui a été reproduit dans cet article de blog. L'interprétation faite dans l'article de blog me semble correcte.
  • Super! Merci pour l'article, et merci beaucoup pour la confirmation!
  • article très intéressant , merci
    1. Laisser un commentaire

      Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


      Ce formulaire est protégé par Google Recaptcha