mocha.parallel という Mocha のテストを並列実行できる npm モジュールがあったので試してみました。

インストール

$ npm install -g mocha
$ npm install -D mocha.parallel

並列じゃない例

まずは並列じゃない例を。

// test/a-test.js

const assert = require('assert');

describe('a', () => {
    before(() => { console.log('before'); });
    beforeEach(() => { console.log('before each'); });
    afterEach(() => { console.log('after each'); });
    after(() => { console.log('after'); });

    it('0', () => {
        assert.strictEqual(0, 0);
    });

    it('1', (done) => {
        setTimeout(() => {
            assert.strictEqual(1, 1);
            done();
        }, 1000);
    });

    it('2', (done) => {
        setTimeout(() => {
            assert.strictEqual(2, 2);
            done();
        }, 2000);
    });

    it('3', (done) => {
        setTimeout(() => {
            assert.strictEqual(3, 3);
            done();
        }, 3000);
    });
});

これを実行すると前のテストの実行が終ってから次が実行されているのがわかります。

$ mocha test --timeout=5000


  a
before
before each0
after each
before each1 (1006ms)
after each
before each2 (2003ms)
after each
before each3 (3001ms)
after each
after


  4 passing (6s)

並列にする

mocha.parallel を使って並列化してみます。

// test/a-test.js

const assert = require('assert');

const parallel = require('mocha.parallel');

parallel('a', () => {
    before(() => { console.log('before'); });
    beforeEach(() => { console.log('before each'); });
    afterEach(() => { console.log('after each'); });
    after(() => { console.log('after'); });

    it('0', () => {
        assert.strictEqual(0, 0);
    });

    it('1', (done) => {
        setTimeout(() => {
            assert.strictEqual(1, 1);
            done();
        }, 1000);
    });

    it('2', (done) => {
        setTimeout(() => {
            assert.strictEqual(2, 2);
            done();
        }, 2000);
    });

    it('3', (done) => {
        setTimeout(() => {
            assert.strictEqual(3, 3);
            done();
        }, 3000);
    });
});

describe のかわりに parallel を使っています。

これを実行してみます。

$ mocha test --timeout=5000


  a
before
before each
before each
before each
before each
after each0
after each1 (1003ms)
after each2 (1000ms)
after each3 (997ms)
after


  4 passing (3s)

beforeEach がはじめにまとめて実行されています。テストがすべて並列で実行されているのがわかります。

テストにかかった時間は前のテストが終ってから計測されるみたいです。上の例の 23 の順番を入れ替えると表示される時間もかわります。

// 略
    it('3', (done) => {
        setTimeout(() => {
            assert.strictEqual(3, 3);
            done();
        }, 3000);
    });

    it('2', (done) => {
        setTimeout(() => {
            assert.strictEqual(2, 2);
            done();
        }, 2000);
    });
// 略
$ mocha test --timeout=5000


  a
before
before each
before each
before each
before each
after each0
after each1 (1002ms)
after each
after each3 (1995ms)
    ✓ 2
after


  4 passing (3s)

2 のテストが一瞬で終わっています。

まとめ

少し書き換えるだけで簡単に導入できるのはいいと感じました。

テストに時間がかかると辛いので、こういうツールは積極敵に使っていきたいです。

ただし、DBやファイル書き込みなどの副作用がある場合は単純には並列化できないので気をつけないといけません。副作用をうまく切り出しておくとよさそうです。