Rendez vous AFUP du 11 juillet 2012 à Lyon

mageekguy edited this page Jul 13, 2012 · 4 revisions

Rendez-vous AFUP à Lyon le 11 juillet 2012

Le support de cette conférence est également disponible au format pdf.
Une vidéo de l'évolution du dépôt de code de atoum de sa création à aujourd'hui a servi d'introduction à la conférence.

RDV AFUP du 11 juillet 2012 diapo 1

Nous sommes réunis aujourd’hui grâce à l’antenne lyonnaise de l’AFUP et à la société Elao pour parler de « TDD » et de atoum.
Je vais donc commencer par vous expliquer pendant environs une dizaine de minutes ce qu’est le « TDD ».
Ensuite, dans un second temps, je vous présenterai pendant une dizaine de minutes atoum et plus particulièrement les principes fondamentaux qui régissent à la fois son développement et son utilisation.
Enfin, je poursuivrai par une démonstration de atoum qui durera approximativement une trentaine de minutes, avant de conclure par la traditionnelle session de questions/réponses.

RDV AFUP du 11 juillet 2012 diapo 2

« TDD » signifie en anglais « Test Driven Development », ce qui peut se traduire en français par « Développement piloté par les tests ». Mais qu’est ce qu’un test, et pourquoi doit-il piloter le développement ?

RDV AFUP du 11 juillet 2012 diapo 3

Indépendamment du domaine dans lequel est il est réalisé, un test permet de comparer un résultat théorique à un résultat pratique.
Dans le cas de l’informatique, il permet donc de vérifier qu’un programme se comporte comme il est bien censé le faire lorsqu'il est exécuté.
Un test informatique défini donc en quelque sorte le cahier des charges du code, puisqu’il décrit la façon dont il doit être utilisé par l’utilisateur afin que ce dernier obtienne le résultat qu’il désire.
Un test peut être conçu et exécuté entièrement par l’Homme, ou bien conçu par l’Homme et exécuté par la machine, et dans ce cas, il se présente donc sous la forme d’un programme informatique, bien souvent écrit à postériori du code à tester, car il semble très logique qu’il faille tout d’abord écrire du code afin de pouvoir le tester.
Cependant, malgré son apparente logique, cette approche a au moins trois inconvénients majeurs.

RDV AFUP du 11 juillet 2012 diapo 4

Tout d’abord, pour être testable, un code doit être écrit d’une certaine manière, en suivant un certain nombre de règles.
Or, les développeurs n’ont pas forcément ces règles en tête au moment de la rédaction du code et il arrive donc souvent qu’il soit nécessaire de le modifier afin de le rendre testable.
Entre parenthèse, les règles permettant d'écrire du code testable étant les mêmes que celles qui permettent d'avoir du code de qualité, le fait d’écrire les tests à postériori n’encourage pas à la conception d’un code de qualité dès le départ.

RDV AFUP du 11 juillet 2012 diapo 5

Le fait que les tests soient écrits à postériori conduit également souvent à l’écriture de code qui n’est pas utile au fonctionnement final du programme, car les développeurs étant déconnectés de l'aspect pratique de leur code lors de sa conception, ils pensent souvent à tort qu'ils auront besoin de bien plus de fonctionnalités que ce dont ils auront besoin en réalité.

RDV AFUP du 11 juillet 2012 diapo 6

Enfin, il arrive également régulièrement au moment de l’écriture des tests à postériori que les développeurs se rendent compte que la façon dont le code doit être utilisé n’est pas pratique ou est source de confusion, bref, qu’il n’est pas simple à mettre en œuvre et qu’en conséquence, il doit être modifié ou bien utilisé tel quel.
Écrire les tests à postériori peut donc engendrer dans le pire des cas simultanément de la frustration au niveau des développeurs, des coûts significatifs en terme financier et un dépassement du planning.

RDV AFUP du 11 juillet 2012 diapo 7

La solution à ces problèmes est donc d’écrire non pas à postériori, mais à priori, et donc de faire du « TDD ».
Lorsqu’il doit développer une nouvelle fonctionnalité ou faire une modification en faisant du « TDD », le développeur commence donc par décrire dans un test le comportement qu’il doit avoir.
Il est alors confronté directement à des cas d'utilisation concret de son code, et dans bien des cas, c'est déjà un problème car il n'a aucune idée de la façon dont son code doit être utilisé pour obtenir le résultat souhaité.
Faire du « TDD » a donc comme premier avantage de mettre immédiatement le code « en situation » et de confronter le développeur a un cas réel d'utilisation du code qu'il va écrire.
Corollaire de cela, il ne développera que les fonctionnalités absolument nécessaire pour obtenir la fonctionnalité dont il a besoin.

RDV AFUP du 11 juillet 2012 diapo 8

