Mindannyian tudjuk, hogy egység teszteket kellene írnunk. De nehéz megtudni, hogy hol kezdjem és mennyi időt fordítsunk a tesztekre a tényleges megvalósításhoz képest. Szóval, hol kezdjem? És csak a kód teszteléséről van szó, vagy van-e más előnye az egység teszteknek?
Ebben a cikkben elmagyarázom a különböző típusú teszteket, és azt, hogy milyen előnyökkel jár az egység tesztelése a fejlesztő csapatok számára. Bemutatom a Jest - egy JavaScript tesztelési keretrendszert.
Különböző típusú vizsgálatok
Mielőtt belevetnénk magukat az egységtesztelési sajátosságokba, szeretnék gyorsan végigvezetni a különféle típusú teszteken. Gyakran van némi zavart körülöttük, és nem csodálkozom. Néha a vonal közöttük elég vékony.
Egységvizsgálatok
Az egységtesztek csak a megvalósítás egyetlen részét tesztelik. Egy egység. Nincsenek függőségek vagy integrációk, nincsenek keretrendszeri sajátosságok. Olyanok, mint egy módszer, amely egy linket ad vissza egy adott nyelven:
export function getAboutUsLink(language){ switch (language.toLowerCase()){ case englishCode.toLowerCase(): return '/about-us'; case spanishCode.toLowerCase(): return '/acerca-de'; } return ''; }
Integrációs tesztek
Egy bizonyos ponton a kód kommunikál egy adatbázissal, fájlrendszerrel vagy más harmadik féllel. Ez akár egy másik modul is lehet az alkalmazásában.
Ezt a megvalósítást integrációs tesztekkel kell tesztelni. Általában bonyolultabb beállításokkal rendelkeznek, amelyek tesztkörnyezetek előkészítését, a függőségek inicializálását stb.
Funkcionális tesztek
Az egységtesztek és az integrációs tesztek biztosak abban, hogy alkalmazásod működik. A funkcionális tesztek az alkalmazást a felhasználó szemszögéből vizsgálják, és tesztelik, hogy a rendszer az elvárt módon működik-e.

