Kuidas alustada JavaScripti koodi testimist

Me kõik teame, et peaksime kirjutama ühikutestid. Kuid on raske teada, kust alustada ja kui palju aega testidele pühendada, võrreldes tegeliku rakendusega. Niisiis, kust alustada? Ja kas see puudutab ainult koodi testimist või on ühikutestidel muid eeliseid?

Selles artiklis selgitan erinevaid testide tüüpe ja seda, milliseid eeliseid üksuste testimine arendusmeeskondadele toob. Esitan Jesti - JavaScripti testimisraamistiku.

Erinevat tüüpi testimine

Enne kui uurime üksuste testimise spetsiifikat, tahan läbi viia erinevat tüüpi testide kiire läbivaatamise. Nende ümber on sageli segadust ja ma ei imesta. Mõnikord on nende vaheline piir üsna õhuke.

Ühikutestid

Ühikutestid testivad ainult ühte osa teie rakendusest. Ühik. Ei sõltuvusi ega integratsioone, raamistiku spetsiifikat. Need on nagu meetod, mis tagastab lingi kindlas keeles:

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

Integreerimiskatsed

Mingil hetkel suhtleb teie kood andmebaasi, failisüsteemi või mõne muu kolmanda osapoolega. See võib olla isegi mõni muu moodul teie rakenduses.

Seda rakenduse osa tuleks testida integreerimistestidega. Neil on tavaliselt keerukam seadistus, mis hõlmab testimiskeskkondade ettevalmistamist, sõltuvuste lähtestamist jne.

Funktsionaalsed testid

Ühikutestid ja integreerimistestid annavad teile kindluse, et teie rakendus töötab. Funktsionaalsed testid vaatavad rakendust kasutaja vaatenurgast ja kontrollivad, kas süsteem töötab ootuspäraselt.

Ülaltoodud diagrammil näete, et ühikutestid moodustavad teie rakenduse testimiskomplekti suure aluse. Tavaliselt on need väikesed, neid on palju ja need täidetakse automaatselt.

Nii et nüüd läheme üksuste testidesse natuke üksikasjalikumalt.

Miks peaksin kirjutusüksuse katseid häirima?

Alati, kui küsin arendajatelt, kas nad kirjutasid oma rakenduse jaoks teste, ütlevad nad mulle alati: "Mul ei olnud nende jaoks aega" või "Ma ei vaja neid, ma tean, et see töötab".

Nii et naeratan viisakalt ja ütlen neile, mida ma teile öelda tahan. Ühikutestid pole ainult testimine. Need aitavad teid ka muul viisil, nii et saate:

Ole kindel, et kood töötab. Millal viimati koodimuudatust tegite, ebaõnnestus teie koostamine ja pool teie rakendusest lakkas töötamast? Minu oma oli eelmine nädal.

Aga see on ikkagi OK. Tõeline probleem on siis, kui ehitamine õnnestub, muudatus juurutatakse ja teie rakendus hakkab olema ebastabiilne.

Kui see juhtub, hakkate kaotama usaldust oma koodi vastu ja palvetate lihtsalt rakenduse töötamise eest. Ühikutestid aitavad teil palju varem probleeme avastada ja enesekindlust juurde saada.

Tehke paremaid arhitektuurilisi otsuseid. Kood muutub, kuid mõned otsused platvormi, moodulite, struktuuri ja teiste osas tuleb teha projekti varases staadiumis.

Kui hakkate kohe alguses mõtlema üksuste testimise peale, aitab see teil oma koodi paremini struktureerida ja mured korralikult lahutada. Teil pole kiusatust määrata ühele koodiplokile mitu vastutust, kuna see oleks üksustestide jaoks õudusunenägu.

Täpsem funktsionaalsus enne kodeerimist. Kirjutate meetodi allkirja ja hakkate seda kohe rakendama. Oh, aga mis peaks juhtuma juhul, kui parameeter on null? Mis siis, kui selle väärtus jääb oodatud vahemikust väljapoole või sisaldab liiga palju märke? Kas viskate erandi või tagastate nulli?

Ühikutestid aitavad teil kõiki neid juhtumeid avastada. Vaadake küsimusi uuesti ja leiate, et see määrab täpselt teie üksuse testimise juhtumid.

Olen kindel, et üksustestide kirjutamisel on palju rohkem eeliseid. Need on just need, mida oma kogemustest meenutan. Need, mida ma õppisin raskelt.

Kuidas kirjutada oma esimene JavaScripti üksuse test

Kuid naaseme JavaScripti juurde. Alustame Jestist, mis on JavaScripti testimise raamistik. See on tööriist, mis võimaldab seadmete automaatset testimist, tagab koodide katvuse ja võimaldab meil objekte lihtsalt mõnitada. Jestil on siin saadaval ka Visual Studio koodi laiendus.