Le développeur exécute ensuite son test, afin de vérifier sa pertinence.
S’il s’exécute avec succès, c’est que le code nécessaire existe déjà et qu’en conséquence, il n’a rien à faire si ce n’est supprimer son test, car il fait forcément doublon le test ayant permis d’écrire le code désiré.

RDV AFUP du 11 juillet 2012 diapo 9

Dans le cas contraire, il peut alors écrire le code le plus simple et le plus minimal possible nécessaire à sa bonne exécution.
Et comme le test a été écrit en premier, le code sera obligatoirement testable.
Le « TDD » apporte donc bien une solution aux problèmes posés par la rédaction des tests à postériori.

RDV AFUP du 11 juillet 2012 diapo 10

Une fois le code nécessaire à la bonne exécution du test rédigé, le développeur n’a plus qu’à exécuter le test une nouvelle fois afin de vérifier que c'est effectivement le cas.
Si tel n'est pas le cas, il lui faudra alors compléter ou corriger son code.

RDV AFUP du 11 juillet 2012 diapo 11

Et si le test s'exécute effectivement avec succès, alors, il peut soit remanier son code afin de l’optimiser et exécuter une nouvelle fois le test afin de vérifier que ses modifications n’ont pas introduit de régression, ou bien modifier ou enrichir le test pour qu'il ne s'exécute plus avec succès et recommencer autant de fois que nécessaire le cycle complet jusqu’à ce que le code ait le comportement voulu.
Nous venons donc de définir le TDD, et il est maintenant temps d’expliquer ce qu’est atoum au cours de la dizaine de minutes à venir.

RDV AFUP du 11 juillet 2012 diapo 12

Atoum est un framework dédié à la création et à l’exécution de tests unitaires.
Un test unitaire valide le fonctionnement de la plus petite unité de code d’un programme informatique.
Il s’agira par exemple de la méthode dans le cas d’un programme réalisé à l’aide de la programmation orientée objet, ou encore de la fonction dans le cas d’un logiciel développé à l’aide d’un langage procédural.
Son développement a débuté aux alentours de 2005 avant d’être rendu publique via Github en 2010 et il est présidé par trois valeurs fondamentales.

RDV AFUP du 11 juillet 2012 diapo 13

La première de ces trois valeurs est la simplicité.
Atoum doit être simple, aussi bien au niveau de son architecture que de son utilisation.
Son code suit donc le principe « KISS », son installation et sa configuration s’effectue très facilement, tandis que sa mise en œuvre ne nécessite que l’utilisation d’un seul et unique fichier.
La rédaction des tests est également très simple, car ils s’écrivent dans un langage quasi naturel au vocabulaire évolutif, et tout est fait à tous les niveaux pour qu'il soit simple à mettre en œuvre.

RDV AFUP du 11 juillet 2012 diapo 14

La seconde valeur fondamentale de atoum est la modernité.
Il nécessite en effet absolument PHP 5.3 pour fonctionner car il fait entre autre massivement appel aux espaces de noms ainsi qu'aux fonctions anonymes et aux fermetures lexicales, et il est parfaitement compatible avec PHP 5.4.
De plus, il est capable d’exécuter chaque test indépendamment des autres et même de les exécuter en parallèle afin d’optimiser les performances.
Atoum est également moderne au niveau de son code puisqu’il fait appel aux concepts objets « à la mode », et il est tout à fait possible de l’installer avec composer.
Enfin, sa modernité se manifeste également au niveau de son utilisation car il se démarque de la concurrence en proposant une façon d’écrire les tests très différente sur certains points.

RDV AFUP du 11 juillet 2012 diapo 15

Enfin, la dernière et troisième valeur fondamentale de atoum est l’intuition.
L’un des buts de atoum est en effet de se faire totalement oublier du développeur et donc que ce dernier n’est plus besoin de réfléchir consciemment à la façon de l’utiliser ou de rédiger un test.
Pour cela, une grande attention est portée au vocabulaire devant être utilisé à la fois pour mettre en œuvre atoum et pour rédiger les tests, de façon à ce que cela soit le plus simple, le plus logique et le plus cohérent possible.
De plus, atoum essaye également d’être intuitif en tentant de suppléer dans la mesure du possible aux erreurs de manipulation du développeur lorsque cela est pertinent, ou bien encore de l’aider dans son travail afin d'augmenter sa productivité.

RDV AFUP du 11 juillet 2012 diapo 16

Il est maintenant temps de voir de quelle façon tout cela se traduit concrètement durant la quarantaine de minutes à venir, et pour cela, nous allons commencer par l’installer afin de pouvoir l’utiliser.
Et pour cela, il existe plusieurs méthodes, à savoir Github, composer et l’archive PHAR.

RDV AFUP du 11 juillet 2012 diapo 17

