af83

Testez votre code Node.js avec Vows

Node.js permet d'écrire de manière relativement simple du code asynchrone mais quand il s'agit de tester ce code, les choses se compliquent. Heureusement, il existe un framework de tests asynchrones pour Node.js : Vows. Et il a en plus le bon goût d'avoir des fonctionnalités très sympathiques. Mais commençons par le début :

Pourquoi tester son code ?

Il y a les raisons habituelles :

  1. Les études montrent que les tests unitaires permettent de réduire significativement le nombre de bugs ;
  2. Les développeurs qui ont essayé le BDD (une méthode qui consiste à écrire un test qui échoue puis à écrire le code minimal qui permet de faire passer ce test) considèrent que cela améliore leur productivité ;
  3. La présence de tests pour un programme favorise sa maintenance et ses évolutions.

Mais il existe aussi une raison propre aux applications et bibliothèques écrites avec Node.js. Node.js est encore jeune et son API évolue encore assez rapidement. Si vous souhaitez réutiliser votre code Node.js dans quelques mois avec une version plus récente, vous allez probablement devoir faire quelques adaptations. Sans tests, il vous faudra beaucoup de courage pour trouver où faire ces modifications et être confiant que vous n'avez pas introduit de régressions. Alors qu'avec des tests, cela se fait très facilement.

Quel outil pour écrire des tests ?

Une fois convaincu par l'importance des tests, vous allez sûrement essayé d'en écrire. Et là, vous allez vous rendre compte que ce n'est pas toujours aussi simple que cela en a l'air, notamment pour tester des comportements asynchrones.

L'utilisation d'un framework vous guide lors de l'écriture de tests et simplifie leur utilisation. Par exemple, pouvoir découper ses tests en plusieurs suites ou pouvoir lancer un seul test sont des fonctionnalités qui peuvent sembler accessoires mais qui vont rapidement vous faire gagner du temps. Si un test échoue sporadiquement, pouvoir le lancer unitairement permet de vérifier que le problème ne vient pas de la concurrence avec un autre test.

Je recommande donc d'utiliser un framework pour écrire ses tests et plus spécifiquement Vows. J'ai utilisé d'autres frameworks par le passé, comme Jasmine mais je trouve que Vows est un cran au-dessus :

  • son approche me paraît plus claire ;
  • son site web est très réussi et l'aide que l'on peut y trouver est très utile ;
  • la sortie en console du résultat des tests est agréable et permet de voir en clin d'oeil les informations importantes.

Écrire ses premiers tests

Nous avons de bonnes raisons d'écrire des tests et un framework, il est temps de s'y mettre. Voici à quoi ressemble un test :

    var vows = require('vows'),
        assert = require('assert'),
        DeepThought = require('deep_thought');

    vows.describe('Deep Thought').addBatch({
        'An instance of DeepThought': {
            topic: new DeepThought,

            'should know the answer to the ultimate question of life': function (deepThought) {
                assert.equal(deepThought.question('what is the answer to the universe?'), 42);
            }
        }
    }).export(module);

Les 3 premières lignes servent à charger les modules, du très classique avec Node.js. Ensuite, nous créons une suite de tests avec vows.describe('Deep Thought'). On a généralement une suite de tests par fichier et le fichier porte le nom de ce qui est testé, deep_thought_spec.js dans notre cas.

On ajoute un batch à cette suite de tests, à l'intérieur duquel on va retrouver des contextes. Chaque contexte se compose d'un sujet (le topic), l'objet du test, et d'un ou plusieurs voeux (vows).

Vows va créer le sujet, puis le passer en argument à chacun des voeux. Ceux-ci peuvent alors vérifier des assertions sur le résultat. Ici, on utilise assert.equal pour vérifier que le résultat est bien la valeur attendue.

Enfin, à la dernière ligne, on fait un export(module) pour que vows puisse bien accéder à cette suite depuis l'extérieur.

Et maintenant pour lancer notre suite de tests, il ne nous reste plus qu'à taper vows test/deep_thought_spec.js en ligne de commande.

Et maintenant de l'asynchrone !

Vows permet d'aller plus loin. Les contextes imbriqués, par exemple, permettent d'organiser nos tests. La manière dont Vows gère l'asynchrone est également intéressante. Bien que très simple sur le principe (une fonction de callback à appeler quand on a fini nos traitements) , cela permet de gérer tous les cas. Voyons un exemple :

    {
        topic: function () {
            fs.stat('~/FILE', this.callback);
        },
        'can be accessed': function (err, stat) {
            assert.isNull   (err);        // We have no error
            assert.isObject (stat);       // We have a stat object
        },
        'is not empty': function (err, stat) {
            assert.isNotZero (stat.size); // The file size is > 0
        }
    }

Le sujet n'est plus un objet, mais une fonction. Celle-ci va être appelée par Vows et charge à elle, d'appeler this.callback quand elle aura fini ses traitements, synchrones ou asynchrones. Les arguments passés à cette fonction sont transmis aux voeux pour que ceux-ci puissent faire leurs vérifications.

À noter, il est recommandé de suivre la convention de Node.js pour les fonctions de callback et de passer err en premier paramètre. Si celui-ci est null, tout s'est bien passé, sinon, il contient un message d'erreur.

Conclusion

Pour finir, j'espère que cet article vous a donné envie d'essayer Vows. Cette introduction est loin d'être exhaustive, vous pourrez trouver beaucoup plus d'informations sur le site officiel. Et n'hésiter pas à contribuer au code de Vows.

blog comments powered by Disqus