Faceți cunoștință cu JSCheck de la Crockford

Există zeci de cadre de testare JavaScript, dar majoritatea funcționează în același mod, mai mult sau mai puțin. Cu toate acestea, JSCheck-ul lui Douglas Crockford este considerabil diferit de majoritatea. În acest tutorial, vă voi arăta cum este diferit și de ce ar trebui să luați în considerare utilizarea acestuia!


Crockford descrie JSCheck ca un "instrument specificat de testare.

Crockford descrie JSCheck ca "un instrument de testare bazat pe specificații". Când utilizați cadrele cu care sunteți obișnuit, ați scrie un test pentru o anumită funcție de funcționalitate și, dacă acel test trece, declară că funcționalitatea dată funcționează corect . Cu toate acestea, este posibil să pierdeți câteva cazuri de margine sau excepții pe care încercările dvs. nu le acoperă.

În timp ce descoperirea de cazuri de margine nu este scopul expres al JSCheck, acesta este un beneficiu frumos lateral. Ideea principală din spatele lui JSCheck este următoarea: specificația pe care o scrieți va descrie de fapt modul în care codul pe care îl testează ar trebui să funcționeze. Apoi, JSCheck va lua caietul de sarcini (numit a Revendicare în JSCheck-lingo) și să genereze teste aleatorii pentru a dovedi revendicarea. În final, vă va raporta rezultatele.

Sună interesant? Citește mai departe! Sună cunoscut? S-ar putea să fi folosit instrumentul de testare Haskell, QuickCheck, pe care sa bazat JSCheck.


Unele coduri de testat

Desigur, înainte de a ne scrie cererea, vom dori să avem un cod de testat. Recent, am scris un scorer de mini-parola, similar cu funcționalitatea pe HowSecureIsMyPassword.net. Este într-adevăr nu este fantezie: trebuie doar să treci funcția o parolă și să obțineți un scor înapoi. Iată codul:

passwordScorer.js

(funcția () var PasswordScorer = ; PasswordScorer.score = funcția (parola) var len = parola.length, lengthScore = 0, letterScore = 0, chars = 21 lengthScore = ; altceva dacă (len> = 16) lengthScore = 6; altceva dacă (len> = 13) lengthScore = 5; 8) lengthScore = 3; altfel dacă (len> = 5) lengthScore = 2; var re = [null, / [az] (var i = 1; i); pentru (var i = 1; i < re.length; i++)  letterScore += (password.match(re[i]) || []).length * i;  return letterScore + lengthScore; ; (typeof window !== 'undefined' ? window : exports).PasswordScorer = PasswordScorer; ());

Este un cod destul de simplu, dar iată ce se întâmplă: scorul este alcătuit din două sub-scoruri. Există un scor de pornire, care se bazează pe lungimea parolei și apoi un scor suplimentar pentru fiecare caracter, 1 punct pentru fiecare literă mică, 2 puncte pentru fiecare literă mare, 3 puncte pentru fiecare număr și 4 puncte pentru fiecare simbol ( dintr-un set limitat).

Deci, acesta este codul pe care îl vom testa: vom genera întâmplător câteva parole cu JSCheck și vom fi siguri că obțin un scor potrivit.


Scrierea afirmației noastre

Acum suntem pregătiți să scriem pretențiile noastre. Mai întâi, du-te pe pagina JSCheck Github și descarcă jscheck.js fişier. Îmi place să-mi execut testele în terminal, prin NodeJS, deci adăugați această singură linie în partea de jos a fișierului:

(fereastra de tip! == 'undefined'? window: exports) .JSC = JSC;

Acest lucru nu va afecta felul în care fișierul se comportă în browser, dar va face ca acesta să funcționeze ca un modul în Nod. Observați că jscheck.js fișier expune SA ca variabilă globală unică pentru întreaga bibliotecă. Dacă nu făceam această ajustare, așa am accesat.

Să ne deschidem passwordScorerSpec.js și începeți lucrurile:

JSC = necesită ("./ ... /vendor/jschec";).JSC; PasswordScorer = necesită ("./ ... /lib/passwordScore";).PasswordScorer;

De vreme ce fac aceste teste în NodeJS, va trebui să cerem modulele pe care le dorim. Desigur, veți dori să vă asigurați că căile corespund locațiilor fișierelor dvs..

Acum, suntem pregătiți să scriem prima noastră afirmație. Desigur, folosim JSC.claim metodă. Această metodă acceptă trei parametri, cu un al patrulea opțional. Primul parametru este doar un șir, a Nume pentru revendicare. Al doilea parametru este numit predicat: este funcția de testare reală. Foarte simplu, această funcție ar trebui să revină Adevărat dacă cererea este adevărată și fals dacă cererea este falsă. Valorile aleatoare pe care JSCheck le va genera pentru test vor fi trecute ca parametri pentru predicat.

Dar cum știe JSCheck ce tip de valori aleatorii să predea predicatul? Aici este al treilea parametru specificator intră în joc. Aceasta este o matrice, cu un element pentru fiecare parametru pentru predicat. Elementele din matrice specifică ce tipuri să dea predicatul, utilizând funcțiile specificatorului JSCheck. Iată câteva dintre ele:

  • JSC.boolean () se întoarce fie adevărat, fie fals.
  • JSC.character () are un caracter min și max și returnează un singur caracter din acel interval. Poate de asemenea să ia un singur cod de caractere și să returneze acel caracter.
  • JSC.integer () va returna un număr prime. Sau, treceți un singur parametru pentru a obține un număr întreg (întreg) între 1 și parametru sau doi parametri pentru un număr întreg din acel interval.

