Știm cu toții că ar trebui să scriem teste unitare. Dar, este greu să știi de unde să începi și cât timp să dedici testelor în comparație cu implementarea efectivă. Deci, de unde să începem? Și este vorba doar de testarea codului sau testele unitare au alte avantaje?

În acest articol, voi explica diferitele tipuri de teste și beneficiile pe care le aduce testele unitare echipelor de dezvoltare. Voi prezenta Jest – un cadru de testare JavaScript.

Diferite tipuri de testare

Înainte de a ne arunca cu privire la specificul testelor unitare, vreau să fac o scurtă trecere prin diferite tipuri de teste. Există adesea o oarecare confuzie în jurul lor și nu mă mir. Uneori linia dintre ele este destul de subțire.

Teste unitare

Testele unitare testează doar o singură parte a implementării dvs. O unitate. Fără dependențe sau integrări, fără specificități de cadru. Sunt ca o metodă care returnează un link într-o anumită limbă:

export function getAboutUsLink(language){
  switch (language.toLowerCase()){
    case englishCode.toLowerCase():
      return '/about-us';
    case spanishCode.toLowerCase():
      return '/acerca-de';
  }
  return '';
}

Teste de integrare

La un moment dat, codul dvs. comunică cu o bază de date, un sistem de fișiere sau o altă terță parte. Ar putea fi chiar un alt modul din aplicația dvs.

Acea parte a implementării ar trebui testată prin teste de integrare. De obicei, acestea au o configurație mai complicată care implică pregătirea mediilor de testare, inițializarea dependențelor etc.

Teste funcționale

Testele unitare și testele de integrare vă oferă încredere că aplicația dvs. funcționează. Testele funcționale privesc aplicația din punctul de vedere al utilizatorului și testează dacă sistemul funcționează conform așteptărilor.

Cum sa incepeti testarea in unitate a codului JavaScript

În diagrama de mai sus, vedeți că testele unitare constituie baza mare a suitei de testare a aplicației dvs. De obicei, acestea sunt mici, sunt multe și sunt executate automat.

Așadar, acum să intrăm în testele unitare mai puțin detaliat.

De ce ar trebui să mă deranjez testele unității de scriere?

Ori de câte ori îi întreb dezvoltatorilor dacă au scris teste pentru aplicația lor, ei îmi spun mereu: „Nu am avut timp pentru ei” sau „Nu am nevoie de ei, știu că funcționează”.

Așa că zâmbesc politicos și le spun ce vreau să vă spun. Testele unitare nu sunt doar teste. Ele vă ajută și în alte moduri, astfel încât să puteți:

Aveți încredere că codul dvs. funcționează. Când ați comis ultima dată o modificare a codului, versiunea dvs. a eșuat și jumătate din aplicația dvs. a încetat să funcționeze? A mea a fost săptămâna trecută.

Dar asta este în continuare OK. Adevărata problemă este când versiunea reușește, schimbarea este implementată și aplicația dvs. începe să fie instabilă.

Când se întâmplă acest lucru, începeți să vă pierdeți încrederea în cod și, în cele din urmă, vă rugați doar ca aplicația să funcționeze. Testele unitare vă vor ajuta să descoperiți probleme mult mai repede și să câștigați încredere.

Luați decizii arhitecturale mai bune. Modificări de cod, dar unele decizii cu privire la platformă, module, structură și altele trebuie luate în primele etape ale unui proiect.

Când începeți să vă gândiți la testarea unității chiar la început, vă va ajuta să vă structurați codul mai bine și să realizați o separare adecvată a preocupărilor. Nu veți fi tentați să atribuiți mai multe responsabilități blocurilor de coduri individuale, deoarece acestea ar fi un coșmar pentru testarea unității.

Identificați funcționalitatea înainte de codificare. Scrii semnătura metodei și începi să o implementezi imediat. Oh, dar ce ar trebui să se întâmple în cazul în care un parametru este nul? Ce se întâmplă dacă valoarea sa este în afara intervalului așteptat sau conține prea multe caractere? Arunci o excepție sau returnezi nul?

Testele unitare vă vor ajuta să descoperiți toate aceste cazuri. Uită-te din nou la întrebări și vei descoperi că este exact ceea ce definește cazurile de testare unitară.

