Logo JavaScript

Tests unitaires en JavaScript

Flattr this!

JavaScript souffre d'une très mauvaise réputation auprès de beaucoup de développeurs/décideurs/gens en général. Pourtant il dispose de bien des qualités que j'espère ne plus avoir à présenter et à défendre. Parmi ces qualités, les outils de tests unitaires. Voilà une liste d'outils que j'ai compilé pour vous :

QUnit

QUnit est le framework de tests unitaires développé par l'équipe de jQuery et qui naturellement est plus qu'adapté à tester vos scripts jQuery. A titre personne, j'aime bien et donc le recommande vivement.

Documentation : http://docs.jquery.com/QUnit
Github : http://github.com/jquery/qunit
Planning de développement : http://jquerytes[...]rontPage

Exemple

Tiré de la documentation :

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <link rel="stylesheet" href="http://code.jquery.com/qunit/git/qunit.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://code.jquery.com/qunit/git/qunit.js"></script>

  <script>
  $(document).ready(function(){

test("a basic test example", function() {
  ok( true, "this test is fine" );
  var value = "hello";
  equal( value, "hello", "We expect value to be hello" );
});

module("Module A");

test("first test within module", function() {
  ok( true, "all pass" );
});

test("second test within module", function() {
  ok( true, "all pass" );
});

module("Module B");

test("some other test", function() {
  expect(2);
  equal( true, false, "failing test" );
  equal( true, true, "passing test" );
});

  });
  </script>

</head>
<body>
  <h1 id="qunit-header">QUnit example</h1>
 <h2 id="qunit-banner"></h2>
 <div id="qunit-testrunner-toolbar"></div>
 <h2 id="qunit-userAgent"></h2>
 <ol id="qunit-tests"></ol>
 <div id="qunit-fixture">test markup, will be hidden</div>
</body>
</html>

 

Résultat

jQuery Qunit

jQuery Qunit

Par défaut, tous les résultats sont présents. Les tests réussis sont repliés pour mettre en avant les tests échoués.

Mockjax

Ce plugin jQuery a fait du mockup de requêtes Ajax sa spécialité. Pour faire simple, il vous permet de tester aisément le comportement de votre application Ajax en fonction des réponses que lui fera le serveur sans avoir besoin d'un serveur disponible. Je crois que l'exemple sera plus parlant. Chose importante à noter, il est particulièrement simple à utiliser et vous pouvez indiquer le temps de réponse du "serveur".

Documentation : http://enterprisejqu[...]elopment/
Github : https://github.com/appendto/jquery-mockjax

Exemple

$.mockjax({
  url: '/restful/fortune',
  responseTime: 750,
  responseText: {
    status: 'success',
    fortune: 'Are you a turtle?'
  }
});

 

Et nous allons donc tester ceci :

$.getJSON('/restful/fortune', function(response) {
  if ( response.status == 'success') {
    $('#fortune').html( 'Your fortune is: ' + response.fortune );
  } else {
    $('#fortune').html( 'Things do not look good, no fortune was told' );
  }
});

Résultat

Ce qui bien entendu affichera "Your fortune is: Are you a turtle?". Cet exemple est tiré de la documentation officielle.

JS Test

Là on va parler du framework de tests maison de Google. Rien que ça. D'ailleurs il a été régulièrement critiqué sur le net. Je serai tenté de dire à tort et par des obtus d'esprit mais on va dire que je veux relancer la polémique. Ce qui lui est essentiellement reproché est de ne pas pouvoir accéder au DOM, ni à window et document puisqu'il s'exécute via V8 directement sans passer par un navigateur, même si c'est possible. A réserver donc aux applications serveurs ou aux tests de prototypes.

Documentation : http://code.google.com/p/google-js-test/
Téléchargement : http://code.google.com/p/google-js-test/downloads/list

Exemple

function UserInfoTest() {
  // Each test function gets its own instance of UserInfoTest, so tests can
  // use instance variables to store state that doesn't affect other tests.
  // There's no need to write a tearDown method, unless you modify global
  // state.
  //
  // Create an instance of the class under test here, giving it a mock
  // function that we also keep a reference to below.
  this.getInfoFromDb_ = createMockFunction();
  this.userInfo_ = new UserInfo(this.getInfoFromDb_);
}
registerTestSuite(UserInfoTest);

UserInfoTest.prototype.formatsUSPhoneNumber = function() {
  // Expect a call to the database function with the argument 0xdeadbeef. When
  // the call is received, return the supplied string.
  expectCall(this.getInfoFromDb_)(0xdeadbeef)
    .willOnce(returnWith('phone_number: "650 253 0000"'));

  // Make sure that our class returns correctly formatted output.
  expectEq('(650) 253-0000', this.userInfo_.getPhoneForId(0xdeadbeef));
};

