Tester Node.js-koden med Mocha og Chai

Introduksjon

Å skrive enhetstester er noe både nybegynnere og erfarne ingeniører vanligvis utsetter for senere utviklingsfaser, men de er nøkkelen til stabil og robust programvareutvikling.

Den grunnleggende forutsetningen for testdrevet utvikling (TDD) skriver testene dine selv før du begynner å kode. Det er et flott mål å strebe etter, men det krever mye disiplin og planlegging når du prøver å følge prinsippene! For å gjøre hele denne prosessen mye enklere, kan du ty til brukervennlige og kraftige test- og påstandsrammeverk, som f.eks. Mocha og Chai.

I denne artikkelen vil vi starte med å introdusere deg for disse to bibliotekene og deretter vise deg hvordan du bruker dem sammen for raskt å lage lesbare og funksjonelle enhetstester.

Chai

Chai er et påstandsbibliotek som gir både BDD (atferdsdrevet utvikling) og TDD (testdrevet utvikling) programmeringsstiler for testing av kode, og er ment å være sammenkoblet med et testbibliotek som lar deg organisere tester. Det er veldig ofte sammenkoblet med Mokka.

Den har tre hoved-APIer:

  • should
  • expect
  • assert

var.should.equal(var2)


expect.var.to.be.equal(var2)


assert.equal(var1, var2)

Gjennom denne artikkelen vil vi fokusere på BDD-stilen ved å bruke Chai expect grensesnitt, selv om det er helt greit å bruke andre grensesnitt/stiler i henhold til din egen intuisjon. De assert grensesnittet er det mest like vanlige TDD-påstandsrammeverket.

expect bruker et veldig naturlig språk-API for å skrive påstandene dine, noe som vil gjøre testene dine lettere å skrive og forbedre senere på veien. Dette gjøres ved å lenke sammen getters for å lage og utføre påstanden, noe som gjør det enklere å oversette krav til kode:

let user = {name: 'Scott'};


expect(user).to.have.property('name');

OBS: Se hvordan du ganske mye kan lese påstanden på et naturlig språk og forstå hva som skjer? Det er en av hovedfordelene ved å bruke et påstandsbibliotek som Chai!

Noen flere eksempler på disse getterne er:

  • to
  • be
  • is
  • and
  • has
  • have

Ganske mange av disse getterne kan lenkes sammen og brukes med påstandsmetoder som true, ok, existog empty for å lage noen komplekse påstander på bare én linje:

"use strict";

const expect = require('chai').expect;


expect({}).to.exist;
expect(26).to.equal(26);
expect(false).to.be.false;
expect('hello').to.be.string;


expect([1, 2, 3]).to.not.be.empty;


expect([1, 2, 3]).to.have.length.of.at.least(3);

OBS: Du finner en fullstendig liste over tilgjengelige metoder her..

Du vil kanskje også sjekke ut listen over tilgjengelige plugins for Chai. Disse gjør det mye enklere å teste mer komplekse funksjoner.

Ta chai-http for eksempel, som er en plugin som hjelper deg med å teste serverruter:

"use strict";

const chai = require('chai');
const chaiHttp = require('chai-http');

chai.use(chaiHttp);

chai.request(app)
    .put('/api/auth')
    .send({username: '[email protected]', password: 'abc123'})
    .end(function(err, res) {
        expect(err).to.be.null;
        expect(res).to.have.status(200);
    });

Organisering av testsaker med Mokka – beskriv() og det()

Mocha er et testrammeverk for Node som gir deg fleksibiliteten til å kjøre asynkron (eller synkron) kode serielt. Eventuelle uoppdagede unntak vises ved siden av testsaken den ble kastet i, noe som gjør det enkelt å identifisere nøyaktig hva som feilet og hvorfor.

Det anbefales å installere Mocha globalt:

$ npm install mocha -g

Du vil at det skal være en global installasjon siden mocha kommandoen brukes til å kjøre testene for prosjektet i din lokale katalog.

Hva gjør denne kodebiten?

it() skal returnere X. it() definerer testtilfeller, og Mocha vil kjøre hver it() som en enhetstest. For å organisere flere enhetstester, kan vi describe() en felles funksjonalitet, og dermed struktur Mokka-tester.

Dette er sannsynligvis best beskrevet med et konkret eksempel:

"use strict";
const expect = require('chai').expect;

describe('Math', function() {
    describe('#abs()', function() {
        it('should return positive value of given negative number', function() {
            expect(Math.abs(-5)).to.be.equal(5);
        });
    });
});

describe() metode, definerte vi en testnavn, Kalt #abs(). Du kan også kjøre tester individuelt etter navnet deres – dette vil bli dekket senere.