A fenti ábrán látható, hogy az egységtesztek jelentik az alkalmazás tesztkészletének nagy alapját. Jellemzően kicsik, sok van belőlük, és automatikusan végrehajtásra kerülnek.
Tehát most térjünk rá egy kicsit részletesebben az egységtesztekre.
Miért kell megkönnyítenem az íróegység-teszteket?
Amikor megkérdezem a fejlesztőket, hogy írtak-e teszteket az alkalmazásukhoz, mindig azt mondják nekem: "Nem volt időm rájuk" vagy "Nincs szükségem rájuk, tudom, hogy működik."
Tehát udvariasan elmosolyodom, és elmondom nekik, mit akarok neked mondani. Az egységvizsgálatok nem csak a tesztelésről szólnak. Más módon is segítenek, így:
Legyen biztos abban, hogy a kód működik. Mikor hajtott végre utoljára kódmódosítást, az összeállítás sikertelen volt, és az alkalmazás fele leállt? Az enyém a múlt héten volt.
De ez így is rendben van. Az igazi probléma az, amikor az összeállítás sikeres, a változás telepítésre kerül, és az alkalmazásod instabillá válik.
Amikor ez megtörténik, kezdi elveszteni a bizalmát a kód iránt, és végül csak imádkozni kell az alkalmazás működéséért. Az egységtesztek segítenek sokkal hamarabb felfedezni a problémákat és megszerezni a bizalmat.
Jobb építészeti döntéseket hozzon. A kód megváltozik, de a platformmal, modulokkal, felépítéssel és másokkal kapcsolatos döntéseket a projekt korai szakaszában kell meghozni.
Amikor már az elején elkezdi gondolkodni az egység tesztelésén, az segít jobban felépíteni a kódot, és el tudja érni az aggályokat. Nem lesz kísértés, hogy több felelősséget rendeljen egyetlen kódblokkhoz, mivel ez rémálom lenne az egységteszten.
Pontos funkcionalitás a kódolás előtt. Megírja a módszer aláírását, és azonnal elkezdi végrehajtani. Ja, de mi történjen abban az esetben, ha egy paraméter null? Mi van, ha értéke meghaladja a várt tartományt, vagy túl sok karaktert tartalmaz? Kivételt dobsz, vagy nullát adsz vissza?
Az egységvizsgálatok segítenek felfedezni ezeket az eseteket. Nézze meg újra a kérdéseket, és rájön, hogy pontosan ez határozza meg az egység tesztjeit.
Biztos vagyok benne, hogy sokkal több előnye van az egységtesztek írásának. Csak ezekre emlékszem vissza a tapasztalataimból. Azokat, akiket megtanultam.
Hogyan írhatjuk meg az első JavaScript egység tesztet
De térjünk vissza a JavaScript-re. Kezdjük a Jest-lel, amely egy JavaScript tesztelési keretrendszer. Ez egy olyan eszköz, amely lehetővé teszi az egységek automatikus tesztelését, kód lefedettséget biztosít, és lehetővé teszi számunkra az objektumok gúnyolódását. A Jestnek itt is elérhető a Visual Studio Code kiterjesztése.
Vannak más keretrendszerek is, ha érdekli, ellenőrizheti őket ebben a cikkben.
npm i jest --save-dev
Használjuk a korábban említett módszert getAboutUsLink
megvalósításként, amelyet tesztelni akarunk:
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;
Ezt betettem az index.js
aktába. Teszteket ugyanabba a fájlba írhatunk, de jó gyakorlat az egységtesztek külön fájlba szétválasztása.
A gyakori elnevezési minták közé tartozik {filename}.test.js
és {filename}.spec.js
. Az elsőt használtam index.test.js
:
const getAboutUsLink = require("./index"); test("Returns about-us for english language", () => { expect(getAboutUsLink("en-US")).toBe("/about-us"); });
Először be kell importálnunk a tesztelni kívánt funkciót. Minden tesztet a test
függvény meghívásaként definiálunk . Az első paraméter a referencia tesztjének neve. A másik egy nyílfüggvény, ahol felhívjuk a tesztelni kívánt függvényt, és meghatározzuk, hogy melyik eredményre számítunk. én
Ebben az esetben a getAboutUsLink
függvényt hívjuk meg en-US
nyelvi paraméterként. Várjuk az eredményt /about-us
.
Most globálisan telepíthetjük a Jest CLI-t és futtathatjuk a tesztet:
npm i jest-cli -g jest
Ha konfigurációval kapcsolatos hibát lát, győződjön meg róla, hogy a package.json
fájlja jelen van. Ha nem, generál egyet a npm init
.
Valami ilyesmit kellene látnia:
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
Nagyszerű munka! Ez volt az első egyszerű JavaScript egység teszt az elejétől a végéig. Ha telepítette a Visual Studio Code kiterjesztést, akkor a fájl mentése után a tesztek automatikusan lefutnak. Próbálja ki úgy, hogy kibővíti a tesztet ezzel a sorral:
expect(getAboutUsLink("cs-CZ")).toBe("/o-nas");
A fájl mentése után a Jest tájékoztatja Önt arról, hogy a teszt nem sikerült. Ez segít még a változtatások végrehajtása előtt felfedezni a lehetséges problémákat.
Fejlett funkcionalitás és gúnyos szolgáltatások tesztelése
A való életben a getAboutUsLink metódus nyelvi kódjai nem lennének konstansok ugyanabban a fájlban. Értéküket általában a projekt során használják, így a saját moduljukban definiálják őket, és importálják azokat az összes funkcióba, amely használja őket.
import { englishCode, spanishCode } from './LanguageCodes'
Ugyanúgy importálhatja ezeket az állandókat a tesztbe. De a helyzet bonyolultabbá válik, ha egyszerű állandók helyett objektumokkal dolgozol. Vessen egy pillantást erre a módszerre:
import { UserStore } from './UserStore' function getUserDisplayName(){ const user = UserStore.getUser(userId); return `${user.LastName}, ${user.FirstName}`; }
Ez a módszer importált adatokat használ 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 }
Annak érdekében, hogy ezt a módszert egységesen teszteljük, gúnyolódnunk kell UserStore
. A gúny az eredeti objektum helyettesítője. Ez lehetővé teszi számunkra a függőségek és a valós adatok elválasztását a tesztelt módszer megvalósításától, ahogyan a próbabábuk is segítenek az autók ütközési tesztjeiben, valódi emberek helyett.
Ha nem használnánk a modellt, akkor ezt a funkciót és az áruházat is tesztelnénk. Ez egy integrációs teszt lenne, és valószínűleg meg kell csúfolnunk a használt adatbázist.
Szolgáltatás gúnyolása
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.
Do you have your own experience with testing code? I'd love to hear it, let me know on Twitter or join one of my Twitch streams.