Cum să testați codul JavaScript cu Qunit

Qunit, dezvoltat de echipa jQuery, este un cadru excelent pentru unitatea de testare a JavaScript. În acest tutorial, vă voi prezenta ceea ce este în mod specific pentru Qunit și de ce ar trebui să vă pese de testarea riguroasă a codului.

Ce este QUnit

QUnit este un cadru de testare unitate puternic JavaScript care vă ajută să depanați codul. Este scris de membrii echipei jQuery și este suita oficială de test pentru jQuery. Dar Qunit este destul de general pentru a testa orice cod JavaScript obișnuit, și este chiar capabil să testeze JavaScript de pe server prin intermediul unui motor JavaScript precum Rhino sau V8.

Dacă nu sunteți familiarizați cu ideea de "testare unitară", nu vă faceți griji. Nu este prea greu de înțeles:

În programarea pe calculator, testarea unității este o metodă de verificare și validare a software-ului în care un programator testează dacă unitățile individuale de cod sursă sunt potrivite pentru utilizare. O unitate este cea mai mică parte testabilă a unei aplicații. În programarea procedurală, o unitate poate fi o funcție sau o procedură individuală.

Acest lucru este citat din Wikipedia. Pur și simplu, scrieți teste pentru fiecare funcționalitate a codului dvs. și dacă toate aceste teste sunt transmise, puteți fi siguri că codul va fi fără bug-uri (în majoritate, depinde de cât de detaliate sunt testele dvs.).

De ce ar trebui să vă testați codul

Dacă nu ați scris anterior niciun test de unitate, probabil că doar aplicați codul direct pe un site web, faceți clic pentru o vreme pentru a vedea dacă apare o problemă și încercați să o remediați în timp ce vedeți unul. Există multe probleme cu această metodă.

În primul rând, e foarte obositoare. Făcând clic de fapt nu este o treabă ușoară, pentru că trebuie să vă asigurați că totul este apăsat și este foarte probabil că veți pierde un lucru sau două. În al doilea rând, tot ceea ce ați făcut pentru testare nu este reutilizabil, ceea ce înseamnă că nu este ușor să găsiți regresii. Ce este o regresie? Imaginați-vă că ați scris un cod și l-ați testat, ați rezolvat toate bug-urile pe care le-ați găsit și l-ați publicat. Apoi, un utilizator trimite feedback despre noile bug-uri și solicită câteva caracteristici noi. Du-te înapoi la cod, rezolvați aceste bug-uri noi și adăugați aceste noi caracteristici. Ce se poate întâmpla în continuare este că unii dintre bug-urile vechi vin din nou, numite "regresii". Vedeți, acum trebuie să faceți clic din nou și este posibil să nu mai găsiți din nou acești bug-uri vechi; chiar dacă o faceți, va dura ceva timp înainte să vă dați seama că problema este cauzată de regresii. Cu testarea unităților, scrieți teste pentru a găsi erori, iar odată ce codul este modificat, îl filtrați din nou prin teste. Dacă apare o regresie, unele teste vor fi cu siguranță eșuate și le puteți găsi cu ușurință, știind care parte din cod conține eroarea. Din moment ce știți ceea ce tocmai ați modificat, poate fi ușor reparat.

Un alt avantaj al testării pe unități este în special pentru dezvoltarea web-ului: facilitează testarea compatibilității cu browserele încrucișate. Doar rulați-vă testele pe diferite browsere și dacă apare o problemă la un browser, remediați-l și executați din nou aceste teste, asigurându-vă că nu introduce regresie pe alte browsere. Puteți fi sigur că toate browserele țintă sunt acceptate, odată ce toate au trecut testele.

Aș dori să menționez unul dintre proiectele lui John Resig: TestSwarm. Este nevoie de testare unitate JavaScript la un nou nivel, prin distribuirea acestuia. Este un site care conține multe teste, oricine poate merge acolo, poate rula câteva dintre teste, apoi returnează rezultatul pe server. În acest fel, codul poate fi testat pe diferite browsere și chiar pe diferite platforme foarte rapid.

Cum se scrie testele de unitate cu Qunit

Deci, cum scrieți teste unitare cu Qunit exact? În primul rând, trebuie să configurați un mediu de testare:

    Qunit Test Suite         