L’installation de atoum via Github est tout ce qu’il y a de plus triviale puisqu’il suffit de cloner son dépôt pour pouvoir commencer immédiatement à l’utiliser.

RDV AFUP du 11 juillet 2012 diapo 18

L’installation de atoum via composer est également très simple puisqu’il suffit d’ajouter la dépendance correspondante au fichier « composer.json » pour pouvoir en bénéficier.

RDV AFUP du 11 juillet 2012 diapo 19

Enfin, il est possible de télécharger atoum sous la forme d’une archive PHAR utilisable directement. Cette dernière a de plus l’avantage de pouvoir se mettre à jour par elle-même, et même de permettre à l'utilisateur de revenir à une des précédentes versions si jamais une mise à jour pose problème.
Cependant, en contrepartie, atoum est moins rapide lors de l'exécution des tests lorsqu'il est utilisé dans ce format par rapport à une installation effectué via Github ou composer.

RDV AFUP du 11 juillet 2012 diapo 20

Maintenant que atoum est installé, nous allons voir comment écrire un test avec en appliquant la méthode « TDD » que nous avons vu précédemment, afin d’illustrer le langage pseudo naturel de atoum.

RDV AFUP du 11 juillet 2012 diapo 21

Dans un tout autre registre, atoum dispose d’un système de bouchonnage puissant, basé sur l’utilisation de fonctions anonymes et de fermetures lexicales.
Mais qu’est ce qu’un bouchon ?

RDV AFUP du 11 juillet 2012 diapo 22

Un bouchon permet de simuler le comportement d’une dépendance de la classe, afin de tester le comportement de ladite classe en fonction des différents comportements possibles de ses dépendances.
Concrètement, un bouchon, ou « mock », est donc un objet qui reprend l’API d’une dépendance mais dont le fonctionnement peut être défini arbitrairement par le développeur afin de pouvoir tester non seulement les cas ou tout va bien, mais aussi ceux ou tout va mal.

RDV AFUP du 11 juillet 2012 diapo 23

Nous venons donc de voir que les assertions de atoum sont bien à même de mimer plus ou moins le langage humain, ce qui permet d’écrire très simplement les tests et de les rendre plus lisibles et donc plus simple à maintenir.
Cependant, leur exécution est fastidieuse, puisqu’elle nécessite de recourir à un appel explicite au « runner » de atoum.
Or, il est très possible de se passer de cet appel explicite en incluant directement le « runner » dans notre fichier de test.
Il est alors toujours possible d’exécuter les tests en utilisant explicitement le « runner » de atoum, mais également en faisant exécuter directement le fichier de test par php .
Cerise sur le gâteau, dans ce dernier cas, l’ensemble des arguments du « runner » de atoum sont toujours utilisables, et nous allons maintenant voir que c’est très intéressant.
En effet, si l’« autorunner » permet de fluidifier le flux de production du développeur lorsqu’il travaille sur un fichier, la manipulation nécessaire pour lancer les tests reste tout de même fastidieuse puisqu’il faut dans le meilleur des cas récupérer la commande correspondante dans l’historique afin de l’exécuter à nouveau.

RDV AFUP du 11 juillet 2012 diapo 24

Or, il est également possible de s’affranchir de cette manipulation grâce au mode « loop », accessible via l’argument -l ou --loop.
Grâce à cet argument, atoum ne s’arrête pas lorsqu’il a fini d’exécuter les tests mais attend que l’utilisateur lui demande de les exécuter à nouveau en appuyant sur la touche « ⏎ ».

RDV AFUP du 11 juillet 2012 diapo 25

Atoum exécute alors à nouveau les tests, et vu qu’il est intuitif, si des tests n’étaient pas passés avec succès lors de l’itération précédente, il n’exécutera alors tout d’abord que ces derniers, afin de vérifier qu’ils passent maintenant avec succès.
Si ce n’est pas le cas, il se remettra alors en attente, et dans le cas contraire, il recommencera l’intégralité des tests dont l’exécution avait été demandée lors du lancement du mode « loop », car dans ce mode, atoum est tout à fait à même de lancer l’exécution de un ou plusieurs fichiers, en fonction des arguments qui lui sont passés en ligne de commande.

RDV AFUP du 11 juillet 2012 diapo 26

Il est en effet possible de demander à atoum d’exécuter les tests contenus dans un ou plusieurs fichiers précis, ou bien dans un ou plusieurs répertoires, respectivement à l’aide des arguments -f ou -d.
Il est également possible de « tagger » les méthodes de test grâce à l’annotation @tag et de n’exécuter que celles disposant des tags ad hoc, via l’argument -t.
Et il est également possible de n’exécuter qu’une méthode de test spécifique via -m , ou bien encore uniquement celles contenues dans un espace de nom particulier grâce à -ns.

RDV AFUP du 11 juillet 2012 diapo 27