Sunt sigur că există mult mai multe avantaje la scrierea testelor unitare. Acestea sunt doar cele pe care mi le amintesc din experiența mea. Cei pe care i-am învățat din greu.

Cum să scrii primul tău test JavaScript

Dar să revenim la JavaScript. Vom începe cu Glumă, care este un cadru de testare JavaScript. Este un instrument care permite testarea automată a unității, asigură acoperirea codului și ne permite să batem cu ușurință obiecte. Jest are, de asemenea, o extensie pentru Visual Studio Code disponibil aici.

Există și alte cadre, dacă sunteți interesat, le puteți verifica Acest articol.

npm i jest --save-dev

Să folosim metoda menționată anterior getAboutUsLink ca implementare dorim să testăm:

const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){
    switch (language.toLowerCase()){
      case englishCode.toLowerCase():
        return '/about-us';
      case spanishCode.toLowerCase():
        return '/acerca-de';
    }
    return '';
}
module.exports = getAboutUsLink;

Am pus asta în index.js fişier. Putem scrie teste în același fișier, dar o bună practică este separarea testelor unitare într-un fișier dedicat.

Modelele comune de denumire includ {filename}.test.js și {filename}.spec.js. Am folosit primul, index.test.js:

const getAboutUsLink = require("./index");
test("Returns about-us for english language", () => {
    expect(getAboutUsLink("en-US")).toBe("/about-us");
});

În primul rând, trebuie să importăm funcția pe care dorim să o testăm. Fiecare test este definit ca o invocare a test funcţie. Primul parametru este numele testului pentru referință. Cealaltă este o funcție săgeată în care numim funcția pe care vrem să o testăm și specificăm rezultatul pe care îl așteptăm. Eu

în acest caz, îl sunăm getAboutUsLink funcționează cu en-US ca parametru de limbă. Ne așteptăm ca rezultatul să fie /about-us.

Acum putem instala Jest CLI la nivel global și putem rula testul:

npm i jest-cli -g
jest

Dacă vedeți o eroare legată de configurare, asigurați-vă că aveți package.json fișier prezent. În caz contrar, generați unul folosind npm init.

Ar trebui să vedeți așa ceva:

 PASS  ./index.test.js
  √ Returns about-us for english language (4ms)
  console.log index.js:15
    /about-us
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.389s

Buna treaba! Acesta a fost primul test de unitate JavaScript simplu de la început până la sfârșit. Dacă ați instalat extensia Visual Studio Code, aceasta va rula testele automat odată ce salvați un fișier. Să încercăm prin extinderea testului cu această linie:

expect(getAboutUsLink("cs-CZ")).toBe("/o-nas");

Odată ce salvați fișierul, Jest vă va informa că testul a eșuat. Acest lucru vă ajută să descoperiți potențiale probleme chiar înainte de a comite modificările.

Testarea funcționalității avansate și a serviciilor de batjocură

În viața reală, codurile de limbă pentru metoda getAboutUsLink nu ar fi constante în același fișier. Valoarea lor este de obicei utilizată pe tot parcursul proiectului, astfel încât acestea să fie definite în propriul modul și importate în toate funcțiile care le utilizează.

import { englishCode, spanishCode } from './LanguageCodes'

Puteți importa aceste constante în test în același mod. Dar situația se va complica dacă lucrați cu obiecte în loc de constante simple. Aruncați o privire la această metodă:

import { UserStore } from './UserStore'
function getUserDisplayName(){
  const user = UserStore.getUser(userId);
  return `${user.LastName}, ${user.FirstName}`;
}

Această metodă utilizează importate UserStore:

class User {
    getUser(userId){
        // logic to get data from a database
    }
    setUser(user){
        // logic to store data in a database
    }
}
let UserStore = new User();
export { UserStore }

Pentru a testa în mod corespunzător această metodă, trebuie să ne batem joc UserStore. O batjocură înlocuiește obiectul original. Ne permite să separăm dependențele și datele reale de implementarea metodei testate, la fel ca manechinii care ajută la testele de avarie ale mașinilor în loc de oameni reali.

Dacă nu am folosi mock-ul, am testa atât această funcție, cât și magazinul. Acesta ar fi un test de integrare și probabil că va trebui să batjocorim baza de date utilizată.

Batjocorind un serviciu

