Playwright の並列実行で大量テストを高速消化!

Playwright テストの実行時間に悩まされていませんか。テストケースが増えるたびに、実行完了を待つ時間が長くなっていく状況を解決する強力な手法があります。
大量のテストケースを効率的に処理する並列実行の威力をご紹介します。この記事では、Playwright の並列実行機能を使って、テスト実行時間を劇的に短縮する実践的な方法をお伝えします。
背景
E2E テストの実行時間が長期化する問題
現代の Web アプリケーション開発では、品質保証のために E2E テストが欠かせません。しかし、アプリケーションが成長するにつれて、テストケースも増加し続けています。
単体テストであれば数千件実行しても数分で完了しますが、E2E テストは 1 件あたり数秒から数十秒かかるため、100 件のテストでも 10 分以上の実行時間が必要になることがあります。
テストの実行時間が長くなると、開発者のフィードバックループが遅くなり、開発効率が大幅に低下してしまいます。
CI/CD パイプラインでのボトルネック
継続的インテグレーション環境では、テスト実行時間がパイプライン全体の実行時間を左右します。特に以下のような問題が発生しがちです。
- プルリクエストのマージまでに長時間を要する
- 並行して動作する複数のパイプラインでリソース競合が発生
- テスト失敗時の再実行に時間がかかり、開発スピードが低下
テスト実行時間の長期化は、チーム全体の生産性に直接影響を与える重要な課題となっています。
テスト数増加に伴う課題
機能追加やバグ修正のたびにテストケースが追加されるため、テスト実行時間は比例的に増加します。この線形的な増加は以下の問題を引き起こします。
mermaidflowchart LR
tests[テスト数] -->|線形増加| time[実行時間]
time -->|影響| dev[開発効率]
time -->|影響| ci[CI/CD速度]
dev -->|低下| quality[品質保証]
ci -->|低下| deploy[デプロイ頻度]
図で示すように、テスト数の増加が開発プロセス全体に連鎖的な影響を与えることがわかります。
課題
単一スレッドでの逐次実行の限界
従来の Playwright テスト実行では、テストが順次実行されるため、CPU やネットワークリソースが十分に活用されていません。
以下のような状況が典型的な問題です。
typescript// 従来の逐次実行パターン
test('ユーザー登録テスト', async ({ page }) => {
// 5秒かかるテスト
});
test('ログインテスト', async ({ page }) => {
// 3秒かかるテスト
});
test('商品検索テスト', async ({ page }) => {
// 7秒かかるテスト
});
// 合計: 15秒(逐次実行)
この例では、各テストが独立しているにも関わらず、合計 15 秒の実行時間が必要になります。
テスト実行時間とチーム生産性の関係
テスト実行時間の長期化は、開発チームの作業パターンに深刻な影響を与えます。
実行時間 | 開発者の行動パターン | 生産性への影響 |
---|---|---|
1-2分 | テスト完了を待機 | 高い集中力を維持 |
5-10分 | 他の作業に移行 | コンテキストスイッチ発生 |
15分以上 | 完全に別作業へ | 大幅な効率低下 |
実行時間が長くなるほど、開発者の集中力が分散し、全体的な生産性が低下してしまいます。
リソース使用率の最適化問題
現代のマシンはマルチコア CPU を搭載していますが、逐次実行では 1 つのコアしか使用されません。
mermaidflowchart TD
subgraph "逐次実行"
core1[CPU Core 1: 100%使用]
core2[CPU Core 2: 0%使用]
core3[CPU Core 3: 0%使用]
core4[CPU Core 4: 0%使用]
end
subgraph "並列実行"
pcore1[CPU Core 1: 75%使用]
pcore2[CPU Core 2: 75%使用]
pcore3[CPU Core 3: 75%使用]
pcore4[CPU Core 4: 75%使用]
end
利用可能なリソースを最大限活用することで、大幅な実行時間短縮が期待できます。
解決策
Playwright の並列実行機能
Playwright には強力な並列実行機能が組み込まれており、複数のワーカープロセスでテストを同時実行できます。
基本的な並列実行の仕組み
Playwright の並列実行は以下の仕組みで動作します。
mermaidflowchart LR
main[メインプロセス] -->|テスト配布| worker1[ワーカー1]
main -->|テスト配布| worker2[ワーカー2]
main -->|テスト配布| worker3[ワーカー3]
worker1 -->|結果収集| main
worker2 -->|結果収集| main
worker3 -->|結果収集| main
各ワーカーは独立したブラウザインスタンスを持ち、テスト間の干渉を防ぎます。
playwright.config.ts での設定
並列実行を有効にするための基本設定は非常にシンプルです。
typescript// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
// 並列実行のワーカー数を指定
workers: 4,
// テスト実行の設定
use: {
baseURL: 'http://localhost:3000',
},
});
この設定により、4 つのワーカーでテストが並列実行されます。
ワーカー数の最適化設定
ワーカー数の選択は、実行環境のリソースとテストの特性を考慮して決定する必要があります。
CPU コア数に基づく設定
typescript// CPU コア数に基づく動的設定
export default defineConfig({
workers: process.env.CI ? 2 : '50%',
});
この設定では、CI 環境では 2 ワーカー、ローカル環境では CPU コア数の 50% を使用します。
環境別の最適化
typescript// 環境別の詳細設定
export default defineConfig({
workers: (() => {
if (process.env.CI) {
// CI環境: リソース制約を考慮
return 2;
} else if (process.env.NODE_ENV === 'development') {
// 開発環境: 高速化重視
return '75%';
} else {
// 本番テスト: 安定性重視
return 1;
}
})(),
});
環境ごとに異なる戦略を採用することで、最適なパフォーマンスを実現できます。
テスト分散戦略
効果的な並列実行のためには、テストの分散方法も重要です。
ファイル単位での分散
Playwright はデフォルトでファイル単位でテストを分散します。
typescript// test1.spec.ts - ワーカー1で実行
test('テスト1-1', async ({ page }) => { /* */ });
test('テスト1-2', async ({ page }) => { /* */ });
// test2.spec.ts - ワーカー2で実行
test('テスト2-1', async ({ page }) => { /* */ });
test('テスト2-2', async ({ page }) => { /* */ });
この方法では、関連するテストを同じワーカーで実行することで、セットアップの効率化が図れます。
テスト実行時間の均等化
ファイルごとの実行時間を均等化することで、並列実行の効果を最大化できます。
typescript// 長時間テストの分割例
// 分割前: heavy-tests.spec.ts (15分)
// 分割後:
// user-registration.spec.ts (5分)
// payment-flow.spec.ts (5分)
// admin-functions.spec.ts (5分)
テストファイルを適切に分割することで、ワーカー間の負荷バランスが改善されます。
具体例
基本的な並列実行設定
実際のプロジェクトで並列実行を導入する手順を段階的に説明します。
ステップ 1: 現在の実行時間を測定
まず、現在のテスト実行時間を正確に把握します。
bash# 逐次実行での時間測定
yarn playwright test --reporter=list
実行結果の例:
sqlRunning 50 tests using 1 worker
✓ test1.spec.ts:3:1 › ユーザー登録テスト (5.2s)
✓ test2.spec.ts:3:1 › ログインテスト (3.1s)
...
50 passed (12m 34s)
ステップ 2: 並列実行の有効化
playwright.config.ts に並列実行設定を追加します。
typescript// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
// 並列実行設定
workers: process.env.CI ? 2 : 4,
// 並列実行時の設定
fullyParallel: true,
// テスト失敗時の動作
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
});
重要な設定項目の説明:
workers
: 並列実行するワーカー数fullyParallel
: ファイル内のテストも並列実行retries
: 失敗したテストの再実行回数
ステップ 3: 実行時間の比較
並列実行を有効にして時間を測定します。
bash# 並列実行での時間測定
yarn playwright test --reporter=list --workers=4
実行結果の例:
sqlRunning 50 tests using 4 workers
✓ test1.spec.ts:3:1 › ユーザー登録テスト (5.2s)
✓ test2.spec.ts:3:1 › ログインテスト (3.1s)
...
50 passed (3m 45s)
この例では、12 分 34 秒から 3 分 45 秒へと、約 70% の時間短縮を実現しています。
プロジェクト別並列実行
大規模なプロジェクトでは、複数のプロジェクト設定を使って並列実行を最適化できます。
プロジェクト設定の分離
typescript// playwright.config.ts
export default defineConfig({
projects: [
{
name: 'chrome-desktop',
use: { ...devices['Desktop Chrome'] },
testDir: './tests/desktop',
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 12'] },
testDir: './tests/mobile',
},
{
name: 'api-tests',
testDir: './tests/api',
use: { baseURL: 'http://localhost:3001/api' },
},
],
// プロジェクト別ワーカー設定
workers: '50%',
});
プロジェクト単位での実行
bash# 特定プロジェクトのみ実行
yarn playwright test --project=chrome-desktop
# 複数プロジェクトの並列実行
yarn playwright test --project=chrome-desktop --project=mobile-safari
CI 環境での最適化事例
GitHub Actions での設定例
yaml# .github/workflows/playwright.yml
name: Playwright Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Run Playwright tests
run: yarn playwright test --shard=${{ matrix.shard }}/4
- name: Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report-${{ matrix.shard }}
path: playwright-report/
この設定により、テストを 4 つのシャードに分割して並列実行し、実行時間を大幅に短縮できます。
シャーディングによる最適化
シャーディング機能を使用することで、CI 環境でのスケーラビリティを向上させられます。
mermaidflowchart TD
main[メインジョブ] -->|分割| shard1[シャード1: テスト1-12]
main -->|分割| shard2[シャード2: テスト13-25]
main -->|分割| shard3[シャード3: テスト26-37]
main -->|分割| shard4[シャード4: テスト38-50]
shard1 -->|結果| collect[結果収集]
shard2 -->|結果| collect
shard3 -->|結果| collect
shard4 -->|結果| collect
シャーディングにより、テスト実行時間を理論上 1/4 に短縮できます。
Docker での並列実行
dockerfile# Dockerfile.playwright
FROM mcr.microsoft.com/playwright:v1.40.0-focal
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
# 並列実行用の設定
ENV PLAYWRIGHT_WORKERS=4
ENV CI=true
CMD ["npm", "run", "test:ci"]
Docker 環境でも並列実行を活用することで、一貫したパフォーマンスを実現できます。
実際の改善事例
あるプロジェクトでの具体的な改善結果をご紹介します。
項目 | 改善前 | 改善後 | 改善率 |
---|---|---|---|
ローカル実行時間 | 25分 | 8分 | 68%短縮 |
CI実行時間 | 35分 | 12分 | 66%短縮 |
ワーカー数 | 1 | 4 | 4倍並列 |
テスト数 | 150件 | 150件 | 同じ |
この改善により、開発チームの生産性が大幅に向上し、より迅速なフィードバックループを実現できました。
まとめ
Playwright の並列実行機能は、テスト実行時間の大幅な短縮を実現する強力なソリューションです。
適切なワーカー数の設定とテスト分散戦略により、従来の 3 分の 1 から 4 分の 1 の実行時間でテストを完了できます。特に大規模なプロジェクトや CI/CD 環境では、その効果は絶大です。
並列実行を導入する際は、段階的なアプローチを取り、環境に応じた最適化を行うことが重要です。リソース使用率の改善とテスト実行時間の短縮により、開発チーム全体の生産性向上を実現しましょう。
継続的な測定と改善を通じて、さらなるパフォーマンス向上を目指していくことをお勧めします。
関連リンク
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来