Je viens de vous expliquer comment écrire des tests unitaires avec atoum et comment il est possible de les exécuter, mais je ne vous ai pas expliqué de quelle façon ils étaient exécutés.
Par défaut, afin de garantir qu’aucune méthode de test n’aura une influence sur le résultat de l’exécution des autres, atoum exécute chacune d’elle dans son propre processus php.
Chaque méthode est donc isolée des autres, et si d’aventure l’une d’entres elles génère une fuite de mémoire, cette dernière sera automatiquement colmatée par la fin du processus php correspondant.
De même, si l’une des méthodes de test provoque une erreur fatale ou un crash de PHP, cela ne remet pas en cause la bonne exécution des autres méthodes.
Cependant, en contrepartie de ces avantages, cette stratégie d’exécution des tests a un impact significatif sur les performances.

RDV AFUP du 11 juillet 2012 diapo 28

C’est la raison pour laquelle par défaut, atoum n’exécute pas les méthodes de test les unes à la suite des autres, mais parallèlement.
De cette façon, l’exécution des tests est très rapide malgré le fait qu’ils soient isolés, d’autant plus que cela permet d’exécuter les tests sur la totalité des cœurs physiques ou logiques présent sur la machine utilisée pour cela.
Mais encore une fois, il y a un prix à payer.
En effet, à cause de la parallélisation, il est possible que des accès concurrents apparaissent au cours de l’exécution des tests, si plusieurs tests font appels à la même ressource.
Pour résoudre le problème, atoum met à la disposition des développeurs des méthodes qui sont systématiquement appelées avant le début et après la fin de chaque suite de tests et méthode de test.
Cependant, il peut également être pertinent de ne pas exécuter une méthode de manière isolé, ou alors de le faire uniquement ponctuellement.

RDV AFUP du 11 juillet 2012 diapo 29

C'est la raison pour laquelle atoum permet au développeur de choisir, pour chaque méthode de test, le moteur qui sera utilisé pour l'exécuter, via l'annotation @engine applicable sur une classe ou une méthode de test.
Atoum propose pour le moment trois moteurs différents, ayant chacun des avantages et des inconvénients. Le moteur par défaut porte le nom de concurrent et permet à la fois d'isoler et de paralléliser les tests, comme nous venons de le voir.
Il s'agit du moteur par défaut car c'est celui qui offre le meilleur compromis entre la sécurité apportée par l'isolation des tests et les performances.
Le second moteur, qui porte quant à lui le nom de isolats, permet lorsqu'il est utilisé d'isoler le test qui le met en œuvre des autres, mais ne permet pas la parallélisation, et s'il s'agit du moteur le moins efficace en terme de performance, en contrepartie, il permet au développeur qui l'utilise de ne pas se soucier des problèmes de concurrence tout en bénéficiant de l'isolation des tests.
Enfin, le dernier moteur, nommé inline, est le plus performant, mais il n'offre aucune isolation.

RDV AFUP du 11 juillet 2012 diapo 30

Enfin, je vais vous parler des fichiers de configuration utilisés par atoum, car ils seront abordés dans la conférence qui va suivre et qui parle de son intégration avec Sonar.
Les fichiers de configuration de atoum ne sont pas au format ini, yaml ou xml mais sont des scripts PHP. En effet, atoum est utilisé par nature par des développeurs PHP, et c'est donc le format le plus simple pour eux à mettre en œuvre.
De plus, cela leur permet d'accéder à l'intégralité de l'API de atoum et de bénéficier de la puissance du langage en cas de besoin.
Par défaut, atoum recherche lorsqu'il démarre un fichier de configuration nommé .atoum.php dans chaque répertoire compris entre le sien et la racine du système de fichier, et il est également possible de définir un ou plusieurs fichiers de configuration différents à l'aide de l'argument -c.

RDV AFUP du 11 juillet 2012 diapo 31

Atoum souffre actuellement d'un manque de documentation en parti compensé par son aspect intuitif. Cependant, ce n'est pas suffisant et un certain nombre de ressources est donc disponible sur son wiki et répond aux problématiques les plus souvent rencontrées.

RDV AFUP du 11 juillet 2012 diapo 32

Le wiki est complété par une documentation rédigée par Gérald Croes et qui est disponible sur Github. Elle n'est pas exhaustive et sera complétée à plus ou moins court terme mais c'est tout de même une bonne base de départ, et toutes les contributions sont les bienvenues.

RDV AFUP du 11 juillet 2012 diapo 33

Cette conférence se termine maintenant et je vous remercie donc d'y avoir participé, ainsi que la société Elao pour son accueil et l'antenne lyonnaise de l'AFUP pour l'avoir organisée.

RDV AFUP du 11 juillet 2012 diapo 34

Je suis maintenant à votre disposition pour répondre à vos questions.

RDV AFUP du 11 juillet 2012 diapo 35