Vous avez déjà regroupé vos tests de manière logique, mais comment est-ce que vous pouvez comparer les valeurs que votre code sort par rapport aux valeurs attendues ?
On appelle cette fonctionnalité une assertion ("expectation" en anglais). Jasmine propose des assertions/expectations très utiles. Vous avez également la possibilité d'écrire des assertions personnalisées lorsqu'un projet demande des assertions spécifiques qui ne se trouvent pas par défaut dans la configuration de Jasmine !
Les attentes
Similaire à describe
et it
, Jasmine dispose d'une autre fonction qui s'appelle expect
.
Vous avez décrit ce qui "doit" se passer dans votre bloc it (ex. votre code "démarre la lecture de la vidéo automatiquement") mais vous n'avez pas intégré cette attente dans un vrai test de code.
Nous avons vu que describe
prend deux arguments : une chaîne de caractères et une fonction. it
prend également deux arguments : une chaîne et une fonction.
expect
ne prend qu'un seul argument : la valeur réelle. La valeur réelle est la valeur que vous testez. Il peut s'agir d'une variable, d'une valeur numérique (integer), d'un booléen, d'un tableau (array), etc.
Si l'on reprend l'exemple du lecteur vidéo que vous avez vu précédemment, ce que l'on attend c'est que la lecture de la vidéo démarre automatiquement, n'est-ce pas ? C'est ce que vous voulez !
Voici comment vous écrirez le résultat attendu (regardez les lignes 4 et 9) :
describe("Video player", function() {
describe("when the page loads", function() {
it("should automatically play the video", function() {
expect(videoPlaying).toBe(true);
};
});
describe("when user clicks the play button", function() {
it("should play the video", function() {
expect(videoPlaying).toBe(true);
};
});
});
Qu'est-ce que c'est, le toBe()
à la fin ?
Bonne question ! Regardons le complément important aux attentes : les matchers.
Les matchers
Un matcher compare une valeur réelle avec une valeur attendue.
Voici une métaphore concrète : vous passez un test à l'école. ✏️ Le professeur qui corrige votre test comparera votre réponse à la réponse attendue. Si vous avez répondu "A", et que la réponse attendue était "A", vous avez réussi cette question, car c'est la bonne réponse ! Si vous avez répondu "A", et que la réponse attendue était "B", vous avez raté cette question, car ce n'est pas la bonne réponse.
Et bien, c'est la même chose lorsque vous testez votre code : vous comparez deux valeurs selon un critère défini qui définit les bonnes et les mauvaises réponses.
Ce qu'il y a de bien avec Jasmine, c'est que cet outil contient déjà en natif de nombreux matchers. Avec ces matchers, vous pouvez tester si :
deux choses sont égales (ou non).
quelque chose est vrai (ou non).
quelque chose est défini (ou non).
une valeur est supérieure à une autre valeur (ou inférieure à une valeur).
si une erreur se produit (ou non).
et plus encore !
C'est évident, les matchers sont très utiles. Ils vous permettent de comparer deux valeurs pour voir si ce qui doit se passer -- se passe !
La syntaxe des matchers
Voici les matchers inclus par défaut dans Jasmine. Lisez chaque matcher et essayez de deviner ce qu'il fait :
expect(fn).toThrow(e);
expect(instance).toBe(instance);
expect(mixed).toBeDefined();
expect(mixed).toBeFalsy();
expect(number).toBeGreaterThan(number);
expect(number).toBeLessThan(number);
expect(mixed).toBeNull();
expect(mixed).toBeTruthy();
expect(mixed).toBeUndefined();
expect(array).toContain(member);
expect(string).toContain(substring);
expect(mixed).toEqual(mixed);
expect(mixed).toMatch(pattern);
Les matchers sont assez faciles à lire de gauche à droite. Par exemple, la ligne de code expect(5).toBeLessThan(6);
ressemble beaucoup à une phrase en anglais. "I expect 5 to be less than 6." C'est pareil !
Vous pouvez également tester un résultat négatif avec ces matchers. Pour tester un cas négatif, vous devez écrire expect(6).not.toBeLessThan(6);
. Il suffit d'enchaîner un not
avant le matcher lui-même.
Comme vous l'avez vu dans le dernier chapitre sur les suites et les spécifications, choisir un matcher sera plus facile si, pendant votre processus BDD, vous avez déjà fait un bon travail en définissant les comportements que vous cherchez à produire.
Exemple de bowling
Revenons à notre fameux exemple bowling. Ouvrez votre fichier BowlingGameSpec.js si vous l'avez fermé après le dernier chapitre. Voici où on était :
describe("Bowling game", function() {
it("should properly calculate a gutter game", function() {
// test
});
it("should properly calculate a strike", function () {
// test
});
it("should properly calculate a spare", function () {
// test
});
});
On avait défini des specs qui vont contenir les tests eux-mêmes. Maintenant, on peut définir nos attentes.
Lancer une balle
Un joueur lance deux fois par tour, et il a le droit à 10 tours dans le match (donc 20 lancers au total) ; n'est-ce pas ? Disons qu'à chaque tour, il ne touche aucune quille.
C'est un scénario à tester ! Je l'ajoute à la première specification :
it("should properly calculate a gutter game", function() {
rollMany(20, 0);
expect(game.score()).toEqual(0);
});
D'où viennent ces nouvelles fonctions (rollMany(), game.score, etc) ?
Je les ai inventées, elles n'existent pas dans le code pour le moment !
Maintenant que vous avez rempli le test -- même si on n'a pas encore écrit le code correspondant -- nous pouvons imaginer le code que nous devons écrire pour faire passer ce test.
Voyons comment le faire dans le prochain chapitre.