Après avoir eu une barre verte en tests unitaires javascript, j'ai eu besoin d'aller plus loin : nous réalisons une application HTML5, or cette application tourne au sein d'un navigateur, et utilise jQuery.

Je me suis tourné alors vers JsTestDriver. Son fonctionnement est différent des autres outils de test : il utilise de vrais navigateurs "esclaves". Il lance un petit serveur http, puis les navigateurs sur une url pointant vers ce serveur qui va déclencher les tests.

Il faut définir dans un fichier jsTestDriver.conf (que j'ai mis sous src) où sont situés les fichiers source :

server: http://localhost:9876
load:
  - main/js/*.js
  - test/js/*.js

Un test s'écrit alors comme cela :

TestCase("MonTest", {
    setUp: function() {...} // pas obligatoire
    tearDown: function {...} // idem

    "test ajoute bonjour avec jQuery": function() {
        /*:DOC += 
*/ ajouteBonjourAuContenu(); assertEquals("

bonjour, le monde!

", jQuery("#contenu").html()); } });

Attention, les intitulés doivent commencer par "test" sinon ils ne sont pas reconnus par JsTestDriver. On lance le test avec la ligne de commande suivante :

java -jar JsTestDriver-1.3.2.jar --port 9876 --browser /usr/bin/firefox --tests all
.E
Total 1 tests (Passed: 0; Fails: 0; Errors: 1) (1,00 ms)
  Firefox 5.0 Linux: Run 1 tests (Passed: 0; Fails: 0; Errors 1) (1,00 ms)
    MonTest.test jQuery error (1,00 ms): ReferenceError: ajouteBonjourAuContenu is not defined
      ()@http://localhost:9876/test/test/js/mon_test.js:26

Tests failed: Tests failed. See log for details.
$ echo $?
1

En implémentant le code :

function ajouteBonjourAuContenu() {
        jQuery("#contenu").append("

bonjour, le monde!

"); }
$ ./run_tests.sh 
..
Total 1 tests (Passed: 1; Fails: 0; Errors: 0) (1,00 ms)
  Firefox 5.0 Linux: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (1,00 ms)
$ echo $?
0

On peut voir que la valeur de retour vaut 1 lorsque les tests échouent et 0 lorsqu'ils réussissent.

Ce que j'ai aimé avec cet outil :

  • prêt à l'emploi, je n'ai pas eu à modifier le code pour pouvoir le faire fonctionner
  • en ligne de commande
  • l'API (les assert*, la manière de déclarer des tests) très complète, et simple à utiliser
  • peut lancer les tests sur plusieurs navigateurs ou versions de navigateur
  • automatisable avec Jenkins/Hudson
  • facilement configurable en lui précisant où se trouvent les fichiers javascript (code prod et test)

L'inconvénient principal que je vois c'est qu'il lance réellement les navigateurs (et les ferme):

  • c'est relativement lent pour lancer la suite, mais paraît-il qu'après c'est très rapide. Il faudrait voir ce que ça donne avec un grand nombre de tests
  • cela demande un environnement graphique : sur un serveur jenkins c'est pas forcément nécessaire

PS : Mon idée avant JsTestDriver, c'était de continuer avec QUnit, en ajoutant l'environnement du navigateur, avec envjs. Envjs, comme expliqué dans cet article permet d'avoir un objet window, et de l'utiliser avec le DOM. Je suis parvenu à faire fonctionner jQuery et l'application comme dans l'article de John Resig, mais impossible de l'automatiser. J'avoue aussi être novice en javascript, je pense que ça doit être possible de faire ce qui est montré en ligne de commande dans un test, mais je n'y suis pas arrivé.