On ka muid raamistikke. Kui olete huvitatud, saate neid selles artiklis kontrollida.

npm i jest --save-dev 

Kasutame eelnevalt mainitud meetodit getAboutUsLinkrakendusena, mida soovime testida:

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; 

Panin selle index.jstoimikusse. Teste saame kirjutada samasse faili, kuid hea tava on eraldada üksustestid spetsiaalsesse faili.

Levinud nimemustrid hõlmavad {filename}.test.jsja {filename}.spec.js. Kasutasin esimest index.test.js:

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

Esiteks peame importima funktsiooni, mida soovime testida. Iga test on defineeritud kui testfunktsiooni kutsumine . Esimene parameeter on teie viite jaoks testi nimi. Teine on noolefunktsioon, kus kutsume funktsiooni, mida soovime testida, ja täpsustame, millist tulemust ootame. Mina

Sel juhul kutsume keele parameetriks getAboutUsLinkfunktsiooni en-US. Eeldame, et tulemus on /about-us.

Nüüd saame Jesti CLI globaalselt installida ja testi käivitada:

npm i jest-cli -g jest 

Kui näete konfiguratsiooniga seotud tõrke, veenduge, et teie package.jsonfail oleks olemas. Kui te seda ei tee, genereerige üks, kasutades npm init.

Peaksite nägema midagi sellist:

 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 

Suurepärane töö! See oli esimene lihtne JavaScripti üksuse test algusest lõpuni. Kui installisite laienduse Visual Studio Code, käivitab see faili salvestamisel testid automaatselt. Proovime seda, laiendades testi selle reaga:

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

Kui olete faili salvestanud, teatab Jest teile, et test ebaõnnestus. See aitab teil võimalikke probleeme avastada juba enne muudatuste tegemist.

Täiustatud funktsionaalsuse ja pilkamisteenuste testimine

Reaalses elus ei oleks meetodi getAboutUsLink keelekoodid konstantsed samas failis. Nende väärtust kasutatakse tavaliselt kogu projekti vältel, nii et need määratletakse nende enda moodulis ja imporditakse kõikidesse neid kasutavatesse funktsioonidesse.

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

Need konstandid saate testisse importida samamoodi. Kuid olukord muutub keerulisemaks, kui töötate objektide asemel lihtsate konstantide asemel. Vaadake seda meetodit:

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

See meetod kasutab imporditud 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 } 

Selle meetodi nõuetekohaseks testimiseks peame mõnitama UserStore. Mõnitamine on algse objekti asendaja. See võimaldab meil testitud meetodi rakendamisest eraldada sõltuvused ja tegelikud andmed täpselt nii, nagu mannekeenid aitavad tegelike inimeste asemel autode kokkupõrketestides.

Kui me ei kasutanud mõnitamist, testime nii seda funktsiooni kui ka poodi. See oleks integreerimiskatse ja tõenäoliselt peaksime kasutatud andmebaasi mõnitama.

Teenuse mõnitamine

Objektide mõnitamiseks võite pakkuda kas mõnitamise funktsiooni või käsitsi mõnitamist. Keskendun viimasele, kuna mul on selge ja lihtne kasutusjuht. Kuid tutvuge julgelt teiste Jesti pakutavate mõnitamisvõimalustega.

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

Esiteks peame täpsustama, mida me mõnitame - ./UserStoremoodulit. Järgmisena peame tagastama maketi, mis sisaldab kõiki selle mooduli eksporditud objekte.

Selles valimis on see ainult funktsiooniga nimetatud Userobjekt . Kuid tegelike rakenduste korral võib mõnitamine olla palju pikem. Kõiki funktsioone, mis teile üksuse testimise käigus tegelikult ei lähe, saab mõnitada .UserStoregetUserjest.fn()

Funktsiooni ühikutest getUserDisplayNameon sarnane sellega, mille lõime enne:

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

Niipea kui faili salvestan, ütleb Jest mulle, et mul on 2 testi. Kui teete teste käsitsi, tehke seda kohe ja veenduge, et näete sama tulemust.

Koodi katvuse aruanne

Nüüd, kui teame, kuidas JavaScripti koodi testida, on hea katta testidega võimalikult palju koodi. Ja seda on raske teha. Lõpuks oleme lihtsalt inimesed. Tahame oma ülesanded ära teha ja üksuste testid toovad tavaliselt kaasa soovimatu töökoormuse, millest kipume mööda vaatama. Koodide katvus on tööriist, mis aitab meil selle vastu võidelda.

Koodi katvus näitab teile, kui suure osa teie koodist katavad ühikutestid. Võtame näiteks minu esimese getAboutUsLinkfunktsiooni kontrollimise üksuse testi :

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.

Kas teil on koodi testimisega oma kogemus? Mulle meeldiks seda kuulda, andke mulle Twitteris teada või liituksin ühe oma Twitchi vooguga.