수색…


기본 주장

가장 기본적인 수준에서 모든 언어의 단위 테스트는 일부 알려진 또는 예상 된 결과에 대한 어설 션을 제공합니다.

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

위의 일반적인 어설 션 방법은 거의 모든 버전의 ECMAScript를 사용하는 Node.js와 같은 대부분의 웹 브라우저와 인터프리터에서 한 가지 빠르고 쉬운 방법을 제시합니다.

훌륭한 단위 테스트는 신중한 코드 단위를 테스트하도록 설계되었습니다. 보통 함수.

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

위의 예제에서 add(x, y) 또는 5 + 20 함수의 반환 값은 분명히 25 이므로 24 의 어설 션은 실패해야하고 assert 메서드는 "실패"행을 기록합니다.

예상되는 주장 결과를 간단히 수정하면 테스트는 성공하고 결과 출력은 다음과 같습니다.

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

console output:

> pass: should return 25...

이 간단한 단언은 많은 다른 경우에 "add"함수가 항상 예상 결과를 반환하고 추가 프레임 워크 나 라이브러리가 필요하지 않음을 보증합니다.

더 엄격한 어설 션 집합은 다음과 같이 보일 것입니다 (각 어설 션에 대해 var result = add(x,y) ).

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

콘솔 출력은 다음과 같습니다.

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

이제 add(x,y) ...가 두 정수의 합을 반환해야한다고 안전하게 말할 수 add(x,y) . 우리는 이것을 다음과 같이 만들 수 있습니다 :

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;

    }
}

Mocha, Sinon, Chai 및 Proxyquire로 단위 테스트 약속

여기에는 외부 ResponseProcessor 의 결과를 기반으로 Promise 를 반환하는 간단한 클래스가 있습니다.이 클래스는 실행하는 데 시간이 걸립니다.

간결함을 위해 processResponse 메소드가 실패하지 않는다고 가정합니다.

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

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

module.exports = ping;

이를 테스트하기 위해 다음 도구를 활용할 수 있습니다.

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

package.json 파일에서 다음 test 스크립트를 사용합니다.

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

이를 통해 es6 구문을 사용할 수 있습니다. 그것은 보이는 test_helper 를 참조합니다.

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 사용하면 외부 ResponseProcessor 대신 자체 스텁을 삽입 할 수 있습니다. 그런 다음 sinon 을 사용하여 스텁의 방법을 간첩 할 수 있습니다. 우리는 할 확장자를 사용하는 chaichai-as-promised 있는지 확인하기를 분사을 ping() 메소드의 약속이되어 fullfilled , 그것은 것을 eventually 필요한 응답을 반환합니다.

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

이제 대신 ping 의 응답을 사용하는 무언가를 테스트하려고한다고 가정 해 봅시다.

import {ping} from './ping';

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

module.exports = pingWrapper;

우리가 활용하는 pingWrapper 를 테스트하려면

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

앞에서와 같이 Proxyquire 사용하면 이전에 테스트 한 ping 메서드와 같이 외부 종속성 대신 자체 스텁을 삽입 할 수 있습니다. 그런 다음 sinon 을 사용하여 그 스텁의 방법을 간첩하고 sinon-stub-promise 을 활용하여 우리가 returnsPromise 하도록 허용 할 수 있습니다. 이 약속은 랩퍼의 응답을 테스트하기 위해 테스트에서 원하는대로 해결되거나 거부 될 수 있습니다.

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
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow