Il existe des dizaines de frameworks de test JavaScript, mais la plupart d'entre eux fonctionnent plus ou moins de la même manière. JSCheck de Douglas Crockford diffère toutefois beaucoup des autres. Dans ce tutoriel, je vais vous montrer en quoi c'est différent et pourquoi vous devriez envisager de l'utiliser!
Crockford décrit JSCheck comme un «outil de test basé sur les spécifications.
Crockford décrit JSCheck comme un «outil de test piloté par la spécification». Lorsque vous utilisez les frameworks auxquels vous êtes habitué, vous écrivez un test pour une fonctionnalité donnée et, si ce test réussit, déclarez que la fonctionnalité donnée fonctionne correctement. . Cependant, il est possible que vous manquiez des cas extrêmes ou des exceptions non couvertes par vos tests..
Découvrir JSCheck n’a pas pour seul objectif de révéler des cas extrêmes, c’est un avantage supplémentaire intéressant. L'idée principale derrière JSCheck est la suivante: la spécification que vous écrivez décrira réellement le fonctionnement du code que vous testez. Ensuite, JSCheck prendra cette spécification (appelée un prétendre dans JSCheck-lingo), et générer des tests aléatoires pour prouver l’affirmation. Enfin, il vous rapportera les résultats.
Ça semble intéressant? Continuer à lire! Sonne familier? Vous avez peut-être utilisé l'outil de test Haskell, QuickCheck, sur lequel JSCheck était basé..
Bien sûr, avant d'écrire notre revendication, nous voudrons avoir du code à tester. Récemment, j'ai écrit un indicateur de mini-mot de passe, semblable à la fonctionnalité de HowSecureIsMyPassword.net. Ce n'est vraiment pas compliqué: il suffit de passer un mot de passe à la fonction et d'obtenir un score. Voici le code:
(function () var PasswordScorer = ; PasswordScorer.score = fonction (mot de passe) var len = mot_passe.length, lengthScore = 0, letterScore = 0, caractères = if (len> = 21) lengthScore = 7 ; else if (len> = 16) lengthcore = 6; else if (len> = 13) lengthcore = 5; else if (len> = 10) lengthScore = 4; else if (len> = 8) lengthScore = 3; else if (len> = 5) lengthScore = 2; var re = [null, / [az] / g, / [AZ] / g, / \ d / g, / [ ! @ # $% \ ^ & \ * \ (\) = _ + -] / g]; pour (var i = 1; i < re.length; i++) letterScore += (password.match(re[i]) || []).length * i; return letterScore + lengthScore; ; (typeof window !== 'undefined' ? window : exports).PasswordScorer = PasswordScorer; ());
C'est un code assez simple, mais voici ce qui se passe: le score est composé de deux sous-scores. Il y a un score de départ, basé sur la longueur du mot de passe, puis un score supplémentaire pour chaque caractère, 1 point pour chaque lettre minuscule, 2 points pour chaque lettre majuscule, 3 points pour chaque chiffre et 4 points pour chaque symbole ( à partir d'un ensemble limité).
C’est donc le code que nous allons tester: nous allons générer de manière aléatoire des mots de passe avec JSCheck et nous assurerons qu’ils obtiennent un score approprié..
Nous sommes maintenant prêts à rédiger nos revendications. Tout d'abord, allez sur la page JSCheck Github et téléchargez le jscheck.js
fichier. J'aime exécuter mes tests dans le terminal, via NodeJS, alors ajoutez cette ligne au bas du fichier:
(typeof window! == 'undefined'? window: exports) .JSC = JSC;
Cela n'affectera en rien le comportement du fichier dans le navigateur, mais le fera fonctionner comme un module dans Node. Notez que le jscheck.js
fichier expose JSC
comme variable globale unique pour l'ensemble de la bibliothèque. Si nous n’effectuions pas cet ajustement, c’est ainsi que nous y accéderions.
Ouvrons passwordScorerSpec.js
et commencer les choses:
JSC = require ("./… /vendor/jschec";).JSC; PasswordScorer = require ("./… /lib/passwordScore";).PasswordScorer;
Comme je lance ces tests dans NodeJS, nous aurons besoin des modules que nous voulons. Bien sûr, vous voudrez vous assurer que les chemins correspondent à vos emplacements de fichiers.
Nous sommes maintenant prêts à rédiger notre première revendication. Bien sûr, nous utilisons le JSC.claim
méthode. Cette méthode accepte trois paramètres, avec un quatrième facultatif. Le premier paramètre est juste une chaîne, un prénom pour la réclamation. Le deuxième paramètre est appelé le prédicat: c'est la fonction de test réelle. Très simplement, cette fonction devrait revenir vrai
si l'affirmation est vraie, et faux
si l'affirmation est fausse. Les valeurs aléatoires que JSCheck générera pour le test seront transmises en tant que paramètres au prédicat.
Mais comment JSCheck sait-il quel type de valeurs aléatoires est attribué au prédicat? C'est là que le troisième paramètre, le spécificateur entre en jeu. Ceci est un tableau, avec un élément pour chaque paramètre de prédicat. Les éléments du tableau spécifient les types à donner au prédicat, à l'aide des fonctions de spécification de JSCheck. En voici quelques unes:
JSC.boolean ()
renvoie vrai ou faux.JSC.character ()
prend un caractère min et max et retourne un seul caractère de cette plage. Il peut également prendre un code de caractère unique et renvoyer ce caractère.JSC.integer ()
retournera un nombre premier. Ou bien, transmettez-lui un seul paramètre pour obtenir un entier (nombre entier) compris entre 1 et le paramètre, ou deux paramètres pour un entier compris dans cette plage..Vous avez eu l'idée. Il y a d'autres spécificateurs, et nous en utiliserons maintenant lorsque nous rédigeons notre première revendication.
JSC.claim ("Tous les mots de passe en minuscules" ;, fonction (mot de passe, maxScore) return PasswordScorer.score (mot de passe) <= maxScore; , [ JSC.string(JSC.integer(10, 20), JSC.character('a', 'z')), JSC.literal(26) ]);
Notre premier paramètre est un nom. La seconde est la fonction de test: elle reçoit un mot de passe et un score maximal, et renvoie true si le score de ce mot de passe est inférieur ou égal au score maximal. Ensuite, nous avons notre tableau de spécificateurs. Notre premier paramètre (le mot de passe) doit être une chaîne, nous utilisons donc le JSC.string ()
méthode: il peut prendre deux paramètres, le nombre de caractères de la chaîne et la valeur de ces caractères. Comme vous pouvez le constater, nous vous demandons un mot de passe de 10 à 20 caractères. Pour la valeur, nous utilisons le JSC.characters ()
méthode pour obtenir des caractères aléatoires entre 'a' et 'z'.
La prochaine valeur est notre maxScore
paramètre. Parfois, nous ne voulons pas du hasard que propose JSCheck, et c’est un de ces moments. Voilà pourquoi il y a JSC.literal
: passer une valeur littérale au prédicat. Dans ce cas, nous utilisons 26, qui devrait être le score maximal pour tout mot de passe en minuscule compris entre 10 et 20 caractères..
Maintenant nous sommes prêts à faire le test.
Avant de traiter la réclamation et d’obtenir le rapport, nous devons configurer la fonction qui recevra le rapport. JSCheck passe le rapport à une fonction de rappel de JSC.on_report
. Par conséquent:
JSC.on_report (function (str) console.log (str););
Rien d'extraordinaire. Maintenant, tout ce qui reste est d'appeler JSC.check ()
. Maintenant, nous pouvons nous diriger vers notre terminal et lancer ceci:
chemin du noeud / to / passwordScorerSpec.js
En coulisse, JSCheck exécute le prédicat 100 fois, générant différentes valeurs aléatoires à chaque fois. Vous devriez voir votre rapport imprimé.
Tous les mots de passe en minuscule 100 sur 100 passent 100
Ils ont tous passé, mais ce n'est pas vraiment un rapport, hein? Eh bien, si l'un de nos tests avait échoué, il aurait été inclus dans le rapport. Cependant, vous pouvez ajuster le niveau de sortie avec JSC.detail
fonction: donnez-lui un nombre compris entre 0 et 4 (inclus) pour ne rien obtenir sans sortie vers tous les cas de test. La valeur par défaut est 3.
Rappelez-vous comment j'ai dit ça JSC.claim
pourrait prendre un quatrième paramètre? Ça s'appelle un classificateur, et il reçoit les mêmes paramètres que le prédicat. Ensuite, il peut retourner une chaîne pour classifier ou grouper nos cas de test. J'admets que je ne savais pas vraiment où cela pourrait être utile avant de créer l'exemple de revendication ci-dessus. Voir, j'ai fait une erreur dans le prédicat et comparé le score à la maxScore
avec le opérateur au lieu de
opérateur, donc tous les mots de passe qui ont marqué 26 points ont échoué. Je voyais des rapports qui ressemblaient à ceci:
FAIL [21] ("nhgkznldvoenhqqlf"); ;, 26) réussir 96 échec 4
La raison pour laquelle certains tests échouent n’est toujours pas tout à fait évidente. J'ai donc ajouté une fonction de classificateur qui regroupe les cas de test par score: comme je l'ai dit, la fonction prend les mêmes paramètres que le prédicat et renvoie une chaîne. Tous les cas de test qui récupèrent la même chaîne du classificateur seront regroupés dans le rapport..
fonction (mot de passe, maxScore) return PasswordScorer.score (mot de passe) + "points" ;;
Cette fonction devrait être le dernier paramètre de notre revendication. Maintenant, vous aurez un rapport qui ressemble à ceci:
Tous les mots de passe en lettres minuscules 96 sur 100 ÉCHEC [4] 26 points :( "illqbtiubsmrhxdwjfo";, 26) ÉCHEC [22] 26 points :( "gruvmmqjzqlcyaozgf";, 26) ÉCHEC [34] 26 points :( "chhbevwtjvslprqcjjsjvs"; ) FAIL [65] 26 points :( "kskqdjhtonybvfewdjm";, 26) 14 points: passer 8 15 points: réussir 5 16 points: passer 12 16 points: passer 10 19 points: passer 12 20 points: passer 11 22 points: passer 12 23 points: passe 8 24 points: passe 10 25 points: passe 8 26 points: passe 0 échec 4
Vous pouvez voir comment les tests sont regroupés selon le nombre de points que valent les mots de passe. Maintenant, il est facile de voir que les seuls mots de passe qui échouent aux tests sont les mots de passe qui marquent 26 points. Et bien que le problème concerne le test, et non le code, il montre quand même l’utilité d’ajouter une fonction de classificateur à vos revendications..
Donc, à la fin de la journée, JSCheck vaut-il la peine d’être utilisé? Voici ce que je pense: ce n'est pas nécessairement quelque chose que vous allez utiliser avec chaque base de code, mais vous trouverez parfois utile de pouvoir créer des scénarios de test aléatoires pour tester rigoureusement un morceau de code donné. Quand c'est ce que vous voulez faire, je n'ai pas vu d'outil meilleur pour cela que JSCheck..
JSCheck a quelques autres options et un tas de spécificateurs que nous n'avons pas examinés dans ce tutoriel; rendez-vous sur JSCheck.og pour en savoir plus. Sinon, j'aimerais entendre vos commentaires sur JSCheck dans les commentaires.!