Playwrightの並列実行とテストファイルの分け方まとめ方
最初にまとめ
config.tsでfullyParallel
を指定しない場合
- テストファイルはファイルごとに並列で実行される
- 一つのテストファイルに複数テストがある場合、モードを指定できる
- デフォルト: 1つのワーカーで順番に実行される、途中で失敗した場合も後続のテストを実行する
- パラレル: 複数のワーカーで実行する、途中で失敗した場合も後続のテストを実行する
- シリアル: 1つのワーカーで上から順番に実行される、途中で失敗した場合は後続のテストをスキップする
- シリアルはあまりおすすめしない
基本的には他に依存しないテストたちは目的や機能ごとに一つのファイルにまとめてパラレルモードにする。
シリアルモードにするかデフォルトにするかは、前のテストが失敗した時に次のテストやることに意味があるかどうかを考えれば判断できそう。
動機
playwrightでE2Eテストを書いていて、テストをどのファイルに入れたり移動していいか迷うことがあったので、曖昧な部分をスッキリさせたい。
シリアル・パラレルモードもなんとなくイメージしている程度だったので、実際に動かして確認してみたい。
まずはドキュメントを読む
Parametrize tests | Playwright
- デフォルトでは、テストファイルは並列で実行されます。
- 一つのファイルに含まれるテストは、同じワーカープロセスで順番に実行されます。
- テストファイルにパラレルモードにすると、1つのファイル内でも並列で実行される
- 相互に依存するテストにシリアルとして注釈を付けることができます。
- シリアルテストの1つが失敗すると、後続のすべてのテストがスキップされます。グループ内のすべてのテストがまとめて再試行されます。
※Google翻訳
確認してみる
準備
$ npm init playwright@latest
npx: 1個のパッケージを2.913秒でインストールしました。
Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Do you want to use TypeScript or JavaScript? · TypeScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · false
$ npx playwright --version
Version 1.24.1
configファイルを修正
/* Run tests in files in parallel */
// fullyParallel: true, // ←コメントアウトする
ついでにtests/*.spec.ts
を削除します
確認してみる
> デフォルトでは、テストファイルは並列で実行されます。
テストファイルを2つ作って実験してみます。
「並列で実行」されているかはどうやって確認したらいいかわからなかったので、別のワーカーで実行されていたら「並行で実行」されてるっぽいとみなしていきたいと思います。
ワーカーはtestInfo.workerIndexの値で区別していきます。
import { test, expect } from '@playwright/test';
test('test1', ({ }, testInfo) => {
console.log('test1:' + testInfo.workerIndex)
expect(true).toBe(true);
})
import { test, expect } from '@playwright/test';
test('test2', ({ }, testInfo) => {
console.log('test2:' + testInfo.workerIndex)
expect(true).toBe(true);
})
結果
$npx playwright test --project=chromium --reporter=list
Running 2 tests using 2 workers
✓ [chromium] › test1.spec.ts:3:1 › test1 (47ms)
test1:0
✓ [chromium] › test2.spec.ts:3:1 › test2 (36ms)
test2:1
workerIndexの値が違うので、別のワーカーで実行されたみたいです。
> 一つのファイルに含まれるテストは、同じワーカープロセスで順番に実行されます。
test1.spec.ts
に3つテストを書いて、"同じワーカープロセスで順番に実行"されてるか確認します。
workerIndexが同じでABC順にconsole.log
の結果が出力されれば良さそう。
import { test, expect } from '@playwright/test';
test('test1A', ({ }, testInfo) => {
console.log('test1A:' + testInfo.workerIndex)
expect(true).toBe(true);
})
test('test1B', ({ }, testInfo) => {
console.log('test1B:' + testInfo.workerIndex)
expect(true).toBe(true);
})
test('test1C', ({ }, testInfo) => {
console.log('test1C:' + testInfo.workerIndex)
expect(true).toBe(true);
})
結果
npx playwright test test1 --project=chromium --reporter=list
Running 3 tests using 1 worker
✓ [chromium] › test1.spec.ts:3:1 › test1A (41ms)
test1A:0
✓ [chromium] › test1.spec.ts:8:1 › test1B (11ms)
test1B:0
✓ [chromium] › test1.spec.ts:13:1 › test1C (5ms)
test1C:0
3 passed (920ms)
想定通り、workerIndexの値が同じで、ABCの順番に実行されてますね。
> テストファイルにパラレルモードにすると、1つのファイル内でも並列で実行される
mode: 'parallel'
にしてみます。
import { test, expect } from '@playwright/test';
test.describe.configure({ mode: 'parallel' });
test('test1A', ({ }, testInfo) => {
console.log('test1A:' + testInfo.workerIndex)
expect(true).toBe(true);
})
test('test1B', ({ }, testInfo) => {
console.log('test1B:' + testInfo.workerIndex)
expect(true).toBe(true);
})
test('test1C', ({ }, testInfo) => {
console.log('test1C:' + testInfo.workerIndex)
expect(true).toBe(true);
})
$ npx playwright test test1 --project=chromium --reporter=list
Running 3 tests using 2 workers
✓ [chromium] › test1.spec.ts:4:1 › test1A (162ms)
test1A:0
✓ [chromium] › test1.spec.ts:9:1 › test1B (151ms)
test1B:1
✓ [chromium] › test1.spec.ts:14:1 › test1C (7ms)
test1C:0
3 passed (1s)
2つのワーカーが使われました。(using 2 workers
)
1つのファイル内でも並列に実行されているみたいですね
> シリアルテストの1つが失敗すると、後続のすべてのテストがスキップされます。
まずはシリアルを実験してみます。
ドキュメントにおすすめしないって書いてありますが、気づいたら増えてそうなやつ…。
2番目の実験と同じ結果になるっぽいですよね。
import { test, expect } from '@playwright/test';
test.describe.configure({ mode: 'serial' }) // 追加
test('test1A', ({ }, testInfo) => {
console.log('test1A:' + testInfo.workerIndex)
expect(true).toBe(true);
})
test('test1B', ({ }, testInfo) => {
console.log('test1B:' + testInfo.workerIndex)
expect(true).toBe(true);
})
test('test1C', ({ }, testInfo) => {
console.log('test1C:' + testInfo.workerIndex)
expect(true).toBe(true);
})
結果
$ npx playwright test test1 --project=chromium --reporter=list
Running 3 tests using 1 worker
✓ [chromium] › test1.spec.ts:4:1 › test1A (24ms)
test1A:0
✓ [chromium] › test1.spec.ts:9:1 › test1B (3ms)
test1B:0
✓ [chromium] › test1.spec.ts:14:1 › test1C (3ms)
test1C:0
同じですね。workerIndexが全部同じでABCの順番で実行されてるっぽいです。
ついでにシリアルだと”1つが失敗すると、後続のすべてのテストがスキップ”されるみたいなので、デフォルトの場合はスキップされないのか確認します。
workerIndexは上で確認したので外します。
import { test, expect } from '@playwright/test';
test.describe.configure({ mode: 'serial' }) // コメントアウト
test('test1A', ({ }, testInfo) => {
expect(true).toBe(true);
})
test('test1B', ({ }, testInfo) => {
expect(true).toBe(false); // 失敗させる
})
test('test1C', ({ }, testInfo) => {
expect(true).toBe(true);
})
結果
(base) ❯ npx playwright test test1 --project=chromium --reporter=list
Running 3 tests using 1 worker
✓ [chromium] › test1.spec.ts:4:1 › test1A (26ms)
✘ [chromium] › test1.spec.ts:9:1 › test1B (7ms)
✓ [chromium] › test1.spec.ts:14:1 › test1C (21ms)
...省略...
1 failed
[chromium] › test1.spec.ts:9:1 › test1B ========================================================
2 passed (2s)
シリアルと違い、test1C
のテストがスキップされず実行されました。
次にシリアルで途中で失敗させて後続がskipされてるか確認します。
import { test, expect } from '@playwright/test';
test.describe.configure({ mode: 'serial' }) // シリアルにする
test('test1A', ({ }, testInfo) => {
expect(true).toBe(true);
})
test('test1B', ({ }, testInfo) => {
expect(true).toBe(false); // 失敗させる
})
test('test1C', ({ }, testInfo) => {
expect(true).toBe(true);
})
test1B
が失敗して、後続のtest1C
がスキップされました。
(base) ❯ npx playwright test test1 --project=chromium --reporter=list
Running 3 tests using 1 worker
✓ [chromium] › test1.spec.ts:4:1 › test1A (20ms)
test1A:0
✘ [chromium] › test1.spec.ts:9:1 › test1B (6ms)
test1B:0
- [chromium] › test1.spec.ts:14:1 › test1C
...省略...
1 failed
[chromium] › test1.spec.ts:9:1 › test1B ========================================================
1 skipped
1 passed (712ms)
Discussion