Qunit Test Suite

    După cum puteți vedea, o versiune găzduită a cadrului QUnit este utilizată aici.

    Codul care urmează să fie testat ar trebui să fie introdus în myProject.js, iar testele dvs. ar trebui inserate în myTests.js. Pentru a rula aceste teste, deschideți pur și simplu acest fișier HTML într-un browser. Acum este momentul să scrieți câteva teste.

    Elementele de bază ale testelor unitare sunt afirmații.

    O afirmație este o afirmație care prezice rezultatul returnării codului tău. Dacă predicția este falsă, afirmația a eșuat și știți că ceva nu a mers bine.

    Pentru a rula afirmații, ar trebui să le puneți într-un test:

     // Să testăm această funcție funcțională esteEven (val) return val% 2 === 0;  test ('isEven ()', functie () ok (isEven (0), zero este un numar par) , "So este negativ patru"); ok (! EsteEven (1), "Unu nu este un număr par"); ok (! IsEven (-7)

    Aici am definit o funcție, isEven, care detectează dacă un număr este egal, și dorim să testați această funcție pentru a ne asigura că nu se întoarce răspunsuri greșite.

    Primul apel la test (), care construiește un test; primul parametru este un șir care va fi afișat în rezultat, iar al doilea parametru este o funcție de retur care conține afirmațiile noastre. Această funcție de apel invers va fi apelată odată ce este executată funcția Qunit.

    Am scris cinci afirmații, toate fiind booleene. O afirmație booleană se așteaptă ca primul său parametru să fie adevărat. Al doilea parametru este, de asemenea, un mesaj care va fi afișat în rezultat.

    Iată ce obțineți, odată ce ați efectuat testul:

    Deoarece toate aceste afirmații au trecut cu succes, putem fi destul de siguri că este chiar() va funcționa conform așteptărilor.

    Să vedem ce se întâmplă dacă o afirmație a eșuat.

     // Să testăm această funcție funcțională esteEven (val) return val% 2 === 0;  test ('isEven ()', functie () ok (isEven (0), zero este un numar par) , 'So este negativ patru'); ok (! EsteEven (1), 'Unu nu este un număr par'); ok (! IsEven (-7) (3), "Trei este un număr par");)

    Iată rezultatul:

    Afirmația a eșuat deoarece am scris în mod deliberat greșit, dar în propria dvs. proiect, dacă testul nu trece și toate afirmațiile sunt corecte, știți că a fost găsită o eroare.

    Mai multe afirmații

    ok () nu este singura afirmație pe care o oferă Qunit. Există alte tipuri de afirmații care sunt utile atunci când vă testați proiectul:

    Comparație Aserțiune

    Afirmația de comparație, egal (), se așteaptă ca primul parametru (care este valoarea reală) să fie egal cu al doilea parametru (care este valoarea așteptată). Este similar cu ok (), dar produce atât valori reale, cât și valori așteptate, ceea ce face mult mai ușor depanarea. Ca și ok (), este necesar ca un al treilea parametru opțional să fie afișat ca mesaj.

    Deci, în loc de:

     test ('assertions', function () ok (1 == 1, 'unul este egal cu unul');)

    Ar trebui să scrieți:

     test ("afirmații", funcție () este egal (1, 1, "unul este egal cu unul");)

    Observați ultimul "1", care este valoarea de comparare.

    Și dacă valorile nu sunt egale:

     test ("afirmații", funcție () egal (2, 1, "unul este egal cu unul");)

    Oferă mult mai multe informații, făcând viața mult mai ușoară.

    Afirmația de comparație folosește "==" pentru a compara parametrii, astfel încât nu se ocupă de compararea matricei sau a obiectului:

     (a: 1, a: 1, "eșuează"), este egal ([ ], [], "eșuează, există mai multe rețele"), este egal cu ([1], [1], "eșuează");)

    Pentru a testa acest tip de egalitate, Qunit oferă o altă afirmație: aceeași afirmație.

    Aserțiunea identică

    Afirmația identică, aceeași (), se așteaptă la aceiași parametri ca la egal (), dar este o afirmație de comparație profundă recursivă, care nu funcționează numai pe tipuri primitive, dar și pe mături și obiecte. Afirmațiile, în exemplul precedent, vor trece toate dacă le schimbați la afirmații identice:

     (a: 1, a: 1, "passes"), aceleași (a: 1 [], [], "trece, matricele au același conținut"), aceleași ([1], [1], "trece");)

    Observați că același () utilizează '===' pentru a face comparația atunci când este posibil, așa că va fi util la compararea valorilor speciale:

     (0, false, 'true'), același (0, fals, 'fals'), egal (null, undefined, true) fals'); )

    Structura afirmațiilor dumneavoastră

    Punerea tuturor afirmațiilor într-un singur caz de testare este o idee foarte rea, deoarece este foarte greu de menținut și nu aduce un rezultat curat. Ce ar trebui să faceți este să le structurați, să le puneți în diferite cazuri de testare, fiecare urmărind o singură funcționalitate.

    Puteți chiar organiza cazuri de testare în diferite module prin apelarea funcției modulului:

     (modulul A); test ('test', funcție () ); test ("un alt test", funcția () ); modul (modulul B); test ('test', funcție () ); test ("un alt test", funcția () );

    Test asincron

    În exemplele anterioare, toate afirmațiile sunt numite în mod sincron, ceea ce înseamnă că rulează unul după altul. În lumea reală, există și multe funcții asincrone, cum ar fi apelurile ajax sau funcțiile numite de setTimeout () și setInterval (). Cum putem testa aceste tipuri de funcții? Qunit oferă un tip special de testare numit "test asincron", care este dedicat testelor asincrone:

    Să încercăm mai întâi să o scriem în mod regulat:

     test ('test asincron', functie () setTimeout (function () ok (true);, 100)

    Vedea? E ca și cum nu am fi scris nici o afirmație. Acest lucru se datorează faptului că afirmația a fugit asincron, până când a fost chemată, cazul de testare fusese deja terminat.

    Aici este versiunea corectă:

     test ('test asincron', funcția () // Întrerupeți testul prima oprire (); setTimeout (funcția () ok (true); , 100))

    Aici folosim stop () pentru a întrerupe cazul testului și după ce aserțiunea a fost apelată, vom folosi start () pentru a continua.

    Apelarea opririi () imediat după apelarea testului () este destul de comună; astfel încât Qunit oferă o comandă rapidă: asyncTest (). Puteți rescrie exemplul anterior astfel:

     asyncTest ('test asincron', functie () // Testul este intrerupt automat setTimeout (function () ok (true); // dupa ce asertia a fost chemata, // continua startul testului; ))

    Există un lucru de urmărit: setTimeout () va apela întotdeauna funcția de apel invers, dar ce dacă este o funcție particularizată (de exemplu, un apel ajax). Cum puteți fi sigur că va fi apelată funcția de apel invers? Și dacă callback-ul nu este sunat, start () nu va fi apelat și testarea întregii unități va fi blocată:

    Deci, iată ce faceți:

     // Funcția funcției personalizate ajax (successCallback) $ .ajax (url: 'server.php', succes: successCallback);  test ('test asincron', functie () // Întrerupeți testul și nu reușiți dacă start () nu este apelat după o oprire secundă (1000), ajax (function () // ... );))

    Voi treceți un timeout pentru a opri (), ceea ce spune Qunit, "dacă startul () nu este sunat după acest timp de expirare, ar trebui să nu reușiți acest test." Puteți să fiți sigur că întreaga testare nu va fi suspendată și veți fi anunțat dacă ceva nu merge bine.

    Ce zici de multiple funcții asincrone? Unde puneți startul ()? Ați pus-o în setTimeout ():

     // Funcția funcției personalizate ajax (successCallback) $ .ajax (url: 'server.php', succes: successCallback);  test ('test asincron', functie () // Întreruperea testului (); ajax (functie () // ... asincrone assertions) ajax (function () // ... assertions asynchronous () start ();, 2000);)

    Timpul de expirare trebuie să fie destul de rezonabil pentru a permite ca ambele callback-uri să fie chemați înainte ca testul să continue. Dar dacă nu este chemat unul din apelul de apel? De unde știi asta? Aici se așteaptă () vine în:

     // Funcția funcției personalizate ajax (successCallback) $ .ajax (url: 'server.php', succes: successCallback);  test ('test asincron', functie () // Pauza stop test (); // Spuneti Qunit ca asteptati ca trei asertiuni sa ruleze asteptati (3) ajax (function () ok (true) ajax (function () ok (adevărat); ok (adevărat);) setTimeout (function () start ();

    Transmiteți un număr pentru a aștepta () pentru a spune QUnit că vă așteptați la X multe afirmații pentru a fi difuzate, dacă una dintre afirmații nu este chemată, numărul nu se va potrivi și veți fi anunțat că ceva nu a mers.

    Există, de asemenea, o scurtătură pentru a aștepta (): trebuie doar să treci numărul ca al doilea parametru pentru test () sau asyncTest ():

     // Funcția funcției personalizate ajax (successCallback) $ .ajax (url: 'server.php', succes: successCallback);  // Spuneți Qunit că așteptați trei afirmații pentru a rula testul ('test asincron', 3, funcția () // Întrerupeți testul (); ajax (funcția () ok (true) () () () () () () () () () () ()

    Concluzie

    Asta e tot ce trebuie să știi pentru a începe cu Qunit. Testarea unităților este o metodă excelentă pentru a testa codul înainte de al publica. Dacă nu ați scris niciun test de unitate înainte, este timpul să începeți! Vă mulțumim pentru lectură!

    • Urmați-ne pe Twitter sau abonați la Nettuts + RSS Feed pentru cele mai bune tutoriale de dezvoltare web de pe web.
    Cod