Pentru a bate joc de obiecte, puteți furniza o funcție de batjocură sau o batjocură manuală. Mă voi concentra asupra acestuia din urmă, deoarece am un caz de utilizare simplu și simplu. Dar simțiți-vă liber să verificați alte posibilități de batjocură pe care le oferă Jest.

jest.mock('./UserStore', () => ({
    UserStore: ({
        getUser: jest.fn().mockImplementation(arg => ({
            FirstName: 'Ondrej',
            LastName: 'Polesny'
        })),
        setUser: jest.fn()
    })
}));

În primul rând, trebuie să specificăm ce ne batjocorim – ./UserStore modul. Apoi, trebuie să returnăm mock-ul care conține toate obiectele exportate din acel modul.

În acest eșantion, este doar User obiect numit UserStore cu funcția getUser. Dar cu implementări reale, simularea poate fi mult mai lungă. Orice funcție care nu vă pasă cu adevărat în domeniul testării unitare poate fi ușor batjocorită jest.fn().

Testul de unitate pentru getUserDisplayName funcția este similară cu cea pe care am creat-o înainte:

test("Returns display name", () => {
    expect(getUserDisplayName(1)).toBe("Polesny, Ondrej");
})

De îndată ce salvez fișierul, Jest îmi spune că am 2 teste de promovare. Dacă executați teste manual, faceți acest lucru acum și asigurați-vă că vedeți același rezultat.

Raport de acoperire a codului

Acum, că știm cum să testăm codul JavaScript, este bine să acoperim cât mai mult cod posibil cu testele. Și asta este greu de făcut. În cele din urmă, suntem doar oameni. Vrem să ne îndeplinim sarcinile, iar testele unitare produc de obicei o sarcină nedorită pe care tindem să o trecem cu vederea. Acoperirea codului este un instrument care ne ajută să combatem acest lucru.

Acoperirea codului vă va spune cât de mare este acoperită o parte din codul dvs. de testele unitare. Luați de exemplu primul meu test de unitate verificând getAboutUsLink funcţie:

test("Returns about-us for english language", () => {
   expect(getAboutUsLink("en-US")).toBe("/about-us");
});

Verifică linkul în limba engleză, dar versiunea în spaniolă rămâne netestată. Acoperirea codului este de 50%. Celălalt test de unitate verifică getDisplayName funcționează bine și acoperirea codului său este de 100%. Împreună, acoperirea totală a codului este de 67%. Am testat 3 cazuri de utilizare, dar testele noastre acoperă doar 2 dintre ele.

Pentru a vedea raportul de acoperire a codului, tastați următoarea comandă în terminal:

jest --coverage

Sau, dacă utilizați Visual Studio Code cu extensia Jest, puteți rula comanda (CTRL + SHIFT + P) Glumă: Comutați acoperirea acoperirii. Vă va arăta chiar în implementare ce linii de cod nu sunt acoperite cu teste.

1611700208 299 Cum sa incepeti testarea in unitate a codului JavaScript

Executând verificarea acoperirii, Jest va crea și un raport HTML. Găsiți-l în dosarul proiectului dvs. sub coverage/lcov-report/index.html.

1611700208 718 Cum sa incepeti testarea in unitate a codului JavaScript

Acum, nu trebuie să menționez că ar trebui să depuneți eforturi pentru a acoperi 100% codul, nu? 🙂

rezumat

În acest articol, v-am arătat cum să începeți cu testarea unităților în JavaScript. Deși este plăcut ca acoperirea codului dvs. să strălucească la 100% în raport, în realitate, nu este întotdeauna posibil să ajungeți (în mod semnificativ) acolo. Scopul este de a permite testelor unitare să vă ajute să vă mențineți codul și să vă asigurați că funcționează întotdeauna conform intenției. Acestea vă permit să:

  • definirea clară a cerințelor de implementare,
  • proiectați-vă mai bine codul și preocupări separate,
  • descoperiți problemele pe care le puteți introduce cu cele mai noi angajamente,
  • și vă oferă încredere că funcționează codul dvs.

Cel mai bun loc pentru a începe este Noțiuni de bază pagina din documentația Jest, astfel încât să puteți încerca singuri aceste practici.

Aveți propria experiență cu codul de testare? Mi-ar plăcea să-l aud, anunțați-mă mai departe Stare de nervozitate sau alăturați-vă unuia dintre a mea Fluxuri de contracție.