Ricerca…


Asserzione di base

Al suo livello più elementare, il test unitario in qualsiasi lingua fornisce asserzioni su alcuni risultati noti o previsti.

function assert( outcome, description ) { 
    var passFail = outcome ? 'pass' : 'fail'; 
    console.log(passFail, ': ', description);
    return outcome;
};

Il popolare metodo di asserzione sopra ci mostra un modo facile e veloce per affermare un valore nella maggior parte dei browser Web e degli interpreti come Node.js con praticamente qualsiasi versione di ECMAScript.

Un buon test unitario è progettato per testare un'unità discreta di codice; di solito una funzione.

function add(num1, num2) { 
    return num1 + num2; 
} 
 
var result = add(5, 20); 
assert( result == 24, 'add(5, 20) should return 25...'); 

Nell'esempio sopra, il valore restituito dalla funzione add(x, y) o 5 + 20 è chiaramente 25 , quindi la nostra asserzione di 24 dovrebbe fallire e il metodo asser registrerà una riga "fail".

Se modifichiamo semplicemente il risultato previsto per l'asserzione, il test avrà esito positivo e l'output risultante sarà simile a questo.

assert( result == 25, 'add(5, 20) should return 25...');

console output:

> pass: should return 25...

Questa semplice asserzione può assicurare che in molti casi diversi, la funzione "aggiungi" restituirà sempre il risultato previsto e non richiede strutture o librerie aggiuntive per funzionare.

Un set di asserzioni più rigoroso sarebbe simile a questo (usando var result = add(x,y) per ogni asserzione):

assert( result == 0, 'add(0, 0) should return 0...');
assert( result == -1, 'add(0, -1) should return -1...');
assert( result == 1, 'add(0, 1) should return 1...');

E l'output della console sarebbe questo:

> pass: should return 0...
> pass: should return -1...
> pass: should return 1...

Ora possiamo tranquillamente dire che add(x,y) ... dovrebbe restituire la somma di due interi . Possiamo sistemarli in qualcosa del genere:

function test__addsIntegers() {

    // expect a number of passed assertions
    var passed = 3;

    // number of assertions to be reduced and added as Booleans
    var assertions = [

        assert( add(0, 0) == 0, 'add(0, 0) should return 0...'),
        assert( add(0, -1) == -1, 'add(0, -1) should return -1...'),
        assert( add(0, 1) == 1, 'add(0, 1) should return 1...')

    ].reduce(function(previousValue, currentValue){

        return previousValue + current;

    });

    if (assertions === passed) {

        console.log("add(x,y)... did return the sum of two integers");
        return true;

    } else {

        console.log("add(x,y)... does not reliably return the sum of two integers");
        return false;

    }
}

Promesse di unit test con Mocha, Sinon, Chai e Proxyquire

Qui abbiamo una semplice classe da testare che restituisce una Promise basata sui risultati di un ResponseProcessor esterno che richiede tempo per essere eseguito.

Per semplicità supponiamo che il metodo processResponse non fallirà mai.

import {processResponse} from '../utils/response_processor';

const ping = () => {
  return new Promise((resolve, _reject) => {
    const response = processResponse(data);
    resolve(response);
  });
}

module.exports = ping;

Per testare questo possiamo sfruttare i seguenti strumenti.

  1. mocha
  2. chai
  3. sinon
  4. proxyquire
  5. chai-as-promised

Io uso il seguente script di test nel mio file package.json .

"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js  --recursive test/**/*_spec.js"

Questo mi permette di usare la sintassi es6 . Fa riferimento a un test_helper che assomiglierà

import chai from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import chaiAsPromised from 'chai-as-promised';
import sinonStubPromise from 'sinon-stub-promise';

chai.use(sinonChai);
chai.use(chaiAsPromised);
sinonStubPromise(sinon);

Proxyquire ci consente di iniettare il nostro stub al posto del ResponseProcessor esterno. Possiamo quindi usare sinon per spiare i metodi di quello stub. Usiamo le estensioni chai che gli inietti chai-as-promised per verificare che la promessa del metodo ping() sia fullfilled e che eventually restituisca la risposta richiesta.

import {expect}       from 'chai';
import sinon          from 'sinon';
import proxyquire     from 'proxyquire';

let formattingStub = {
  wrapResponse: () => {}
}

let ping = proxyquire('../../../src/api/ping', {
  '../utils/formatting': formattingStub
});

describe('ping', () => {
  let wrapResponseSpy, pingResult;
  const response = 'some response';

  beforeEach(() => {
    wrapResponseSpy = sinon.stub(formattingStub, 'wrapResponse').returns(response);
    pingResult = ping();
  })

  afterEach(() => {
    formattingStub.wrapResponse.restore();
  })

  it('returns a fullfilled promise', () => {
    expect(pingResult).to.be.fulfilled;
  })

  it('eventually returns the correct response', () => {
    expect(pingResult).to.eventually.equal(response);
  })
});

Ora invece supponiamo che desideri testare qualcosa che usi la risposta dal ping .

import {ping} from './ping';

const pingWrapper = () => {
  ping.then((response) => {
    // do something with the response
  });
}

module.exports = pingWrapper;

Per testare il pingWrapper facciamo leva

  1. sinon
  2. proxyquire
  3. sinon-stub-promise

Come prima, Proxyquire ci consente di iniettare il nostro stub al posto della dipendenza esterna, in questo caso il metodo ping che abbiamo testato in precedenza. Possiamo quindi usare sinon per spiare i metodi di tale stub e sfruttare la sinon-stub-promise per permetterci di returnsPromise . Questa promessa può quindi essere risolta o respinta come desideriamo nel test, al fine di testare la risposta del wrapper a questo.

import {expect}   from 'chai';
import sinon      from 'sinon';
import proxyquire from 'proxyquire';

let pingStub = {
  ping: () => {}
};

let pingWrapper = proxyquire('../src/pingWrapper', {
  './ping': pingStub
});

describe('pingWrapper', () => {
  let pingSpy;
  const response = 'some response';

  beforeEach(() => {
    pingSpy = sinon.stub(pingStub, 'ping').returnsPromise();
    pingSpy.resolves(response);
    pingWrapper();
  });

  afterEach(() => {
    pingStub.wrapResponse.restore();
  });

  it('wraps the ping', () => {
    expect(pingSpy).to.have.been.calledWith(response);
  });
});


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow