Mais pourquoi « seulement » 80 % alors que le développement d’atoum a été piloté par les tests ?
Tout simplement parce que le développement de certaines portions de son code n’a pas été piloté par les tests, car atoum n’était pas fonctionnel à ce moment puisqu’en cours de développement.
Et ce taux de couverture de « seulement » 80 % n’est de toute façon pas réellement un problème.
En effet, atoum se testant avec lui-même, chaque contributeur effectue implicitement sur atoum des tests manuels lorsqu’il travaille sur son code.
En conséquence, si les tests unitaires laissent passer un bug, ce qui ne peut manquer d’arriver, car l’Humain est faillible, alors les tests manuels permettront éventuellement de le détecter.
Il sera alors reproduit sous la forme d’un test unitaire qui viendra s’ajouter à ceux déjà existants avant d’être corrigé, ce qui permettra d’éviter sa réapparition à l’avenir.
Ainsi, contrairement à ce que la plupart des développeurs semblent penser, les tests automatisés, qu’ils soient unitaires ou fonctionnels, ne rendent aucunement les tests manuels facultatifs.
En effet, en l’état actuel de la Science, l’intervention humaine est encore indispensable, autant au niveau de la conception des tests que de leur exécution, car la machine ne dispose pas encore de la puissance et de l’intelligence nécessaire pour générer les tests permettant de vérifier la validité technique et fonctionnelle d’un code.
Alors, quel est l’intérêt d’avoir des tests automatisés s’ils doivent impérativement être complétés par des tests manuels ?
Il y en a plusieurs.
Tout d’abord, ils sont exécutés par une machine qui coûte beaucoup moins cher à une entreprise qu’un salarié, puisqu’une machine a un coût fixe amortissable alors que ce n’est pas le cas du salarié.
Donc même si le salarié doit passer du temps à écrire des tests, la machine reste tout de même extrêmement plus rentable que lui, d’autant que pendant qu’elle travaille, il peut continuer à développer.
Et si d’aventure le développeur fait du développement piloté par les tests, le coût des tests est alors intégré au coût du développement et devient donc totalement transparent, ce qui augmente encore l’intérêt des tests automatisés d’un point de vue financier.
De plus, les tests automatisés sont exécutés par la machine qui garantie, de par sa nature, qu’ils seront exécutés de manière exhaustive, alors que ce n’est pas le cas lorsqu’ils sont exécutés par l’Humain, ce dernier étant faillible par nature.
J’ajoute que la machine exécute les tests beaucoup plus rapidement que l’Humain.
Or, il a été démontré que plus un bug est détecté tôt, moins sa correction coûte cher.
Enfin, les tests unitaires permettent d’obtenir un certain nombre d’informations à propos du code et donc de quantifier sa qualité, ne serait-ce que grâce au taux de couverture et même si ce dernier est à prendre avec des pincettes dans le cadre de PHP.
Les tests unitaires ont donc très clairement un intérêt puisqu’ils permettent d’augmenter la productivité du développeur tout en limitant les coûts.
Cependant, malgré leur forte valeur ajoutée, ils ne sont pas magiques et sont complémentaires des tests manuels et ne les remplace en aucune manière en l’état actuel de la technologie.
Et de même, les tests unitaires ne rendent pas les tests fonctionnels facultatifs, tout comme les tests fonctionnels ne rendent pas les tests unitaires facultatifs.
Tout comme les tests automatisés et les tests manuels, ils sont en effet complémentaire même s’ils sont tous deux automatisés.
Nous en avons d’ailleurs régulièrement la preuve dans le cadre du développement d’atoum, car à ce jour le projet ne contient aucun test fonctionnel.
Or, la plupart des bugs qui nous sont rapportés auraient pu être détectés à l’aide de tests fonctionnels.
En effet, les tests unitaires virtualisent à l’aide de bouchons les dépendances des méthodes testées.
Or, cette virtualisation peut ne pas refléter la réalité, tout comme la Matrice peut ressembler à la réalité, mais pour autant permettre des comportements irréalistes.
Faut-il pour autant éviter de recourir au bouchonnage ou bien en limiter drastiquement et arbitrairement l’utilisation ?
Je ne le pense pas.
Il me semble que la solution est de vérifier la corrélation entre le monde virtuel défini par les tests unitaires et la (parfois) dure réalité grâce aux tests fonctionnels qui eux s’exécutent dans un cadre très proche sinon identique à celui de la production.
Les tests fonctionnels vont alors permettre aussi bien la détection des éventuels bugs présents dans le code que ceux présents dans les tests, faisant d'une pierre deux coups.
De plus, un test unitaire indique qu’une méthode utilisée individuellement se comporte correctement dans le contexte défini par le test.
Cependant, cela ne donne aucune garantie sur son fonctionnement lorsque cette méthode doit collaborer avec d’autres dans le cadre d’une application et dans un contexte de production.
Or, le test fonctionnel peut apporter dans une certaine mesure cette garantie puisqu'il met en jeu le code dans son intégralité et non plus uniquement une méthode isolée.
Enfin, il peut être parfois très difficile techniquement d’écrire un test unitaire, ou alors cela prendrait bien trop de temps pour être rentable économiquement parlant.
La solution est alors non pas de ne pas tester, mais d’écrire un test fonctionnel qui est bien souvent plus simple à mettre en place.
Les tests fonctionnels sont donc clairement le chaînon manquant actuellement dans la chaîne de production d’atoum et j’espère trouver le temps à moyen de terme d’y remédier.
Malgré la mise en place d’une intégration continue sur Travis ainsi que sur notre propre infrastructure, nous avons donc des axes d’amélioration possible en ce qui concerne la politique de développement d’atoum.
Mais reste que malgré cette carence en test fonctionnel, nous disposons d’une base de test qui nous permet d’avoir la quasi-certitude que le code se comporte toujours de la même façon qu’auparavant après une modification, ce qui nous permet de réagir très rapidement sans devoir passer par une longue et fastidieuse phase de tests manuels tout en ayant confiance dans la qualité de nos modifications.
C’est par exemple grâce à cela que j’ai pu modifier en profondeur et en quelques minutes le fonctionnement du système de bouchonnage d’atoum en ayant la quasi-certitude de ne pas avoir introduit un bug.
Comme l’a rappelé Olivier Mansour dans son dernier billet, « un test, c’est mieux que pas de test ! ».
3 réactions
1 De Renaud - 26/04/2013, 16:47
"Et si d’aventure le développeur fait du développement piloté par les tests, le coût des tests est alors intégré au coût du développement et devient donc totalement transparent"
Je ne suis point d'accord avec toi sur cette phrase en particulier alors que je suis d'accord avec le reste.
Mais non, le coût du test n'est pas transparent car écrire ses tests prends un certain pourcentage de temps en plus que si on ne l'écrit pas. Ce petit pourcentage est totalement récupéré sur la durée de vie du projet lors de la correction de bug, l'ajout de feature ou le refactoring, mais il n'est pas transparent lors du dev.
Et c'est précisément la raison pour laquelle autant de dev refuse d'en faire car ils estiment que c'est une perte de temps. Ils ont raison à très court terme, car si un dev avec tests prend 1 journée, un dev sans tests en prenant probablement 25 à 50% de moins (données venant du pifomètre de compétition que je me suis offert à noël dernier). Mais ils ont totalement tord sur le long terme.
2 De Yoann - 26/04/2013, 20:19
@Renaud : Je suis pas tout à fait d'accord avec toi, tu vois l'écriture des tests unitaires comme un surplus de code et donc de temps, alors que ce temps perdu peut permettre d'économiser du temps de test même sur du très court terme durant le développement de la fonctionnalité. Cela peut aussi permettre de se forcer à avoir une réflexion sur la manière de découpler son code en amont car cela facilitera la mise en place des tests unitaires et donc évitera ultérieurement (au moins partiellement) d'avoir à faire du refactoring (du temps que l'on nous accorde pas forcément). Attention je ne dis pas que cela est forcément vrai dans tous les cas, juste qu'on ne peut pas forcement dire qu'écrire des tests unitaires soit une perte de temps sur du court terme. Après sur la raison de pourquoi beaucoup de développeurs boudent les tests unitaires, je pense simplement que beaucoup n'en voient tout simplement pas l'intérêt et ne cherchent pas à le voir. Surtout que cela demande un temps d'adaptation et de casser toutes ses habitudes de développement.
3 De Renaud - 27/04/2013, 08:31
@Yoann : Mageekguy, sur irc, me dit la même chose que toi, mais vous ne comprenez pas quel mot m'a fait bondir. C'est le mot "transparent".
On ne peut pas dire que c'est transparent. C'est comme si j'étais livreur, que je devais faire le trajet Marseille-Paris le plus vite possible (c'est une demande de mon patron) et que je fais un détour par Lyon et Strasbourd. Même si à terme, ça va me faire gagner du temps parce que je profite de ce voyage pour livrer d'autres colis et donc, que je n'aurai pas à faire ces voyages la semaine prochaine, ce n'est pas transparent. Sans ces détours, j'aurais mis 10h de trajet et là, j'en ai mis 15. MAIS ça m'a fait gagner du temps sur mes futurs boulots puisque je n'aurai pas à faire 2 autres trajets de 6 et 8h une autre fois.
Ok, c'est un exemple en carton, mais ce que je veux dire c'est que "intégrer le cout des tests" et dire que c'es transparent, c'est comme dire "intégrer le temps des détours" et dire que c'est transparent. Écrire 12 lignes de tests, c'est du temps que tu ne passes pas à écrire 12 lignes de code. Indépendamment du fait que ça structure mieux ton code, que tu "t'assures" de ne pas faire d'erreur et du temps gagné plus tard lorsque tu voudras rajouter une feature ou refactorer ton code. À **très court terme**, c'est "du temps perdu". Et comme je le dis dans le dernier paragraphe de mon précédent commentaire, c'est justement cette sensation de temps perdu SI ON A UNE VISION À COURT TERME UNIQUEMENT qui rebute pas mal de développeur à se lancer dans l'écriture de tests.
Qu'on soit bien clair, je ne dis absolument pas que c'est du temps perdu et qu'il ne faut pas écrire de tests, bien au contraire. Je tique sur le mot "transparent".
De toute façon, soit c'est comme je dis et le temps pris à faire des tests rallonge le développement d'une feature et n'est donc pas transparent, soit c'est comme vous dites, toi et Mageekguy, et le développement avec les tests vous en fait gagner... et n'est donc pas transparent non plus
Mon expérience personnelle me montre que je prends plus de temps à développer à l'instant t qu'en j'écris des tests mais que j'en gagne bien d'avantage au fur et à mesure de la vie du projet/de la feature. Je ne pense pas que ce soit vraiment quantifiable mais certaines fois, j'ai vraiment l'impression de gagner plusieurs heures voire plusieurs jours grâce aux tests.