Playwright × Docker:本番環境に近い E2E テストを構築

現代の Web アプリケーション開発において、品質保証は欠かせない要素となっています。特に End-to-End(E2E)テストは、実際のユーザー体験を再現し、アプリケーション全体の動作を検証する重要な手法です。
しかし、従来の E2E テスト手法では本番環境との差異により、テスト結果が不安定になったり、開発チーム間で実行環境が統一できないといった課題が存在しました。本記事では、Playwright と Docker を組み合わせることで、これらの課題を解決し、本番環境に近い安定した E2E テスト環境を構築する方法をご紹介いたします。
背景
Playwright とは
Playwright は Microsoft が開発したモダンな Web アプリケーション向け E2E テストフレームワークです。Chrome、Firefox、Safari(WebKit)など複数のブラウザエンジンに対応し、高速で信頼性の高いテスト実行を実現できます。
次の図は、Playwright の基本的な動作フローを示しています。
mermaidflowchart LR
test[テストコード] -->|制御| browser[ブラウザエンジン]
browser -->|操作| page[Webページ]
page -->|結果| browser
browser -->|レポート| test
subgraph engines[対応ブラウザ]
chrome[Chromium]
firefox[Firefox]
safari[WebKit]
end
browser -.->|切替可能| engines
Playwright の主な特徴は以下の通りです。
# | 説明 |
---|---|
1 | 複数ブラウザ対応(Chromium, Firefox, WebKit) |
2 | 高速な並列実行 |
3 | 自動待機機能による安定性向上 |
4 | スクリーンショット・動画録画機能 |
5 | ネットワークインターセプト機能 |
Docker とは
Docker はコンテナ型仮想化技術を提供するプラットフォームで、アプリケーションとその実行環境を軽量なコンテナとしてパッケージ化できます。これにより、「どこでも同じ環境で動作する」を実現し、開発・テスト・本番環境の一致度を大幅に向上させることができます。
Docker の基本概念を図で示します。
mermaidflowchart TB
dockerfile[Dockerfile]
dockerfile -->|ビルド| image[Dockerイメージ]
image -->|実行| container[コンテナ]
subgraph host[ホストマシン]
container
container2[コンテナ2]
container3[コンテナ3]
end
host -->|隔離された環境| isolation[環境の独立性]
Docker を使用することで得られるメリットは以下の通りです。
- 環境の一貫性: 開発、テスト、本番環境で同じコンテナを使用
- 依存関係の解決: 必要なライブラリやツールをコンテナに含める
- スケーラビリティ: 必要に応じてコンテナの数を増減
- 分離性: 他のプロセスに影響を与えない独立した環境
従来の E2E テストの課題
従来の E2E テストでは、以下のような課題が頻繁に発生していました。
環境依存による不安定性 開発者のローカル環境、CI/CD 環境、本番環境でブラウザのバージョンや OS、ライブラリのバージョンが異なることで、テスト結果にばらつきが生じます。
セットアップの複雑さ 各開発者が個別にブラウザドライバーやテスト環境をセットアップする必要があり、初期導入のハードルが高くなっていました。
リソース管理の困難さ 複数のテストを並列実行する際、システムリソースの競合や、テスト間でのデータ競合が発生しやすい状況でした。
課題
環境差異によるテスト結果の不整合
最も深刻な問題の一つが、実行環境の違いによってテスト結果が変わってしまうことです。
以下の図は、従来の環境差異による課題を示しています。
mermaidflowchart TD
dev[開発環境] -->|テスト実行| result1[✓ 成功]
ci[CI/CD環境] -->|同じテスト実行| result2[✗ 失敗]
prod[本番環境] -->|実際の動作| result3[? 不明]
subgraph issues[差異の原因]
browser_ver[ブラウザバージョン]
os_diff[OS の違い]
network[ネットワーク設定]
timezone[タイムゾーン]
end
result2 -.->|原因| issues
具体的な課題例:
- ブラウザバージョンの違い: 開発者の Chrome と CI 環境の Chromium で動作が異なる
- 画面解像度の差異: スクリーンショット比較テストで予期しない差分が発生
- タイムゾーンの設定: 日時処理に関するテストで意図しない結果
CI/CD 環境でのテスト実行の困難さ
継続的インテグレーション・継続的デリバリー(CI/CD)パイプラインでの E2E テスト実行には、特有の課題があります。
実行時間の長期化 E2E テストは単体テストと比較して実行時間が長く、CI/CD パイプラインのボトルネックになりがちです。
デバッグの困難さ CI 環境でテストが失敗した場合、ローカル環境では再現できないケースが多く、原因の特定に時間がかかります。
リソースの制約 CI/CD サーバーのメモリや CPU リソースが限られているため、複数のブラウザを同時に起動することが困難な場合があります。
スケーラビリティの問題
プロジェクトの成長とともに、E2E テストの数も増加します。しかし、従来の手法では以下の問題が発生します:
mermaidgraph LR
small[小規模プロジェクト] -->|テスト増加| medium[中規模プロジェクト]
medium -->|さらに増加| large[大規模プロジェクト]
small -->|実行時間| time1[5分]
medium -->|実行時間| time2[30分]
large -->|実行時間| time3[2時間+]
time3 -->|問題| issues2[開発サイクルの悪化]
並列実行の制限 単一のマシンでは同時に実行できるブラウザインスタンス数に限界があります。
メンテナンス性の悪化 テスト環境の構築・維持が複雑になり、開発チーム全体の生産性に影響を与えます。
解決策
Playwright × Docker アーキテクチャ
Playwright と Docker を組み合わせることで、前述の課題を効果的に解決できます。
以下の図は、Playwright × Docker アーキテクチャの全体像を示しています。
mermaidflowchart TB
subgraph docker_env[Docker環境]
subgraph container1[Playwrightコンテナ1]
pw1[Playwright]
browser1[ブラウザ群]
end
subgraph container2[Playwrightコンテナ2]
pw2[Playwright]
browser2[ブラウザ群]
end
subgraph app_container[アプリケーションコンテナ]
webapp[Webアプリ]
database[(DB)]
end
end
test_code[テストコード] -->|実行指示| container1
test_code -->|実行指示| container2
container1 -->|HTTP通信| app_container
container2 -->|HTTP通信| app_container
container1 -->|結果| results[テスト結果]
container2 -->|結果| results
このアーキテクチャでは、以下の要素が連携します:
# | 役割 |
---|---|
1 | Playwright コンテナ: テスト実行環境を提供 |
2 | アプリケーションコンテナ: テスト対象の Web アプリケーション |
3 | データベースコンテナ: テストデータの管理 |
4 | Docker Compose: 複数コンテナの統合管理 |
コンテナ化によるメリット
Docker コンテナ化により、以下のメリットを享受できます。
環境の完全な統一 開発者のローカル環境、CI/CD 環境、本番環境で同じ Docker イメージを使用することで、環境差異を根本的に解決します。
依存関係の確実な管理 必要なブラウザ、ドライバー、ライブラリをすべてコンテナに含めることで、「動かない」問題を回避できます。
スケーラブルな並列実行 複数のコンテナを起動することで、テストの並列実行数を柔軟に調整可能です。
mermaidsequenceDiagram
participant Dev as 開発者
participant Docker as Docker
participant Container as コンテナ群
participant App as テスト対象アプリ
Dev->>Docker: docker-compose up
Docker->>Container: コンテナ群起動
Container->>App: 並列テスト実行
App->>Container: テスト結果
Container->>Docker: 結果集約
Docker->>Dev: 統合レポート
本番環境との一致度向上
Docker を使用することで、本番環境とテスト環境の一致度を飛躍的に向上させることができます。
インフラストラクチャ as Code Dockerfile と Docker Compose ファイルによって、インフラストラクチャをコードとして管理し、バージョン管理システムで追跡できます。
本番データの安全な活用 本番環境のデータベースダンプを匿名化してテスト用コンテナで使用することで、より現実的なテストが可能になります。
ネットワーク環境の再現 Docker Network を使用して、本番環境のマイクロサービス構成を忠実に再現できます。
具体例
Docker 環境のセットアップ
まずは基本的な Docker 環境を構築します。プロジェクトのルートディレクトリに以下のファイルを作成しましょう。
package.json の準備 必要なパッケージを定義します。
json{
"name": "playwright-docker-e2e",
"version": "1.0.0",
"scripts": {
"test:e2e": "playwright test",
"test:e2e:docker": "docker-compose up --abort-on-container-exit"
},
"devDependencies": {
"@playwright/test": "^1.40.0"
}
}
Dockerfile の作成 Playwright が動作するコンテナ環境を定義します。
dockerfileFROM mcr.microsoft.com/playwright:v1.40.0-focal
# 作業ディレクトリの設定
WORKDIR /app
# package.jsonとyarn.lockをコピー
COPY package.json yarn.lock ./
# 依存関係のインストール
RUN yarn install --frozen-lockfile
依存関係のインストール後、アプリケーションのソースコードをコピーします。
dockerfile# アプリケーションファイルのコピー
COPY . .
# Playwrightブラウザの追加インストール(必要な場合)
RUN npx playwright install
# テスト実行のデフォルトコマンド
CMD ["yarn", "test:e2e"]
docker-compose.yml の設定 複数のサービスを連携させるための設定を行います。
yamlversion: '3.8'
services:
# テスト対象のWebアプリケーション
web-app:
build:
context: ./app
dockerfile: Dockerfile
ports:
- '3000:3000'
environment:
- NODE_ENV=test
depends_on:
- database
データベースサービスとテスト実行サービスを追加します。
yaml # テスト用データベース
database:
image: postgres:15-alpine
environment:
POSTGRES_DB: testdb
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
# Playwrightテスト実行環境
e2e-tests:
build:
context: .
dockerfile: Dockerfile.playwright
environment:
- BASE_URL=http://web-app:3000
depends_on:
- web-app
volumes:
- ./test-results:/app/test-results
- ./playwright-report:/app/playwright-report
volumes:
postgres_data:
Playwright の設定とカスタマイズ
次に、Playwright の設定を Docker 環境に最適化します。
playwright.config.js の基本設定 テスト実行の基本設定を行います。
javascriptimport { defineConfig, devices } from '@playwright/test';
export default defineConfig({
// テストディレクトリの指定
testDir: './tests',
// 並列実行の設定
fullyParallel: true,
// CI環境での失敗時リトライ設定
retries: process.env.CI ? 2 : 0,
// テストタイムアウト設定
timeout: 30000,
});
ブラウザとプロジェクト設定を追加します。
javascriptexport default defineConfig({
// ... 前の設定
// テスト結果の出力設定
reporter: [
['html'],
['json', { outputFile: 'test-results/results.json' }],
['junit', { outputFile: 'test-results/junit.xml' }],
],
use: {
// ベースURL(Docker環境用)
baseURL:
process.env.BASE_URL || 'http://localhost:3000',
// スクリーンショット設定
screenshot: 'only-on-failure',
// 動画録画設定
video: 'retain-on-failure',
// ブラウザコンテキストの設定
viewport: { width: 1280, height: 720 },
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
],
});
環境変数による設定の動的変更 Docker 環境とローカル環境で設定を切り替えられるようにします。
javascript// Docker環境の検出
const isDocker = process.env.DOCKER_ENV === 'true';
export default defineConfig({
// Docker環境では並列実行数を制限
workers: isDocker ? 2 : undefined,
use: {
baseURL: isDocker
? 'http://web-app:3000'
: 'http://localhost:3000',
// Docker環境では headless モードを強制
headless: isDocker || process.env.CI === 'true',
},
});
CI/CD パイプラインへの組み込み
GitHub Actions を使用した CI/CD パイプラインの設定例をご紹介します。
GitHub Actions ワークフローファイル
.github/workflows/e2e.yml
を作成します。
yamlname: E2E Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
e2e-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Docker 環境でのテスト実行を設定します。
yaml- name: Run E2E tests with Docker
run: |
docker-compose up --build --abort-on-container-exit
- name: Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: |
test-results/
playwright-report/
retention-days: 7
並列実行の最適化 CI 環境でのリソースを有効活用するため、テストを分割実行します。
yamljobs:
e2e-tests:
strategy:
matrix:
shard: [1/3, 2/3, 3/3]
steps:
# ... 前のステップ
- name: Run E2E tests (Shard ${{ matrix.shard }})
run: |
export PLAYWRIGHT_SHARD=${{ matrix.shard }}
docker-compose up --build --abort-on-container-exit
実際のテストケース実装
実際の Playwright テストコードを作成します。
基本的なテストケース ユーザーログインフローのテストを実装します。
javascriptimport { test, expect } from '@playwright/test';
test.describe('User Authentication', () => {
test('should login with valid credentials', async ({
page,
}) => {
// ログインページへの遷移
await page.goto('/login');
// フォーム入力
await page.fill(
'input[name="email"]',
'test@example.com'
);
await page.fill(
'input[name="password"]',
'password123'
);
// ログインボタンクリック
await page.click('button[type="submit"]');
// ダッシュボードへのリダイレクトを確認
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText(
'Welcome'
);
});
});
データ駆動テスト 複数のテストデータを使用したテストケースです。
javascriptimport { test, expect } from '@playwright/test';
const testUsers = [
{
email: 'admin@example.com',
password: 'admin123',
role: 'admin',
},
{
email: 'user@example.com',
password: 'user123',
role: 'user',
},
{
email: 'guest@example.com',
password: 'guest123',
role: 'guest',
},
];
testUsers.forEach(({ email, password, role }) => {
test(`should login as ${role}`, async ({ page }) => {
await page.goto('/login');
await page.fill('input[name="email"]', email);
await page.fill('input[name="password"]', password);
await page.click('button[type="submit"]');
// ロールに応じた画面表示の確認
const expectedText =
role === 'admin' ? 'Admin Panel' : 'Dashboard';
await expect(page.locator('h1')).toContainText(
expectedText
);
});
});
API 通信のモック 外部 API との連携をテストする場合のモック設定です。
javascriptimport { test, expect } from '@playwright/test';
test('should handle API errors gracefully', async ({
page,
}) => {
// APIレスポンスをモック
await page.route('**/api/users/**', (route) => {
route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({
error: 'Internal Server Error',
}),
});
});
await page.goto('/users');
// エラーメッセージの表示確認
await expect(
page.locator('.error-message')
).toBeVisible();
await expect(
page.locator('.error-message')
).toContainText('データの取得に失敗');
});
スクリーンショット比較テスト 視覚的回帰テストの実装例です。
javascriptimport { test, expect } from '@playwright/test';
test('visual regression test for dashboard', async ({
page,
}) => {
await page.goto('/dashboard');
// 動的コンテンツの読み込み待機
await page.waitForSelector('.dashboard-content');
// 時刻表示などの動的要素をマスク
await page.locator('.current-time').hover();
// スクリーンショット比較
await expect(page).toHaveScreenshot('dashboard.png', {
mask: [page.locator('.current-time')],
fullPage: true,
});
});
これらの具体例により、Docker 環境での Playwright E2E テストの実装方法が明確になります。各段階で適切な設定と実装を行うことで、安定性と保守性を兼ね備えたテスト環境を構築できるでしょう。
まとめ
本記事では、Playwright と Docker を組み合わせた本番環境に近い E2E テスト環境の構築方法について詳しく解説いたしました。
従来の E2E テストで直面していた環境差異による不整合、CI/CD 環境での実行困難さ、スケーラビリティの問題を、コンテナ化技術によって根本的に解決できることをご理解いただけたかと思います。
導入による主要なメリット
- 環境統一: 開発・テスト・本番環境での一貫した動作
- 安定性向上: 環境依存による不安定なテスト結果の解消
- 開発効率化: セットアップの簡素化と並列実行による高速化
- 保守性向上: インフラストラクチャのコード化による管理の簡素化
今後の展開
本記事で紹介した基本的な構成をベースに、以下のような発展的な取り組みも可能です。
- Kubernetes 環境での大規模並列実行
- テストデータ管理の自動化
- パフォーマンステストとの統合
- セキュリティテストの組み込み
Playwright と Docker の組み合わせは、現代の Web アプリケーション開発において、品質保証の新しいスタンダードとなることでしょう。皆様のプロジェクトでも、ぜひこの手法を取り入れて、より信頼性の高いアプリケーション開発を実現してください。
関連リンク
- article
Playwright × Docker:本番環境に近い E2E テストを構築
- article
Playwright でページ遷移と状態管理をしっかり検証
- article
Playwright でアクセシビリティテストも簡単自動化
- article
Playwright と Allure でテストレポートを美しく可視化
- article
Playwright でマルチユーザー・認証テストを実現する
- article
Playwright × GitHub Actions でテスト自動化の最先端
- article
Playwright × Docker:本番環境に近い E2E テストを構築
- article
Docker でマイクロサービスを構築するアーキテクチャ入門
- article
Vite × Docker:本番運用を見据えたコンテナ化手順
- article
【解説】Docker Hub とプライベートレジストリの違いと使い分け
- article
Docker で GPU を活用する:機械学習環境を構築するための手順
- article
Docker Compose と Makefile を組み合わせて開発効率を最大化する方法
- article
Astro × TypeScript:型安全な静的サイト開発入門
- article
Playwright × Docker:本番環境に近い E2E テストを構築
- article
useQuery から useLazyQuery まで - Apollo Hooks 活用パターン集
- article
Zod で非同期バリデーション(async)を実装する方法
- article
Node.js スクリプトからサービスへ:systemd や pm2 による常駐運用
- article
Web Components Shadow DOM を使いこなす - スタイルカプセル化と Slot 活用テクニック
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来