Kaip pradėti testuoti „JavaScript“ kodą

Mes visi žinome, kad turėtume parašyti vieneto testus. Tačiau sunku žinoti, nuo ko pradėti ir kiek laiko skirti bandymams, palyginti su realiu įgyvendinimu. Taigi, nuo ko pradėti? Ar tai tik apie kodo testavimą, ar vieneto testai turi kitų privalumų?

Šiame straipsnyje paaiškinsiu įvairius bandymų tipus ir tai, kokią naudą vieneto bandymai duoda kūrimo komandoms. Aš pristatysiu „Jest“ - „JavaScript“ testavimo sistemą.

Skirtingi bandymų tipai

Prieš pasinerdami į vieneto testavimo ypatumus, noriu greitai atlikti skirtingų tipų bandymus. Aplink juos dažnai kyla painiava ir aš nesistebiu. Kartais linija tarp jų yra gana plona.

Vieneto bandymai

Vieneto testai tikrina tik vieną jūsų įgyvendinimo dalį. Vienetas. Jokių priklausomybių ar integracijų, jokios sistemos specifikos. Jie panašūs į metodą, kuris pateikia nuorodą konkrečia kalba:

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

Integracijos testai

Tam tikru momentu jūsų kodas bendrauja su duomenų baze, failų sistema ar kita trečiąja šalimi. Tai netgi gali būti kitas jūsų programos modulis.

Tas įgyvendinimas turėtų būti išbandytas integracijos testais. Paprastai jie turi sudėtingesnę sąranką, kurią sudaro bandomosios aplinkos paruošimas, priklausomybių inicijavimas ir pan.

Funkciniai bandymai

Vieneto testai ir integracijos testai suteikia jums pasitikėjimo, kad jūsų programa veikia. Funkciniai testai žiūri į programą vartotojo požiūriu ir patikrina, ar sistema veikia taip, kaip tikėtasi.

Aukščiau pateiktoje diagramoje matote, kad vieneto testai sudaro didelę jūsų programos testavimo paketo dalį. Paprastai jie yra maži, jų yra daug ir jie vykdomi automatiškai.

Taigi dabar pereikime prie detalių bandymų kiek išsamiau.

Kodėl turėčiau trukdyti rašymo vieneto testams?

Kaskart, kai klausiu kūrėjų, ar jie parašė savo programos testus, jie man visada sako: „Aš neturėjau jiems laiko“ arba „Man jų nereikia, aš žinau, kad tai veikia“.

Taigi mandagiai šypsausi ir sakau jiems, ką noriu jums pasakyti. Vieneto testai nėra tik bandymai. Jie jums padeda ir kitais būdais, todėl galite:

Būkite tikri, kad jūsų kodas veikia. Kada paskutinį kartą keitėte kodą, nepavyko sukurti ir pusė programos nustojo veikti? Mano buvo praėjusią savaitę.

Bet tai vis tiek gerai. Tikroji problema yra ta, kai sukūrimas pavyksta, pakeitimas įdiegtas ir jūsų programa pradeda būti nestabili.

Kai tai atsitiks, jūs pradėsite prarasti pasitikėjimą savo kodu ir galų gale tiesiog melstis, kad programa veiktų. Vieneto testai padės greičiau atrasti problemas ir įgyti pasitikėjimo savimi.

Priimkite geresnius architektūrinius sprendimus. Kodas keičiasi, tačiau kai kuriuos sprendimus dėl platformos, modulių, struktūros ir kitus reikia priimti ankstyvaisiais projekto etapais.

Kai pradėsite galvoti apie vieneto bandymą, tai padės geriau susisteminti kodą ir tinkamai atskirti rūpesčius. Jums nebus gundoma priskirti kelias atsakomybes vieno kodo blokams, nes tai būtų košmaras bandant vienetą.

Tiksliai nustatykite funkcionalumą prieš koduodami. Jūs parašote metodo parašą ir iškart pradedate jį įgyvendinti. O, bet kas turėtų atsitikti, jei parametras yra nulinis? Ką daryti, jei jo vertė yra už numatyto diapazono ribų arba joje yra per daug simbolių? Metate išimtį ar grąžinate niekinę?

Vieneto testai padės atrasti visus šiuos atvejus. Dar kartą pažiūrėkite į klausimus ir pamatysite, kad būtent tai apibrėžia jūsų vieneto bandymo atvejus.

Esu įsitikinęs, kad vieneto testų rašymas turi daug daugiau privalumų. Tai tik tie, kuriuos prisimenu iš savo patirties. Tie, kuriuos išmokau sunkiai.

Kaip parašyti pirmąjį „JavaScript“ vieneto testą

Bet grįžkime prie „JavaScript“. Pradėsime nuo „Jest“, kuris yra „JavaScript“ testavimo sistema. Tai įrankis, leidžiantis atlikti automatinį vieneto testavimą, aprėpiantis kodą ir leidžiantis lengvai tyčiotis iš objektų. „Jest“ taip pat turi „Visual Studio Code“ plėtinį, kurį galite rasti čia.

Taip pat yra ir kitų sistemų, jei jus domina, galite jas patikrinti šiame straipsnyje.

npm i jest --save-dev 

Panaudokime anksčiau minėtą metodą getAboutUsLinkkaip įgyvendinimą, kurį norime išbandyti:

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; 

