O introducere în Jasmine unitate de testare

Jasmine este cel mai popular biblioteca JS pentru unitatea de testare aplicații web. În acest tutorial, conceput pentru începători, vă vom prezenta un ghid rapid și complet pentru testarea cu Jasmine.

veți fi prezentat Jasmine, un cadru popular de testare bazat pe comportament pentru JavaScript. Vom vedea, de asemenea, un exemplu practic simplu despre cum să scrieți teste unitare cu Jasmine, care vă pot ajuta să verificați cu ușurință erorile din codul dvs.

pe scurt, vom vedea cum să scrieți suitele de testare, specificațiile și așteptările și cum să aplicați Jasmine matchers încorporate sau să vă construiți propriile matchers personalizate

vom vedea, de asemenea, cum puteți grupa suitele de dragul organizării testelor pentru baze de cod mai complexe.

introducerea Jasmine

Jasmine este un foarte popular JavaScript de dezvoltare bazate pe comportament (în BDD, scrie teste înainte de a scrie cod real) cadru pentru unitatea de testare aplicații JavaScript. Oferă utilități care pot fi utilizate pentru a rula teste automate atât pentru codul sincron, cât și pentru cel asincron.

Jasmine are multe caracteristici, cum ar fi:

  • Este rapid și are aeriene reduse și nu dependențe externe.
  • este o bibliotecă inclusă în baterii și oferă tot ce aveți nevoie pentru testarea codului.
  • este disponibil atât pentru nod și browser-ul.
  • acesta poate fi utilizat cu alte limbi, cum ar fi Python și Ruby.
  • nu necesită DOM.
  • oferă o sintaxă curată și ușor de înțeles și, de asemenea, un API bogat și simplu.
  • putem folosi limbajul natural pentru a descrie testele și rezultatele așteptate.Jasmine este un instrument open source care este disponibil sub licența permisivă MIT. Începând cu această scriere, cea mai recentă versiune majoră este Jasmine 3.0, care oferă noi caracteristici și unele modificări de rupere. Versiunea 2.99 a Jasmine va oferi diferite avertismente de depreciere pentru apartamentele care au un comportament diferit în versiunea 3.0, ceea ce va facilita migrarea dezvoltatorilor la noua versiune.

    puteți citi despre noile caracteristici și modificările de rupere din acest document.

    utilizarea Jasmine

    puteți utiliza Jasmine în mai multe moduri diferite:

    • În vechiul mod prin includerea atât a miezului Jasmine, cât și a fișierelor dvs. de testare folosind un <script> etichetă,
    • ca instrument CLI folosind nod.js,
    • ca o bibliotecă în nod.js,
    • ca parte a unui sistem de construcție ca Gulp.js sau Grunt.js via grunt-contrib-jasmine și gulp-Jasmine-browser

    de asemenea, puteți utiliza Jasmine pentru testarea codului Python cu jasmine-py care poate fi instalat de la PyPI folosind comandapip install jasmine. Acest pachet conține atât un server web care servește și execută o suită Jasmine pentru proiectul dvs., cât și un script CLI pentru rularea testelor și integrărilor continue.

    Jasmine este de asemenea disponibil pentru proiecte Ruby prin jasmine-gem, care poate fi instalat prin adăugareagem 'jasmine' la Gemfile și ruleazăbundle install. Acesta include un server pentru servirea și rularea testelor, un script CLI și, de asemenea, generatoare pentru proiectele Ruby on Rails.

    acum să ne concentrăm asupra modului de utilizare a Jasmine cu JavaScript:

    utilizarea Standalone Jasmine

    începeți prin a descărca cea mai recentă versiune de Jasmine de pe pagina lansări.

    apoi pur și simplu extrageți fișierul zip, de preferință într-un folder din proiectul pe care doriți să îl testați.

    folderul va conține o grămadă de fișiere și foldere implicite:

    /src: conține fișierele sursă pe care doriți să le testați. Aceasta poate fi ștearsă fie dacă aveți deja configurarea folderului proiectului dvs., fie poate fi utilizată și atunci când este cazul pentru găzduirea codului sursă.

    /lib: conține fișierele de bază Jasmine.

    /spec: conține testele pe care urmează să le scrieți.

    SpecRunner.html: acest fișier este folosit ca un alergător de testare. Executați specificațiile prin simpla lansare a acestui fișier.

    acesta este conținutul unui fișier implicitSpecRunner.html:

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>Jasmine Spec Runner v3.2.1</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-3.2.1/jasmine_favicon.png"> <link rel="stylesheet" href="lib/jasmine-3.2.1/jasmine.css"> <script src="lib/jasmine-3.2.1/jasmine.js"></script> <script src="lib/jasmine-3.2.1/jasmine-html.js"></script> <script src="lib/jasmine-3.2.1/boot.js"></script> <!-- include source files here... --> <script src="src/Player.js"></script> <script src="src/Song.js"></script> <!-- include spec files here... --> <script src="spec/SpecHelper.js"></script> <script src="spec/PlayerSpec.js"></script></head><body></body></html>

    rețineți că trebuie să modificați fișierele incluse din folderele/src și/spec pentru a conține sursa reală și fișierele de testare.

    utilizarea Jasmine ca o bibliotecă

    puteți utiliza, de asemenea, Jasmine ca o bibliotecă în proiectul dumneavoastră. De exemplu, următorul cod importă și execută Jasmine:

    var Jasmine = require('jasmine');var jasmine = new Jasmine();jasmine.loadConfigFile('spec/support/jasmine.json');jasmine.execute();

    Mai întâi solicităm/importăm Jasmine și folosim metodaloadConfigFile() pentru a încărca fișierul de configurare disponibil de laspec/support/jasmine.json apoi în cele din urmă executăm Jasmine.

    utilizarea Jasmine prin CLI

    puteți utiliza, de asemenea, Jasmine din CLI, care vă permite să rulați cu ușurință teste Jasmine și implicit de ieșire rezultatele în terminal.

    vom urma această abordare pentru a rula testele noastre de exemplu în acest ghid, deci mai întâi mergeți mai departe și executați următoarea comandă pentru a instala Jasmine la nivel global:

    npm install -g jasmine

    poate fi necesar să rulați sudo pentru instalarea pachetelor NPM la nivel global, în funcție de configurația npm.

    acum, creați un folder pentru proiectul dvs. și navigați în interiorul acestuia:

    $ mkdir jasmine-project $ cd jasmine-project

    apoi, executați următoarea comandă pentru a inițializa proiectul pentru Jasmine:

    această comandă creează pur și simplu un folder spec și un fișier de configurare JSON. Aceasta este ieșirea dir comandă:

    .└── spec └── support └── jasmine.json2 directories, 1 file

    acesta este conținutul unui implicit jasmine.json fișier:

    { "spec_dir": "spec", "spec_files": pec.js" ], "helpers": , "stopSpecOnExpectationFailure": false, "random": true}
    • spec_dir: specifică unde Jasmine caută fișiere de testare.
    • spec_files: specifică modelele fișierelor de testare, în mod implicit toate fișierele JS care se termină cu șiruri Spec sau spec.
    • helpers: specifică unde Jasmine caută fișiere helper. Fișierele Helper sunt executate înainte de specificații și pot fi folosite pentru a defini matchers personalizate.
    • stopSpecOnExpectationFailure: când este setat la true se va opri imediat o spec pe primul eșec al unei așteptări (poate fi folosit ca opțiune CLI prin--stop-on-failure).
    • random: când este setat la True Jasmine va rula pseudo-aleatoriu cazurile de testare (poate fi folosit ca opțiune CLI prin--random).

    spec_files șihelpers Matricele pot conține, de asemenea, modele Glob (datorită pachetului node-glob) pentru specificarea căilor de fișiere pe care le utilizați de obicei pentru a specifica un set de fișiere atunci când lucrați în Bash (de exemplu,ls *.js).

    dacă nu utilizați locația implicită pentru fișierul de configurarejasmine.json, trebuie doar să specificați locația personalizată prin opțiuneajasmine --config.

    puteți găsi mai multe opțiuni CLI din documentele oficiale.

    înțelegerea Jasmine

    În această secțiune vom învăța despre elementele de bază ale Jasmine de testare, cum ar fi apartamente, specificatii, așteptările, matchers și spioni, etc.

    în folderul proiectului, executați următoarea comandă pentru a inițializa un nou modul nod:

    aceasta va crea un fișierpackage.json cu informații implicite:

    { "name": "jasmine-project", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": , "author": "", "license": "ISC"}

    apoi, creați un fișierindex.js și adăugați următorul cod:

    function fibonacci(n){ if (n === 1) { return ; } else { var s = fibonacci(n - 1); s.push(s + s); return s; }}function isPrime(num){ for (let i = 2; i < num; i++) if (num % i === 0) return false; return num !== 1 && num !== 0;}function isEven(n) { return n % 2 == 0;}function isOdd(n) { return Math.abs(n % 2) == 1;}function toLowerCase(str){ return str.toLowerCase();}function toUpperCase(str){ return str.toUpperCase();}function contains(str, substring, fromIndex){ return str.indexOf(substring, fromIndex) !== -1;}function repeat(str, n){ return (new Array(n + 1)).join(str);}module.exports = { fibonacci: fibonacci, isPrime: isPrime, isEven: isEven, isOdd: isOdd, toLowerCase: toLowerCase, toUpperCase: toUpperCase, contains: contains, repeat: repeat};

    Suites

    o suită grupează un set de specificații sau cazuri de testare. Este folosit pentru a testa un comportament specific al codului JavaScript care este de obicei încapsulat de un obiect/clasă sau o funcție. Este creat folosind funcția Jasmine global describe() care are doi parametri, titlul suitei de testare și o funcție care implementează codul real al suitei de testare.

    să începem prin crearea primei noastre suite de testare. În folderulspec creați un fișierMyJSUtilitiesSpec.js și adăugați:

    describe("MyJSUtilities", function() { /* ... */ });

    MyJSUtilities este numele acestei suite de testare de nivel superior.

    cum se grupează și se cuibăresc suitele

    pentru o mai bună organizare și descriere exactă a setului nostru de teste, putem cuibări suitele în interiorul suitei de nivel superior. De exemplu, să adăugăm două suite la suita MyJSUtilities:

    describe("String Utils", function() { /*...*/});describe("Math Utils", function() { /*...*/});

    în interiorul suitei Math Utils, să adăugăm și două suite imbricate:

    describe("Basic Math Utils", function() { /* ... */ }); describe("Advanced Math Utils", function() { /* ... */ });

    grupăm testele aferente în teste pentru Utils String, Utils Math Basic și Utils Math Advanced și le cuibărim în interiorul testului de nivel superior suite myjsutilities. Aceasta va compune specificațiile dvs. ca arbori similari cu o structură de foldere.

    structura de cuibărit va fi afișată în raport, ceea ce vă face ușor să găsiți teste nereușite.

    cum se exclud suitele

    puteți dezactiva temporar o suită utilizând funcțiaxdescribe(). Are aceeași semnătură (parametri) ca o describe() funcție ceea ce înseamnă că puteți dezactiva rapid suitele existente adăugând pur și simplu un x la funcție.specificațiile dintr-o funcție

    xdescribe() vor fi marcate în așteptare și nu vor fi executate în raport.

    Specificații

    o spec declară un caz de testare care aparține unei suite de testare. Acest lucru se face apelând funcția globală Jasmine it() care ia doi parametri, titlul spec (care descrie logica pe care dorim să o testăm) și o funcție care implementează cazul de testare real.

    o specificație poate conține una sau mai multe așteptări. Fiecare așteptare este pur și simplu o afirmație care poate returna fie true sau false. Pentru ca spec să fie trecut, toate așteptările aparținând spec trebuie să fie true altfel spec eșuează.

    în suita noastră String Utils, adăugați aceste specificații:

    describe("String Utils", function() { it("should be able to lower case a string",function() { /*...*/ }); it("should be able to upper case a string",function() { /*...*/ }); it("should be able to confirm if a string contains a substring",function() { /*...*/ }); it("should be able repeat a string multiple times",function() { /*...*/ });});

    în suita noastră Basic Math Utils să adăugăm câteva specificații:

    describe("Basic Math Utils", function() { it("should be able to tell if a number is even",function() { /*...*/ }); it("should be able to tell if a number is odd",function() { /*...*/ }); });

    pentru Utils Math avansate, să adăugăm specificațiile:

    describe("Advanced Math Utils", function() { it("should be able to tell if a number is prime",function() { /*...*/ }); it("should be able to calculate the fibonacci of a number",function() { /*...*/ }); });

    cum se exclud specificațiile

    la fel ca suitele, puteți exclude și specificațiile individuale folosindxit() funcție care dezactivează temporarit() și marchează specificațiile ca fiind în așteptare.

    așteptările

    așteptările sunt create folosindexpect() funcție care ia o valoare numită real (aceasta poate fi valori, expresii, variabile, funcții sau obiecte etc.). Așteptările compun specificațiile și sunt utilizate împreună cu funcțiile matcher (prin înlănțuire) pentru a defini ce așteaptă dezvoltatorul de la o anumită unitate de cod pentru a efectua.

    o funcție matcher compară între o valoare reală (transmisă laexpect() funcția cu care este înlănțuită) și o valoare așteptată (transmisă direct ca parametru către matcher) și returnează fie adevărat, fie fals, care fie trece, fie eșuează spec.

    puteți înlănțuiexpect() funcția cu mai multe matchere. Pentru a anula / inversa rezultatul boolean al oricărui matcher, puteți utiliza not cuvânt cheie înainte de a apela matcher.

    să implementăm specificațiile exemplului nostru. Pentru moment vom folosi vom folosi expect() cu nothing() matcher care face parte din matchers built-in pe care le vom vedea un pic mai târziu. Acest lucru va trece toate specificațiile, deoarece nu ne așteptăm la nimic în acest moment.

    describe("MyJSUtilities", function() {describe(">String Utils", function() { it("should be able to lower case a string",function() { expect().nothing(); }); it("should be able to upper case a string",function() { expect().nothing(); }); it("should be able to confirm if a string contains a substring",function() { expect().nothing(); }); it("should be able repeat a string multiple times",function() { expect().nothing(); }); });describe("Math Utils", function() { describe("Basic Math Utils", function() { it("should be able to tell if a number is even",function() { expect().nothing(); }); it("should be able to tell if a number is odd",function() { expect().nothing(); }); }); describe("Advanced Math Utils", function() { it("should be able to tell if a number is prime",function() { expect().nothing(); }); it("should be able to calculate the fibonacci of a number",function() { expect().nothing(); }); }); });});

    aceasta este o captură de ecran a rezultatelor în acest moment:

    avem opt specificații trecute și zero eșecuri.

    puteți utiliza fie matchers built-in sau, de asemenea, crea propriile matchers personalizate pentru nevoile dvs. specifice.

    built-in Matchers

    Jasmine oferă un set bogat de matchers built-in. Să vedem câteva dintre cele importante:

    • toBe() pentru testarea identității,
    • toBeNull() pentru testarea null,
    • toBeUndefined()/toBeDefined() pentru testare pentru undefined/not undefined,
    • toBeNaN() pentru testarea pentru Nan (nu un număr)
    • toEqual() pentru testarea pentru egalitate,
    • toBeFalsy()/toBeTruthy() pentru testarea falsității/veridicității etc.

    puteți găsi lista completă a matchers din docs.

    să pună în aplicare acum specificatiile noastre cu unele dintre aceste matchers atunci când este cazul. Mai întâi importăm funcțiile pe care le testăm în MyJSUtilitiesSpec.js fișier:

    const utils = require("../index.js");

    apoi, începeți cu șirul Utils suite și schimbați expect().nothing() cu așteptările corespunzătoare.

    de exemplu pentru prima spec, ne așteptăm ca metodatoLowerCase() să fie definită mai întâi și, în al doilea rând, să returneze un șir cu litere mici, adică:

    it("should be able to lower case a string",function() { expect(utils.toLowerCase).toBeDefined(); expect(utils.toLowerCase("HELLO WORLD")).toEqual("hello world"); });

    acesta este codul complet pentru suită:

    describe(">String Utils", function() { it("should be able to lower case a string",function() { expect(utils.toLowerCase).toBeDefined(); expect(utils.toLowerCase("HELLO WORLD")).toEqual("hello world"); }); it("should be able to upper case a string",function() { expect(utils.toUpperCase).toBeDefined(); expect(utils.toUpperCase("hello world")).toEqual("HELLO WORLD"); }); it("should be able to confirm if a string contains a substring",function() { expect(utils.contains).toBeDefined(); expect(utils.contains("hello world","hello",0)).toBeTruthy(); }); it("should be able repeat a string multiple times",function() { expect(utils.repeat).toBeDefined(); expect(utils.repeat("hello", 3)).toEqual("hellohellohello"); }); });

    Matchers personalizate

    Jasmine oferă posibilitatea de a scrie matchers personalizate pentru punerea în aplicare afirmații care nu sunt acoperite de matchers built-in sau doar de dragul de a face teste mai descriptiv și ușor de citit.

    de exemplu, să luăm următoarele specificații:

    it("should be able to tell if a number is even",function() { expect(utils.isEven).toBeDefined(); expect(utils.isEven(2)).toBeTruthy(); expect(utils.isEven(1)).toBeFalsy(); });

    Să presupunem că metoda isEven() nu este implementată. Dacă rulăm testele, vom primi mesaje precum următoarea captură de ecran:

    mesajul de eșec pe care îl primim spune că se așteaptă ca nedefinit să fie definit, ceea ce nu ne oferă nicio idee despre ce se întâmplă. Deci, să facem acest mesaj mai semnificativ în contextul domeniului nostru de cod (acest lucru va fi mai util pentru bazele de cod complexe). Pentru această chestiune, să creăm un matcher personalizat.

    vom crea matchers personalizate folosindaddMatchers() metoda care ia un obiect compus din una sau mai multe proprietăți care vor fi adăugate ca matchers. Fiecare proprietate ar trebui să ofere o funcție din fabrică care să ia doi parametri: util, care are un set de funcții de utilitate pe care să le folosească matcherii (vezi: matchersUtil.js) și customEqualityTesters care trebuie trecut în dacă util.equals este numit, și ar trebui să returneze un obiect cu un compare funcție care va fi apelat pentru a verifica așteptările.

    trebuie să înregistrăm matcherul personalizat înainte de a executa fiecare spec folosind metoda beforeEach() :

    describe("/Basic Math Utils", function () {beforeEach(function () {jasmine.addMatchers({hasEvenMethod: function (util, customEqualityTesters) {return {compare: function (actual, expected) {var result = { pass: utils.isEven !== undefined };if (result.pass) {result.message = "Expected isEven() to be not defined."}else {result.message = "Expected isEven() to be defined."}return result;}}}});});/*...*/});

    putem folosi apoi matcherul personalizat în loc de expect(utils.isEven).toBeDefined():

    expect().hasEvenMethod();

    Acest lucru ne va oferi un mesaj de eșec mai bun:

    folosind beforeEach() și afterEach()

    pentru inițializarea și curățarea specificațiilor, Jasmine oferă două funcții globale, beforeEach() și afterEach():

    • funcția beforeEach este apelată o dată înainte de fiecare spec în suita în care este apelată.
    • funcțiaafterEach este apelată o dată după fiecare spec în suita unde este apelată.

    de exemplu, dacă trebuie să utilizați orice variabile din suita de testare, le puteți declara pur și simplu la începutul funcțieidescribe() și puteți pune orice cod de inițializare sau instanțiere în interiorul unei funcțiibeforeEach(). În cele din urmă, puteți utiliza funcția afterEach() pentru a reseta variabilele după fiecare spec, astfel încât să puteți avea testarea unității pure fără a fi nevoie să repetați inițializarea și Codul de curățare pentru fiecare spec.

    funcțiabeforeEach() este, de asemenea, perfect combinată cu multe API-uri Jasmine, cum ar fi metodaaddMatchers() pentru a crea matchers personalizate sau, de asemenea, cu funcțiadone() pentru a aștepta operațiile asincrone înainte de a continua testarea.

    eșecul unui Test

    puteți forța un test să eșueze folosind metoda globalăfail() disponibilă în Jasmine. De exemplu:

    it("should explicitly fail", function () { fail('Forced to fail'); });

    ar trebui să primiți următoarea eroare:

    testarea excepțiilor

    când vă testați codul, erorile și excepțiile pot fi aruncate, deci ar putea fi necesar să testați pentru aceste scenarii. Jasmine oferătoThrow() șitoThrowError() matchers pentru a testa atunci când o excepție este aruncat sau pentru a testa pentru o excepție specifică, respectiv.

    de exemplu, dacă avem o funcție care aruncă oTypeError excepție:

    function throwsError() { throw new TypeError("A type error"); }

    ai putea scrie un spec care să testeze pentru dacă o excepție este aruncat:

    it('it should throw an exception', function () { expect(throwsError).toThrow(); });

    sau ai putea folosi, de asemenea, testul pentru specificTypeError excepție:

    it('it should throw a TypeError', function () { expect(throwsError).toThrowError(TypeError); });

    înțelegerea spionilor

    cel mai adesea, metodele depind de alte metode. Aceasta înseamnă că atunci când testați o metodă, puteți ajunge, de asemenea, să testați dependențele acesteia. Acest lucru nu este recomandat în testare, adică trebuie să vă asigurați că testați funcția pură izolând metoda și văzând cum se comportă având în vedere un set de intrări.

    Jasmine oferă spioni care pot fi folosiți pentru a spiona / asculta apeluri de metode pe obiecte și pentru a raporta dacă se apelează o metodă și cu ce context și argumente.

    Jasmine oferă două moduri de spionaj pe apeluri metoda: folosindspyOn() saucreateSpy() metode.

    puteți utilizaspyOn() când metoda există deja pe obiect, altfel trebuie să utilizațijasmine.createSpy() care returnează o nouă funcție.

    în mod implicit, un spion va raporta numai dacă un apel a fost efectuat fără a apela prin funcția spied (i.e funcția se va opri de executare), dar puteți schimba comportamentul implicit folosind aceste metode:

    • and.callThrough(): apel prin funcția originală,
    • and.returnValue(value): returnați valoarea specificată,
    • and.callFake(fn): apelați funcția fals în loc de cel original,
    • and.throwError(err): arunca o eroare,
    • and.stub(): resetează comportamentul stubbing implicit.

    puteți utiliza un spion pentru a aduna statistici run-time pe funcția spied, de exemplu, dacă doriți să știți cât de multe ori funcția a fost numit.

    spunem că vrem să ne asigurăm cătoUpperCase() metoda folosește metoda încorporată String.toUpperCase(), trebuie să spionăm pur și simplu String.toUpperCase() folosind:

    it("should be able to upper case a string", function () { 
    var spytoUpperCase = spyOn(String.prototype, 'toUpperCase') 
    expect(utils.toUpperCase).toBeDefined(); expect(utils.toUpperCase("hello world")).toEqual("HELLO WORLD"); expect(String.prototype.toUpperCase).toHaveBeenCalled(); expect(spytoUpperCase.calls.count()).toEqual(1); });

    testul a eșuat din cauza celei de-a doua așteptări, deoarece utils.toUpperCase("hello world") a revenit nedefinit în locul lumii așteptate. Asta pentru că, așa cum am menționat, mai devreme după crearea spionului pe toUpperCase(), metoda nu este executată. Trebuie să schimbăm acest comportament implicit apelând callThrough():

    vă rugăm să rețineți că ospy funcția înlocuiește funcția spionat cu un ciot în mod implicit. Dacă trebuie să apelați funcția originală în schimb, puteți adăuga.and.callThrough() laspy obiect.

    var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.callThrough();

    acum toate așteptările trec.

    de asemenea, puteți utiliza and.callFake() sau and.returnValue() pentru a falsifica fie spionat pe funcția sau doar valoarea returnată, dacă nu pentru a apela prin funcția reală:

    var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.returnValue("HELLO WORLD"); 
    var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.callFake(function(){ return "HELLO WORLD"; });

    acum, dacă vom ajunge să nu folosim construit în String.toUpperCase() în propria noastră utils.toUpperCase() punerea în aplicare, vom obține aceste eșecuri:

    cele două așteptări expect(String.prototype.toUpperCase).toHaveBeenCalled()expect(spytoUpperCase.calls.count()).toEqual(1) au eșuat.

    cum se tratează Asincronitatea în Jasmine

    dacă codul pe care îl testați conține operații asincrone, aveți nevoie de o modalitate de a anunța Jasmine când s-au finalizat operațiile asincrone.

    în mod implicit, Jasmine așteaptă ca orice operație asincronă, definită printr-un apel invers, promisiune sau cuvântul cheieasync să fie terminată. Dacă Jasmine găsește un cuvânt cheie callback, promise sau async într-una din aceste funcții: beforeEachafterEachbeforeAllafterAll și it va aștepta ca asincronul să fie făcut înainte de a trece la următoarea operație.

    folosind done() cu beforeEach () / it() ..

    să luăm exemplul nostrusimulateAsyncOp() care simulează o operație asincronă folosindsetTimeout(). Într-un scenariu din lumea reală, aceasta poate fi o cerere Ajax sau orice lucru similar care se întâmplă asincron:

    function simulateAsyncOp(callback){ 
    setTimeout(function () { callback(); }, 2000); }

    pentru a testa această funcție putem folosi beforeEach() funcția cu done() apel invers. Codul nostru trebuie să invoce done() pentru a-i spune lui Jasmine că operația asincronă s-a încheiat:

    describe("/Async Op", function () {var asyncOpCompleted = false;beforeEach(function (done) {utils.simulateAsyncOp(function(){ asyncOpCompleted = true; done();});});it("should be able to tell if the async call has completed", function () { expect(asyncOpCompleted).toEqual(true);});});

    putem observa rapid un dezavantaj al acestei metode, deci trebuie să scriem codul nostru pentru a acceptadone() apel invers. În cazul nostru, nu am codificat metoda done() în simulateAsyncOp(fn) dar am furnizat un parametru de apel invers doar pentru a putea apela done().

    utilizarea promisiunilor

    dacă nu doriți să creați un cod care depinde de modul în care scrieți testul, puteți utiliza în schimb o promisiune și puteți apeladone() apel invers atunci când promisiunea s-a rezolvat. Sau mai bine, în Jasmine 2.7+ , dacă codul dvs. returnează un Promise, Jasmine va aștepta până când este rezolvat sau respins înainte de a executa următorul cod.

    folosind asincron/wait

    Jasmine 2.7+ acceptăasync șiawait solicită specificații. Acest lucru vă scutește de la punerea afirmă într-un .then() sau .catch() bloc.

    it("should work with async/await", async () => { let completed = false; completed = await utils.simulateAsyncOp(); expect(completed).toEqual(true); });

    aceasta este implementarea simulateAsyncOp:

    function simulateAsyncOp() { 
    return new Promise(resolve => { setTimeout(() => { resolve(true); }, 1000); }); }

    folosind Jasmine Clock

    ceasul Jasmine este folosit pentru a testa codul asincron care depinde de funcții de timp, cum ar fi setTimeout() în același mod în care testăm codul sincron prin batjocorirea API-urilor bazate pe timp cu metode personalizate. În acest fel, puteți executa funcțiile testate sincron controlând sau avansând manual ceasul.

    puteți instala ceasul Jasmine apelând funcțiajasmine.clock().install în specificațiile sau suita dvs.

    după utilizarea ceasului, trebuie să îl dezinstalați pentru a restabili funcțiile originale.

    cu Jasmine clock, puteți controla JavaScriptsetTimeoutsausetIntervalfuncții bifând ceasul pentru a avansa în timp folosindjasmine.clock().tick funcție, care ia numărul de milisecunde cu care vă puteți deplasa.

    de asemenea, puteți utiliza ceasul Jasmine pentru a bate joc de data curentă.

    beforeEach(function () {jasmine.clock().install();});afterEach(function() {jasmine.clock().uninstall();});it("should call the asynchronous operation synchronously", function() {var completed = false;utils.simulateAsyncOp(function(){completed = true;});expect(completed).toEqual(false);jasmine.clock().tick(1001);expect(completed).toEqual(true);});

    aceasta estesimulateAsyncOp funcția:

    function simulateAsyncOp(callback){ 
    setTimeout(function () { callback(); }, 1000); }

    în cazul în care nu ați specificat un timp pentru funcția mockDate, aceasta va utiliza data curentă.

    erori de manipulare

    dacă codul dvs. asincron eșuează din cauza unei erori, doriți ca specificațiile dvs. să eșueze corect. Începând cu Jasmine 2.6 + orice erori netratate sunt trimise la spec executat în prezent.

    Jasmine oferă, de asemenea, o modalitate de a utiliza în cazul în care aveți nevoie pentru a eșua în mod explicit specificatiile:

    • folosinddone() apel invers cubeforeEach() apelânddone.fail(err) metodă,
    • pur și simplu trecând o eroare ladone(err) apel invers (Jasmine 3+),
    • apelândreject() metoda unuiPromise.

    concluzie

    În acest ghid am introdus Jasmine și am văzut cum să începeți să utilizați Jasmine pentru a testa unitatea codului JavaScript. Vă mulțumim pentru lectură!

    Acest articol a fost publicat inițial în techiediaries.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *