みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

Vitestの並列実行が快適だった

ユニットテストを高速で簡単に実行できるVitestを触ってみました.

Vitest v0.5.8

2022/02/28現在は鋭意製作中のライブラリみたいですが,問題なく使えました.

package.json

{
  "name": "vt",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "vitest watch"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vitest": "^0.5.8"
  }
}

順番に実行する場合

test/basic.test.ts

import { assert, describe, it, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';

const sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t));

beforeAll(async () => {
    await sleep(1000);
    console.log("beforeAll() complete.");
});
afterAll(async () => {
    await sleep(1000);
    console.log("afterAll() complete.");
});
beforeEach(async () => {
    await sleep(1000);
    console.log("beforeEach() complete.");
});
afterEach(async () => {
    await sleep(1000);
    console.log("afterEach() complete.");
});

describe("suite 1", () => {
    it("a", async () => {
        await sleep(1000);
        assert.equal(1, 1);
        console.log("test a complete.");
    });
    it("b", async () => {
        await sleep(1000);
        assert.equal(2, 2);
        console.log("test b complete.");
    });
    it("c", async () => {
        await sleep(1000);
        assert.equal(3, 3);
        console.log("test c complete.");
    });
});

これを実行すると,以下のように出力されました.

stdout | unknown test
beforeAll() complete.

stdout | test/basic.test.ts > suite 1 > a
beforeEach() complete.

stdout | test/basic.test.ts > suite 1 > a
test a complete.

stdout | test/basic.test.ts > suite 1 > a
afterEach() complete.

stdout | test/basic.test.ts > suite 1 > b
beforeEach() complete.

stdout | test/basic.test.ts > suite 1 > b
test b complete.

stdout | test/basic.test.ts > suite 1 > b
afterEach() complete.

stdout | test/basic.test.ts > suite 1 > c
beforeEach() complete.

stdout | test/basic.test.ts > suite 1 > c
test c complete.

stdout | test/basic.test.ts > suite 1 > c
afterEach() complete.

stdout | unknown test
afterAll() complete.

 √ test/basic.test.ts (3) 11023ms

Test Files  1 passed (1)
     Tests  3 passed (3)
      Time  11.02s

最初にbeforeAll(),次にそれぞれのbeforeEach(),メイン,afterEach() が実行され,最後にafterAll() が実行されました.

並列に実行する場合

it()it.concurrent()に変更して,非同期関数を指定するだけです.

test/basic.test.ts

import { assert, describe, it, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';

const sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t));

beforeAll(async () => {
    await sleep(1000);
    console.log("beforeAll() complete.");
});
afterAll(async () => {
    await sleep(1000);
    console.log("afterAll() complete.");
});
beforeEach(async () => {
    await sleep(1000);
    console.log("beforeEach() complete.");
});
afterEach(async () => {
    await sleep(1000);
    console.log("afterEach() complete.");
});

describe("concurrent suite", () => {
    it.concurrent("a", async () => {
        await sleep(1000);
        assert.equal(1, 1);
        console.log("test a complete.");
    });
    it.concurrent("b", async () => {
        await sleep(1000);
        assert.equal(2, 2);
        console.log("test b complete.");
    });
    it.concurrent("c", async () => {
        await sleep(1000);
        assert.equal(3, 3);
        console.log("test c complete.");
    });
});
stdout | unknown test
beforeAll() complete.

stdout | test/basic.test.ts > concurrent suite > c
beforeEach() complete.

stdout | test/basic.test.ts > concurrent suite > c
beforeEach() complete.

stdout | test/basic.test.ts > concurrent suite > c
beforeEach() complete.

stdout | test/basic.test.ts > concurrent suite > c
test a complete.

stdout | test/basic.test.ts > concurrent suite > c
test b complete.

stdout | test/basic.test.ts > concurrent suite > c
test c complete.

stdout | test/basic.test.ts > concurrent suite > c
afterEach() complete.

stdout | unknown test
afterEach() complete.

stdout | unknown test
afterEach() complete.

stdout | unknown test
afterAll() complete.

 √ test/basic.test.ts (3) 5020ms

Test Files  1 passed (1)
     Tests  3 passed (3)
      Time  5.02s

最初にbeforeAll(),次にそれぞれのbeforeEach(),メイン,afterEach() が実行され,最後にafterAll() が実行されたのは同じですが,途中が並列実行され,実行時間が11秒から5秒に短縮しました.

Jestの流儀とchaiの評価をもとにいい感じにテストを実行してくれました.