LoginSignup
8
6

More than 5 years have passed since last update.

ava, sinonを使ったnode.jsのテスト

Last updated at Posted at 2016-04-04

こちらの記事を読みました。

Mocha, Chai, Sinon を使ったNode.js のテスト自動化 実践編 - Qiita

上記のテストをavaで書き直してみます。
travisでv0.10,v0.12,v4,v5のすべての環境でパスするのを確認しました。

avaについては日本語のドキュメントがあるので、それを確認するといいでしょう。

ava-docs/ja_JP at master · sindresorhus/ava-docs

テスト対象のコードは以下です。
もとのコードから少し変えさせてもらってます。

index.js
'use strict';

function calculate(num) {
    if (typeof num !== 'number' || isNaN(num)) {
        throw new TypeError('Type of numeric is expected.');
    }

    return Math.floor(num / 2);
}

function read() {
    process.openStdin().on('data', function(chunk) {
        var param = Number(chunk);
        try {
            var result = calculate(param);
            console.log('result: ' + result);
        } catch (e) {
            console.log(e.message);
        }
    });
}

exports.calculate = calculate;
exports.read = read;

環境

$ npm init
$ npm i -D ava

テスト対象のコードをindex.js、テストファイルをtest.jsとします。
テストコマンドは以下です。

$ ava

詳細

$ ava -v

監視

$ ava -w

実行

内容自体は元コードままです。
avaのテストは並列で走りますが、console.logをスタブする関係で一部直列化しています。
また、avaは内部的にbabelを使っているのでes6で書けます。

test.js
import test from 'ava';
import sinon from 'sinon';
import {EventEmitter} from 'events';
import fn from './';

test.beforeEach(t => {
    t.context.log = console.log;
    sinon.stub(console, 'log');
});

test.afterEach(t => {
    console.log = t.context.log;
});

test('return 2 when the value is 4', t => {
    t.is(fn.calculate(4), 2);
});

test('return 1 when the value is 3', t => {
    t.is(fn.calculate(3), 1);
});

test('throw exceptions when the value are other than numbers', t => {
    t.throws(fn.calculate);
    t.throws(() => fn.calculate(null), 'Type of numeric is expected.');
    t.throws(() => fn.calculate('abc'), / numeric /);
    t.throws(() => fn.calculate([]), TypeError, /^Type of numeric /);
});

test.serial('print "result: 4" when the value is 8 that given from the stdin', t => {
    const ev = new EventEmitter();
    process.openStdin = sinon.stub().returns(ev);
    fn.read();
    ev.emit('data', '8');
    t.is(console.log.callCount, 1);
    t.true(console.log.calledWith('result: 4'));
});

test.serial('print "Type of numeric is expected." when the value is not a numeric', t => {
    const ev = new EventEmitter();
    process.openStdin = sinon.stub().returns(ev);
    fn.read();
    ev.emit('data', 'abc');
    t.is(console.log.callCount, 1);
    t.true(console.log.calledWithMatch('Type of numeric is expected.'));
});

比較

chaiのshould記法とexpect記法

// should
divided.calculate(4).should.equal(2);
// expect
expect(divided.calculate(4)).to.equal(2);

ava

t.is(divided.calculate(4), 2);

avaの方が読みやすく簡潔ですね。
また、テストを落としたときのエラーはpower-assertにより非常にわかりやすいです。

  1. test › return 1 when the value is 3

  t.is(fn.calculate(3), 1)
          |
          1.5

      Test.fn (test.js:15:4)

その他

今回はすべて同期処理のテストでしたが、avaはasyncが使えるので、Promiseによる非同期処理のテストが簡潔に書けます。

test.js
import test from 'ava';

function calc(num) {
    return new Promise(resolve => {
        resolve(num * num);
    });
}

test('calc', async t => {
    const ans = await calc(10);
    t.is(ans, 100);
});

参考

8
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6