Mise en place de tests fonctionnels avec Zombie-js

Publié le Mis à jour le

Introduction

Dans le développement Web, il y a des bonnes pratiques qui ont tendance à ressortir, la mise en place de tests fonctionnels en fait partie. Les outils disponibles sont nombreux, qu’ils soient intégrés à un framework Web comme l’est la classe sfBrowser de Symfony ou via des outils tiers tels que Cucumber ou Selenium. De la même manière dans le monde de la science-fiction et du « pfiou, si cela pouvait se produire, on s’ennuierait beaucoup moins en ce dimanche pluvieux dans la banlieue de Dunkerque », on trouvera les zombies. Aujourd’hui nous allons parler d’un outil mélangeant les deux, j’ai nommé [Zombie-js->http://zombie.labnotes.org].

Cet article ne traite absolument pas des tenants et des aboutissants de la mise en place de tests fonctionnels au sein de votre application. Le sujet est beaucoup trop vaste alors nous allons partir du principe que vous êtes tous des développeurs connaissant un peu le sujet, ou le concept. Nous allons nous contenter de parler de Zombies sur un blog corporate, et c’est largement suffisant pour justifier un article!

Présentation

Insanely fast, headless full-stack testing using Node.js

Zombie-js est une bibliothèque pour nodejs qui apporte de nombreux avantages :

  • Tous d’abord, Zombie-js vous permet d’exécuter (et par extension, de tester) du code Javascript client sans avoir à lancer de navigateur. Pouvoir lancer l’exécution de ces tests d’une simple ligne de commande est tout simplement génial (sans être une innovation quelconque, soyons clairs).
  • Les suites de tests vont s’écrire en javascript, grâce à une API très bien pensée sur laquelle nous reviendrons tout de suite après. Si pour être efficace une suite de tests doit s’exécuter rapidement, elle ne doit pas être moins rapide à écrire pour autant.
  • Zombie permet d’atteindre des éléments de la page de différentes manières, que ce soit via le DOM de la page, un sélecteur CSS3 ou encore une instruction XPath.

Premiers pas

Zombie utilise node.js, un outil basé sur le moteur javascript V8 qui permet le développement d’applications serveur à l’aide de Javascript. Par son architecture et les bibliothèques qu’il met à disposition, les utilisations possibles sont très nombreuses et ne limitent pas à un fonctionnement requête-réponse. Les exemples sont nombreux sur le site officiel : serveur de chat, « monitoring » en temps réel, etc.

L’installation de node.js depuis les sources est très simple :


$ git clone https://github.com/ry/node.git
$ ./configure && make && make install

L’installation de Zombie quant à elle est un peu plus longue depuis les sources. Il est cependant possible de passer par npm, le gestionnaire de paquets pour node :


$ npm install zombie

Jusque là vous noterez que l’utilisation de nodejs et de zombie n’est pas bien compliquée et demeure accessible (j’ai pour ma part rencontré un problème lors de l’installation depuis les sources, ma version de npm était tout simplement obsolète).

Mise en place dans un cas concret

Voyons maintenant ce que Zombie peut faire pour nous, au travers d’une page basique.

Cette page contient un formulaire permettant de rentrer son login et son héros préféré. Lorsque l’on clique sur le bouton, le formulaire est soumis et un petit récapitulatif s’affiche. Devant la complexité d’un tel formulaire, vous comprendrez assez facilement la nécessité de mettre en place une série de tests fonctionnels.

Le premier test que nous allons mettre en place est de nous assurer que l’image contenant le logo de Clever Age possède bien un attribut alt, pour ce faire nous allons utiliser une bête assertion. Ce test va échouer puisque l’image n’a pas d’attribut alt.

var zombie = require(« zombie »);
var assert = require(« assert »);

new zombie.Browser({debug: true}).visit(« http://labo.local/perso/experiments/zombies-js/superhero/superhero.php », function(error, browser)
{
// does my image have an alt attribute ?
assert.ok(browser.querySelector(« div#logo img »).hasAttribute(« alt »));
});

Ce problème est très facile à corriger. Il est important de savoir que le composant assert est disponible nativement avec nodejs, et que seul le navigateur Zombie est utilisé pour accéder au composant image du formulaire. Maintenant que ce problème mineur est corrigé, nous allons pouvoir nous attaquer une vérification plus poussée de cette page, en simulant le remplissage et l’envoi du formulaire.

var zombie = require(« zombie »);
var assert = require(« assert »);

new zombie.Browser({debug: true}).visit(« http://labo.local/perso/experiments/zombies-js/superhero/superhero.php », function(error, browser)
{
// Let’s fill
browser
.fill(« Your Login », « Palleas »)
.select(« Your superhero name », « 4 »)
.pressButton(« Click me if you dare », function(error, browser)
{
assert.ok(browser.querySelector(« p#feedback »));
});
});

Vous pourrez constater que le code est vraiment simple :

  • Les différentes méthodes d’utilisation de la page (remplissage, click, selection d’une option dans une liste) permettent de se succéder simplement grâce au chainage des méthodes : fill().select().pressButton()...
  • La manière d’atteindre l’élément de la page est également très intéressante. Alors que nous parlions d’utiliser un sélecteur CSS3, une instruction XPath ou encore naviguer dans le DOM, il est possible de se baser sur le contenu du label ou le texte du bouton de l’élément de formulaire ciblé.

Enfin, la méthode pressButton() prend comme deuxième paramètre une fonction de callback qui sera appelée lorsque la nouvelle page aura été chargée. La suite – c’est à dire le test effectué – se déroule de la même manière que précédemment, via une simple instruction d’assertion.

Conclusion

Les possibilités offertes par Zombie sont encore plus larges : il serait, par exemple, possible de rendre le formulaire un peu plus réactif à l’aide d’une requête XMLHTTPRequest – que le navigateur Zombie gère parfaitement. Ce qu’il faut retenir de cet outil, c’est qu’il est vraiment prometteur et propose une philosophie vraiment « décontractée ». On notera que son fonctionnement, décrit dans des parties nommées « hunting », « walking » et « feeding », devrait aider dans son adoption.