UserInfoTest.prototype.returnsLastNameFirst = function() {
  expectCall(this.getInfoFromDb_)(0xdeadbeef)
    .willOnce(returnWith('given_name: "John" family_name: "Doe"'));

  // Make sure that our class puts the last name first.
  expectEq('Doe, John', this.userInfo_.getNameForId(0xdeadbeef));
};

Résultat

[ RUN      ] UserInfoTest.formatsUSPhoneNumber
[       OK ] UserInfoTest.formatsUSPhoneNumber
[ RUN      ] UserInfoTest.returnsLastNameFirst
user_info_test.js:32
Expected: 'Doe, John'
Actual:   'John Doe'
[  FAILED  ] UserInfoTest.returnsLastNameFirst
[ RUN      ] UserInfoTest.understandsChineseNames
[       OK ] UserInfoTest.understandsChineseNames

Cet exemple est tiré lui aussi de la documentation officielle.

Sinon.js

Ce framework pourtant pas très récent (quand même déjà une bonne année de présence sur Github) ne fait parler vraiment de lui que depuis peu de temps. Et ceci pour la bonne raison que même si il peut fonctionner seul, il propose aussi des adapters pour travailler avec d'autres frameworks de tests unitaires. Même si je trouve sa syntaxe bien moins claire, la maîtriser permet de n'avoir à en apprendre qu'une seule pour tester aussi bien vos devs jQuery que node.js.

Adapters disponibles pour :

  • QUnit : voir plus haut ;
  • qooxdoo : framework JS (voir lien) ;
  • Jasmine BDD : framework JS de Behavior Driven Development, n'étant pas du tout au point sur Agile, je ne vais rien dire plutôt que de dire une ânerie (voir lien) ;
  • nodeunit : voir plus bas ;

Documentation : http://sinonjs.org/docs/
Github : https://github.com/cjohansen/Sinon.JS

Exemple

Pour le coup, je n'en mets pas parce que je n'ai rien de simple et clair à proposer. Désolé.

nodeunit

Je termine avec un framework de tests unitaires pour NodeJS.

Github : https://github.com/caolan/nodeunit

Exemple

Comme pour Jasmine BDD, je ne maîtrise pas encore assez NodeJS pour m'étendre dessus sans prendre le risque de dire une grosse bêtise. Je laisse les intéressés découvrir.

Conclusion

Le développeur JS dispose d'une panoplie assez riche d'outils pour tester ses développements. Un point de plus où les trolls anti-JS perdent encore leur crédibilité. Bien évidement cette liste n'est que pour vous présenter ces outils et vous éveiller l'esprit à ce sujet. J'ai bien l'intention de vous faire des articles plus détaillés prochainement, peut être pas sur chacun mais au moins sur QUnit et Mockjax.

Flattr this!

A propos de Mathieu

Ingénieur développeur web dans la vente par correspondance B2B, adepte de nouvelles technologies et d'innovation. Vous pouvez aussi me retrouver sur Twitter @mathrobin
Cette entrée a été publiée dans JavaScript, avec comme mot(s)-clef(s) , , , , , , , , , , , . Vous pouvez la mettre en favoris avec ce permalien.
  • DrBenton

    En ce qui me concerne j’utilise Vows (https://github.com/cloudhead/vows), mais pour Node.js on a un choix très étendu, avec plusieurs dizaines de bibliothèques pour les tests unitaires :-) :
    > https://github.com/joyent/node/wiki/modules#wiki-testing
    Certaines sont compatibles avec des tests Javascript coté client.

    • http://www.mathieurobin.com/ Mathieu

      Intéressant effectivement. Je n’aurais pas pu en parler plus que ça ceci dit, vu que je ne le connais pas. A l’occasion, il serait pas mal que je me penche dessus.

  • http://www.pure-tentation.fr/ Syndrael

    Un point qu’on oublie trop souvent les tests.. Dur de parer à la réplique: Un bon développeur fait du code qu’on n’a pas besoin de tester..
    Quant aux décideurs, ils ne connaissent pas Javascript, et n’ont pas besoin de le connaître, ils se mettraient à poser trop de questions.. LOL !!
    Déja du mal à imposer le PRINCIPE de tests unitaires, et surtout faire comprendre qu’à chaque modifs il faut retester..
    S.

    • http://www.mathieurobin.com/ Mathieu

      Ce type de management irresponsable est, je l’espère sincèrement, voué à disparaître. Mais concernant les décideurs, connaître l’existence de Javascript pourrait être bien au contraire un plus. A condition qu’on les éduque correctement dès le début et non pas avec le classique « ça permet de faire des contrôles de formulaires et des animations ». Qui était vrai au tout début, mais bon, c’était il y a 20 ans.

Articles liés