Recherche…


Assertion de base

À son niveau le plus élémentaire, le test unitaire dans n'importe quel langage fournit des assertions contre certains résultats connus ou attendus.

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

La méthode d'assertion courante ci-dessus nous montre un moyen rapide et facile d'affirmer une valeur dans la plupart des navigateurs Web et des interpréteurs comme Node.js avec pratiquement n'importe quelle version d'ECMAScript.

Un bon test unitaire est conçu pour tester une unité de code discrète; généralement une fonction.

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

Dans l'exemple ci-dessus, la valeur de retour de la fonction add(x, y) ou 5 + 20 est clairement 25 , donc notre assertion de 24 devrait échouer et la méthode assert enregistrera une ligne "échec".

Si nous modifions simplement notre résultat d'assertion attendu, le test réussira et la sortie résultante ressemblera à ceci.

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

console output:

> pass: should return 25...

Cette simple assertion peut garantir que dans de nombreux cas différents, votre fonction "Ajouter" renverra toujours le résultat attendu et ne nécessite aucun framework ou bibliothèque supplémentaire pour fonctionner.

Un ensemble d'assertions plus rigoureux ressemblerait à ceci (en utilisant var result = add(x,y) pour chaque assertion):

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...');

Et la sortie de la console serait la suivante:

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

Nous pouvons maintenant affirmer que add(x,y) … devrait retourner la somme de deux entiers . Nous pouvons les transformer en quelque chose comme ceci:

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;

    }
}

Test d'unité avec Moka, Sinon, Chai et Proxyquire

Nous avons ici une classe simple à tester qui renvoie une Promise basée sur les résultats d'un ResponseProcessor externe qui prend du temps à exécuter.

Pour simplifier, nous supposerons que la méthode processResponse n'échouera jamais.

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

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

module.exports = ping;

Pour tester cela, nous pouvons tirer parti des outils suivants.

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

J'utilise le script de test suivant dans mon fichier package.json .

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

Cela me permet d'utiliser la syntaxe es6 . Il fait référence à un test_helper qui ressemblera à

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 nous permet d'injecter notre propre stub à la place du ResponseProcessor externe. Nous pouvons alors utiliser sinon pour espionner les méthodes de ce stub. Nous utilisons les extensions de chai que chai-as-promised injecte pour vérifier que la promesse de la méthode ping() est fullfilled et qu'elle renvoie eventually la réponse requise.

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);
  })
});

Supposons maintenant que vous souhaitiez tester quelque chose qui utilise la réponse de ping .

import {ping} from './ping';

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

module.exports = pingWrapper;

Pour tester le pingWrapper nous pingWrapper

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

Comme précédemment, Proxyquire nous permet d'injecter notre propre stub à la place de la dépendance externe, en l'occurrence la méthode ping nous avons testée précédemment. Nous pouvons alors utiliser sinon pour espionner les méthodes de ce stub et tirer parti de sinon-stub-promise returnsPromise pour nous permettre de returnsPromise . Cette promesse peut alors être résolue ou rejetée comme nous le souhaitons dans le test, afin de tester la réponse de l'enveloppe à cela.

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow