🙌
jest it.concurrent / test.concurrent の挙動
test.concurrent is considered experimental - see here for details on missing features and other issues.
test.concurrentは実験的なものとみなされています。不足している機能やその他の問題の詳細については、こちらをご覧ください。
とあるので、どういう挙動なのかを確認した。
jest バージョン 29.5.0
で確認した。
テスト対象コード
import { setTimeout } from "timers/promises";
export const calc = (a: number) => async (b: number, c: number) => {
await setTimeout(1000);
return a * (b + c);
};
concurrentを使わない場合
describe("concurrentを使わない場合", function () {
it("test 1", async function () {
const result = await calc(2)(4, 2);
expect(result).toBe(12);
});
it("test 2", async function () {
const result = await calc(2)(5, 2);
expect(result).toBe(14);
});
});
PASS ./index.test.ts
concurrentを使わない場合
✓ test 1 (1003 ms)
✓ test 2 (1002 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.257 s
concurrentを使う場合
describe("concurrentを使う場合", function () {
it.concurrent("test 1", async function () {
const result = await calc(2)(4, 2);
expect(result).toBe(12);
});
it.concurrent("test 2", async function () {
const result = await calc(2)(5, 2);
expect(result).toBe(14);
});
});
PASS ./index.test.ts
concurrentを使う場合
✓ test 1 (1003 ms)
✓ test 2
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 1.238 s, estimated 2 s
早い。
beforeAll を使う場合
concurrentを使わない場合
describe("beforeAllを使い、concurrentを使わない場合", function () {
let calc2;
beforeAll(() => {
calc2 = calc(2);
});
it("test 1", async function () {
const result = await calc2(4, 2);
expect(result).toBe(12);
});
it("test 2", async function () {
const result = await calc2(5, 2);
expect(result).toBe(14);
});
});
PASS ./index.test.ts
beforeAllを使い、concurrentを使わない場合
✓ test 1 (1002 ms)
✓ test 2 (1001 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.251 s, estimated 3 s
Ran all test suites.
concurrentを使う場合
describe("beforeAllを使い、concurrentを使う場合", function () {
let calc2;
beforeAll(() => {
console.log("beforeAll");
calc2 = calc(2);
});
it.concurrent("test 1", async function () {
console.log("test 1");
const result = await calc2(4, 2);
expect(result).toBe(12);
});
it.concurrent("test 2", async function () {
console.log("test 2");
const result = await calc2(5, 2);
expect(result).toBe(14);
});
});
FAIL ./index.test.ts
beforeAllを使い、concurrentを使う場合
✕ test 1
✕ test 2
● beforeAllを使い、concurrentを使う場合 › test 1
TypeError: calc2 is not a function
52 | it.concurrent("test 1", async function () {
53 | console.log("test 1");
> 54 | const result = await calc2(4, 2);
| ^
55 | expect(result).toBe(12);
56 | });
57 |
失敗。
console.logの出力を見ると、beforeAllでの出力が最後に実行されている。
console.log
test 1
at log (index.test.ts:53:13)
console.log
test 2
at log (index.test.ts:59:13)
console.log
beforeAll
at Object.log (index.test.ts:48:13)
回避策
https://github.com/jestjs/jest/issues/7997#issuecomment-1455052585 に、
I found some workaround to execute beforeAll before test.concurrent. Seems like problem is not with test.concurrent logic but with describe. If we move beforeAll out from describe, everything works as expected:
test.concurrentの前にbeforeAllを実行する回避策を見つけました。問題はtest.concurrentのロジックではなく、describeにあるようだ。beforeAllをdescribeから外せば、すべてが期待通りに動く:
とある。
let calc2;
beforeAll(() => {
console.log("beforeAll");
calc2 = calc(2);
});
it.concurrent("test 1", async function () {
console.log("test 1");
const result = await calc2(4, 2);
expect(result).toBe(12);
});
it.concurrent("test 2", async function () {
console.log("test 2");
const result = await calc2(5, 2);
expect(result).toBe(14);
});
PASS ./index.test.ts
✓ test 1 (1004 ms)
✓ test 2
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 1.084 s
Ran all test suites.
確かに回避できた。
Discussion