サーチ…
基本アサーション
最も基本的なレベルでは、どの言語のユニットテストでも、既知の出力または予想される出力に対してアサーションが提供されます。
function assert( outcome, description ) {
var passFail = outcome ? 'pass' : 'fail';
console.log(passFail, ': ', description);
return outcome;
};
上記の一般的なアサーション手法は、ECMAScriptのどのバージョンでも、Node.jsのようなほとんどのWebブラウザとインタープリタで、値をアサートできる簡単で簡単な方法を示しています。
慎重な単位のコードをテストするための優れた単体テストが設計されています。通常は関数です。
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)
...が2つの整数の和を返すべきであると安全に言えるよう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;
これをテストするために、以下のツールを活用することができます。
私はpackage.json
ファイルで次のtest
スクリプトを使用します。
"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js --recursive test/**/*_spec.js"
これにより私はes6
構文を使用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
を使用することができます。私たちはする拡張機能を使用chai
そのchai-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
をテストするには
前述のように、 Proxyquire
は、外部依存関係の場所に独自のスタブを挿入することができます。この場合、前にテストしたping
メソッドです。私たちはそのスタブの方法をスパイするためにsinon
を使い、 returnsPromise
ことができるようにするために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);
});
});