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 ! ».