Ai idee. Există și alți specialiști și vom folosi unii acum când scriem prima noastră revendicare.

JSC.claim ("Toate parolele mici" ;, funcția (parola, maxScore) returnare PasswordScorer.score (parola) <= maxScore; , [ JSC.string(JSC.integer(10, 20), JSC.character('a', 'z')), JSC.literal(26) ]);

Primul nostru parametru este un nume. Al doilea este funcția de testare: primește o parolă și un scor maxim și returnează adevărat dacă scorul pentru parola respectivă este mai mic sau egal cu scorul maxim. Apoi, avem matricea specificatoarelor noastre. Primul nostru parametru (parola) ar trebui să fie un șir, deci folosim JSC.string () : pot lua doi parametri, numărul de caractere din șir și valoarea pentru acele caractere. După cum puteți vedea, solicităm o parolă între 10 și 20 de caractere. Pentru valoare, folosim JSC.characters () pentru a obține caractere aleatorii între 'a' și 'z'.

Următoarea valoare este cea a noastră maxScore parametru. Uneori, nu vrem să avem o întâmplare pe care JSCheck o oferă și acesta este unul din acele vremuri. De asta există JSC.literal: pentru a transmite o valoare literală predicatului. În acest caz, folosim 26, care ar trebui să fie scorul maxim pentru orice parolă mică între 10 și 20 de caractere.

Acum suntem gata să facem testul.


Executarea revendicării noastre

Înainte de a executa reclamația și de a obține raportul, trebuie să configurați funcția care va primi raportul. JSCheck transmite raportul unei funcții de apel invers JSC.on_report. De aici:

JSC.on_report (funcția (str) console.log (str););

Nimic fantezist. Acum, tot ce a mai rămas este să sunați JSC.check (). Acum, ne putem duce la terminalul nostru și putem rula acest lucru:

calea nodului / către / parolaScorerSpec.js

În spatele scenei, JSCheck rulează predicatul de 100 de ori, generând diferite valori aleatorii de fiecare dată. Ar trebui să vedeți raportul dvs. imprimat.

Toate parolele minuscule 100 din 100 trec 100

Toți au trecut, dar asta nu este un raport, nu? Ei bine, dacă oricare dintre testele noastre ar fi eșuat, ar fi fost incluse în raport. Cu toate acestea, puteți ajusta nivelul de ieșire cu JSC.detail funcția: treceți-i un număr între 0 și 4 (inclusiv) pentru a obține nimic pentru nici o ieșire în toate cazurile de testare. Valoarea implicită este 3.


Adăugarea unui clasificator

Ține minte cum am spus asta JSC.claim ar putea lua un al patrulea parametru? Se numește a clasificator, și primește aceiași parametri pe care predicatul le primește. Apoi, acesta poate returna un șir pentru a clasifica sau grupa casetele noastre de testare. Voi recunoaște că nu eram foarte sigur unde ar fi util până când am creat exemplul de mai sus. Vezi, am făcut o greșeală în predicat și am comparat scorul cu maxScore cu operator în loc de operator, astfel încât toate parolele care au marcat 26 de puncte au eșuat. Am văzut rapoarte care arătau așa:

Toate parolele minuscule 96 din 100 FAIL [12] ("vqfqkqqbwkdjrvplkrx"; 26) FAIL [21] ("nhgkznldvoenhqqlfza"; 26) ; 26) trec 96 de eșec 4

Încă nu este evident de ce unele încercări nu reușesc. Așa că am adăugat o funcție de clasificare care a grupat cazurile de testare prin scor: așa cum am spus, funcția are aceiași parametri ca predicatul și returnează un șir. Fiecare caz test care primește același șir din clasificator va fi grupat în raport.

(parola, maxScore) returnare PasswordScorer.score (parola) + "puncte" ;; 

Această funcție ar trebui să fie ultimul parametru al revendicării noastre. Acum, veți primi un raport care este ceva de genul:

Toate parolele minuscule 96 din 100 FAIL [4] 26 de puncte: ("illqbtiubsmrhxdwjfo"; 26) FAIL [22] 26 puncte :( "gruvmmqjzqlcyaozgfh"; 26) FAIL [34] 26 points :( chhbevwtjvslprqczjg; ) FAIL [65] 26 puncte: ("kskqdjhtonybvfewdjm"; 26) 14 puncte: trecere 8 15 puncte: trecere 5 16 puncte: trecere 12 18 puncte: trecere 10 19 puncte: trecere 12 20 puncte: trecere 11 22 puncte: 12 23 puncte: trecere 8 24 puncte: trecere 10 25 puncte: trecere 8 26 puncte: trecere 0 eșec 4

Puteți vedea cum sunt grupate testele în funcție de numărul de puncte în care sunt valide parolele. Acum, este ușor să vedeți că singurele parole care nu reușesc de testare sunt parolele care scor 26 puncte. Și în timp ce problema a fost aici cu testul și nu cu codul, acesta arată încă cum poate fi util să adăugați o funcție de clasificator la afirmațiile dvs..


Gândurile finale

Deci, la sfârșitul zilei, merită să fie folosit de JSCheck? Iată ce gândesc: nu este ceva ce o să utilizați neapărat cu fiecare bază de cod, dar uneori veți găsi util să puteți crea cazuri de testare aleatorii care vor testa riguros o anumită bucată de cod. Când asta vrei să faci, nu am văzut un instrument mai bun pentru asta decât JSCheck.

JSCheck are câteva alte opțiuni și o grămadă de specificatori pe care nu am revizuit-o în acest tutorial; du-te la JSCheck.og pentru a citi despre acestea. În caz contrar, mi-ar plăcea să vă aud gândurile despre JSCheck în comentarii!

Cod