Įdėjau tai į index.jsbylą. Testus galime rašyti tame pačiame faile, tačiau gera praktika yra padalinti testus į tam skirtą failą.

Bendri vardų davimo modeliai yra {filename}.test.jsir {filename}.spec.js. Aš naudojau pirmąjį index.test.js:

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

Pirmiausia turime importuoti funkciją, kurią norime išbandyti. Kiekvienas testas apibrėžiamas kaip testfunkcijos iškvietimas . Pirmasis parametras yra jūsų nuorodos bandymo pavadinimas. Kita yra rodyklės funkcija, kai mes vadiname norimą išbandyti funkciją ir nurodome, kurio rezultato tikimės. Aš

Šiuo atveju kalbos parametru vadiname getAboutUsLinkfunkciją en-US. Mes tikimės, kad rezultatas bus /about-us.

Dabar mes galime įdiegti „Jest“ CLI visame pasaulyje ir paleisti testą:

npm i jest-cli -g jest 

Jei matote su konfigūracija susijusią klaidą, įsitikinkite, kad turite package.jsonfailą. Jei to nepadarysite, sugeneruokite vieną naudodami npm init.

Turėtumėte pamatyti kažką tokio:

 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 

Puikus darbas! Tai buvo pirmasis paprastas „JavaScript“ vieneto testas nuo pradžios iki pabaigos. Jei įdiegėte „Visual Studio Code“ plėtinį, bandymai bus vykdomi automatiškai, kai išsaugosite failą. Pabandykime pratęsdami testą šia eilute:

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

Kai išsaugosite failą, Jestas informuos jus, kad bandymas nepavyko. Tai padeda atrasti galimas problemas dar prieš atliekant pakeitimus.

Išplėstinio funkcionalumo ir pašaipos paslaugų testavimas

Realiame gyvenime „getAboutUsLink“ metodo kalbos kodai nebūtų to paties failo konstantos. Jų vertė paprastai naudojama visame projekte, todėl jie bus apibrėžti jų pačių modulyje ir importuoti į visas jas naudojančias funkcijas.

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

Šias konstantas galite importuoti į testą tokiu pačiu būdu. Bet situacija taps dar sudėtingesnė, jei dirbsite su objektais, o ne su paprastomis konstantomis. Pažvelkite į šį metodą:

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

Šiuo metodu naudojami importuoti 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 } 

Norint tinkamai išbandyti šį metodą, turime tyčiotis UserStore. Pasityčiojimas yra originalaus objekto pakaitalas. Tai leidžia mums atskirti priklausomybes ir tikrus duomenis nuo išbandyto metodo įgyvendinimo, kaip ir manekenai padeda tikrinant automobilius, o ne realius žmones.

Jei nenaudotume maketo, išbandytume ir šią funkciją, ir parduotuvę. Tai būtų integracijos testas, ir mums greičiausiai reikės pašiepti naudotą duomenų bazę.

Pasityčiojimas iš paslaugos

To mock objects, you can either provide a mocking function or a manual mock. I will focus on the latter as I have a plain and simple use-case. But feel free to check out other mocking possibilities Jest provides.

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

First, we need to specify what are we mocking - the ./UserStore module. Next, we need to return the mock that contains all exported objects from that module.

In this sample, it's only the User object named UserStore with the function getUser. But with real implementations, the mock may be much longer. Any functions you don't really care about in the scope of unit testing can be easily mocked with jest.fn().

The unit test for the getUserDisplayName function is similar to the one we created before:

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

As soon as I save the file, Jest tells me I have 2 passing tests. If you're executing tests manually, do so now and make sure you see the same result.

Code Coverage Report

Now that we know how to test JavaScript code, it's good to cover as much code as possible with tests. And that is hard to do. In the end, we're just people. We want to get our tasks done and unit tests usually yield an unwanted workload that we tend to overlook. Code coverage is a tool that helps us fight that.

Code coverage will tell you how big a portion of your code is covered by unit tests. Take for example my first unit test checking the getAboutUsLink function:

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

It checks the English link, but the Spanish version stays untested. The code coverage is 50%. The other unit test is checking the getDisplayName function thoroughly and its code coverage is 100%. Together, the total code coverage is 67%. We had 3 use cases to test, but our tests only cover 2 of them.

To see the code coverage report, type the following command into the terminal:

jest --coverage 

Or, if you're using Visual Studio Code with the Jest extension, you can run the command (CTRL+SHIFT+P) Jest: Toggle Coverage Overlay. It will show you right in the implementation which lines of code are not covered with tests.

By running the coverage check, Jest will also create an HTML report. Find it in your project folder under coverage/lcov-report/index.html.

Now, I don't have to mention that you should strive for 100% code coverage, right? :-)

Summary

In this article, I showed you how to start with unit testing in JavaScript. While it's nice to have your code coverage shine at 100% in the report, in reality, it's not always possible to (meaningfully) get there. The goal is to let unit tests help you maintain your code and ensure it always works as intended. They enable you to:

  • clearly define implementation requirements,
  • better design your code and separate concerns,
  • discover issues you may introduce with your newer commits,
  • and give you confidence that your code works.

The best place to start is the Getting started page in the Jest documentation so you can try out these practices for yourself.

Ar turite savo patirties bandant kodą? Labai norėčiau tai išgirsti, praneškite man „Twitter“ ar prisijungčiau prie vieno iš savo „Twitch“ srautų.