OBS: Med Mokka-tester trenger du ikke det require() noen av Mokka-metodene. Disse metodene leveres globalt når de kjøres med mocha kommando.

For å kjøre disse testene, lagre filen og bruk mocha kommando:

$ mocha .

  Math
    #abs()
      ✓ should return positive value of given number 


  1 passing (9ms)

Utdataene er en oversikt over testene som ble kjørt og resultatene deres. Legg merke til hvordan nestet describe() anrop overføres til resultatet. Det er nyttig å ha alle testene for en gitt metode eller funksjon nestet sammen.

Disse metodene er grunnlaget for Mokka-testrammeverket. Bruk dem til å komponere og organisere testene dine slik du vil. Vi vil se ett eksempel på dette i neste avsnitt.

Skrive tester med Mokka og Chai

Den anbefalte måten å organisere testene dine i prosjektet på er å legge dem alle sammen /test katalog. Som standard ser Mocha etter enhetstester ved hjelp av globs ./test/*.js og ./test/*.coffee. Derfra vil den laste og kjøre alle filer som kaller describe() metoden.

Sjekk ut vår praktiske, praktiske guide for å lære Git, med beste praksis, bransjeaksepterte standarder og inkludert jukseark. Slutt å google Git-kommandoer og faktisk lære den!

Det er vanlig å suffikse testfilene med .test.js for kildefilene som inneholder Mokka-tester:

├── package.json
├── lib
│   ├── db.js
│   ├── models.js
│   └── util.js
└── test
    ├── db.test.js
    ├── models.test.js
    ├── util.test.js
    └── util.js

util.js i test katalogen ville ikke inneholde noen enhetstester, bare verktøyfunksjoner for å hjelpe med testing.

Merknader: Du kan bruke hvilken struktur som er fornuftig for deg, enhetstestene blir automatisk plukket opp.

Når det gjelder å faktisk skrive testene, hjelper det å organisere dem ved hjelp av describe() metoder. Du kan organisere dem etter funksjon, funksjon, fil eller et hvilket som helst annet vilkårlig nivå. For eksempel ser en testfil organisert for å beskrive virkemåten på funksjonsnivå slik:

"use strict";

const expect = require('chai').expect;

describe('Math', function() {
    describe('#abs()', function() {
        it('should return positive value of given negative number', function() {
            expect(Math.abs(-5)).to.be.equal(5);
        });

        it('should return positive value of given positive number', function() {
            expect(Math.abs(3)).to.be.equal(3);
        });

        it('should return 0 given 0', function() {
            expect(Math.abs(0)).to.be.equal(0);
        });
    });
});

Å kjøre testene vil da gi deg utdata:

$ mocha .

  Math
    #abs()
      ✓ should return positive value of given negative number 
      ✓ should return positive value of given positive number 
      ✓ should return 0 given 0 


  3 passing (11ms)

Hvis du utvider ytterligere, kan du til og med ha tester for flere metoder i en enkelt fil. I dette tilfellet er metodene gruppert etter Math gjenstand:

"use strict";

const expect = require('chai').expect;

describe('Math', function() {
    describe('#abs()', function() {
        it('should return positive value of given negative number', function() {
            expect(Math.abs(-5)).to.be.equal(5);
        });

        it('should return positive value of given positive number', function() {
            expect(Math.abs(3)).to.be.equal(3);
        });

        it('should return 0 given 0', function() {
            expect(Math.abs(0)).to.be.equal(0);
        });
    });

    describe('#sqrt()', function() {
        it('should return the square root of a given positive number', function() {
            expect(Math.sqrt(25)).to.be.equal(5);
        });

        it('should return NaN for a given negative number', function() {
            expect(Math.sqrt(-9)).to.be.NaN;
        });

        it('should return 0 given 0', function() {
            expect(Math.sqrt(0)).to.be.equal(0);
        });
    });
});

Som resulterer i:

$ mocha .

  Math
    #abs()
      ✓ should return positive value of given negative number 
      ✓ should return positive value of given positive number 
      ✓ should return 0 given 0 
    #sqrt()
      ✓ should return the square root of a given positive number 
      ✓ should return NaN for a given negative number 
      ✓ should return 0 given 0 


  6 passing (10ms)

Mokkakroker – før(), etter(), førHver() og etterHver()

Riktignok er de fleste enhetstester ikke så enkle. Mange ganger vil du sannsynligvis trenge andre ressurser for å utføre testene dine, for eksempel en database eller en annen ekstern ressurs (eller en hån/stubb av dem). For å sette opp dette kan vi bruke ett eller flere av følgende Mokka krok metoder:

  • before(): Kjører før alle tester i gitt blokk
  • beforeEach(): Kjører før hver test i gitt blokk
  • after(): Kjører etter alle tester i gitt blokk
  • afterEach(): Kjører etter hver test i gitt blokk

Disse krokene er det perfekte stedet for å utføre oppsett- og rivearbeid som kreves for testene dine. En av de vanligste brukstilfellene er å etablere en tilkobling til databasen din før du kjører testene:

"use strict";

const expect = require('chai').expect;
let User = require('../models').User;

describe('Users', function() {

    let database = null;

    before(function(done) {
        
    });

    afterEach(function(done) {
        
    });

    describe('#save()', function() {
        it('should save User data to database', function(done) {
            
        });
    });

    describe('#load()', function() {
        it('should load User data from database', function(done) {
            
        });
    });
});

Før noen av testene kjøres, sendes funksjonen til vår before() metoden kjøres (og bare kjøres én gang gjennom testene), som etablerer en tilkobling til databasen. Når dette er gjort, kjøres testpakkene våre.

Siden vi ikke vil at dataene fra en testpakke skal påvirke de andre testene våre, må vi slette dataene fra databasen vår etter at hver suite er kjørt. Dette er hva afterEach() er for. Vi bruker denne kroken til å slette alle databasedataene etterpå hver enkelt testcase kjøres, slik at vi kan starte fra et rent ark for de neste testene.

Kjører Mokka-tester

For de fleste tilfeller er denne delen ganske enkel. Forutsatt at du allerede har installert Mocha og navigert til prosjektkatalogen, trenger de fleste prosjekter bare å bruke mocha kommando uten argumenter for å kjøre testene:

$ mocha


  Math
    #abs()
      ✓ should return positive value of given negative number 
      ✓ should return positive value of given positive number 
      ✓ should return 0 given 0 
    #sqrt()
      ✓ should return the square root of a given positive number 
      ✓ should return NaN for a given negative number 
      ✓ should return 0 given 0 


  6 passing (10ms)

Dette er litt annerledes enn våre tidligere eksempler siden vi ikke trengte å fortelle Mocha hvor testene våre var plassert. I dette eksemplet er testkoden på forventet plassering av /test.

Det er imidlertid noen nyttige alternativer du kanskje vil bruke når du kjører tester. Hvis noen av testene dine mislykkes, for eksempel, vil du sannsynligvis ikke kjøre hele suiten hver gang du gjør en endring. For noen prosjekter kan det ta noen minutter å fullføre hele testpakken. Det er mye bortkastet tid hvis du egentlig bare trenger å kjøre én test.

For tilfeller som dette bør du fortell Mocha hvilke tester du skal kjøre. Dette kan gjøres ved hjelp av -g or -f alternativer.

For å kjøre individuelle tester, kan du levere -g flagg og legg til et felles mønster mellom testene du vil kjøre. For eksempel, hvis du ønsker å kjøre #sqrt() tester:

$ mocha -g sqrt

  Math
    #sqrt()
      ✓ should return the square root of a given positive number 
      ✓ should return NaN for a given negative number 
      ✓ should return 0 given 0 


  3 passing (10ms)

Legg merke til at #abs() tester ble ikke inkludert i denne kjøringen. Hvis du planlegger deretter med testnavnene dine, kan dette alternativet brukes til kun å kjøre bestemte deler av testene dine.

Dette er imidlertid ikke de eneste nyttige alternativene. Her er noen flere alternativer for Mokka som du kanskje vil sjekke ut:

  • --invert: Inverterer -g og -f fyrstikker
  • --recursive: Inkluder underkataloger
  • --harmony: Aktiver alle harmonifunksjoner i Node

Merknader: Du kan sjekke ut hele listen over alternativer ved å bruke mocha -h kommando, eller på denne siden.

Hvor kan man lære mer? Det er mye mer til dette emnet enn vi kan dekke i en kort artikkel, så hvis du vil lære mer, anbefaler vi å sjekke ut den offisielle Mocha og Chai dokumentasjon.

konklusjonen

Husk at både Mocha og Chai kan brukes til å teste omtrent alle typer nodeprosjekter, enten det er et bibliotek, kommandolinjeverktøy eller til og med et nettsted. Ved å bruke de forskjellige alternativene og pluginene som er tilgjengelige for deg, bør du være i stand til å tilfredsstille dine testbehov ganske enkelt. Hvert av disse bibliotekene er veldig nyttige for å validere koden din og bør brukes i omtrent alle Node-prosjektene dine.

Forhåpentligvis har dette fungert som en nyttig introduksjon til Mocha og Chai. Det er mye mer å lære enn det jeg har presentert her, så sørg for å sjekke ut dokumentene for mer informasjon.

Tidstempel:

Mer fra Stackabuse