読者が抱える課題
E2Eテストの実行において、テストケースごとに毎回ログイン処理(ID・パスワード入力、送信、遷移待ち)を実行すると、テスト全体の実行時間が大幅に増加します。また、認証プロバイダへの頻繁なアクセスは、アカウントロックやレートリミット(回数制限)に抵触するリスクもあります。
この記事で分かること
Playwrightの「Storage State(認証状態の保存と再利用)」機能を用いて、ログイン処理を1回のみ実行し、そのセッション情報(CookieやLocalStorage)を使い回すことで、テストを効率化・高速化する具体的な実装手順と注意点が分かります。
前提条件
- Node.jsがインストールされていること
- Playwright(TypeScript環境)がセットアップされていること
- 対象アプリケーションがCookieまたはLocalStorageベースのセッション管理を行っていること(多要素認証(MFA)が必須な環境では、追加のバイパス処理やモックが必要になる場合があります)
具体的な実装手順
Playwrightでは、globalSetupを使用する方法と、setupプロジェクト(Project Dependencies)を使用する方法があります。ここでは、公式でも推奨されている、テストの依存関係(Dependencies)を利用したクリーンな実装パターンを紹介します。
1. ディレクトリ構成例
.
├── playwriting.config.ts
├── tests/
│ ├── auth.setup.ts # ログイン処理とセッション保存を行うセットアップファイル
│ └── user-flow.spec.ts # 実際の業務シナリオテスト
└── playwriting/.auth/ # セッション情報を保存するディレクトリ(.gitignoreに要追加)
2. 設定ファイル(playwright.config.ts)の設定
playwright.config.tsで、認証処理を行うプロジェクトを定義し、通常のテストプロジェクトがその認証処理に依存するように設定します。
import { defineConfig, devices } from '@playwright/test';
// 認証情報の保存先パス
export const STORAGE_STATE = 'playwright/.auth/user.json';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000', // テスト対象のURLに合わせて変更してください
trace: 'on-first-retry',
},
projects: [
// 1. 認証処理を行うセットアッププロジェクト
{
name: 'setup',
testMatch: /.*\.setup\.ts/,
},
// 2. メインのテストプロジェクト(Chromium例)
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
// 保存されたストレージ状態を読み込む
storageState: STORAGE_STATE,
},
// setupプロジェクトが完了した後に実行する
dependencies: ['setup'],
},
],
});
3. 認証セットアップ処理(tests/auth.setup.ts)の実装
実際にログイン画面にアクセスし、認証情報を入力してログインを完了させ、その状態をファイルに保存します。
import { test as setup, expect } from '@playwright/test';
import { STORAGE_STATE } from '../playwright.config';
setup('authenticate', async ({ page }) => {
// 1. ログインページへ遷移
await page.goto('/login');
// 2. 認証情報の入力(環境変数からの読み込みを推奨)
const username = process.env.TEST_USER_EMAIL || 'default-user@example.com';
const password = process.env.TEST_USER_PASSWORD || 'password123';
await page.getByLabel('メールアドレス').fill(username);
await page.getByLabel('パスワード').fill(password);
await page.getByRole('button', { name: 'ログイン' }).click();
// 3. ログイン完了の判定(ダッシュボードへの遷移や特定の要素の表示を待つ)
await expect(page.getByRole('heading', { name: 'ダッシュボード' })).toBeVisible();
// 4. 認証状態(Cookie、LocalStorage)をファイルに保存
await page.context().storageState({ path: STORAGE_STATE });
});
4. テストコード(tests/user-flow.spec.ts)の実装
テストコード側では、ログイン処理を記述する必要はありません。テスト開始時点で既にログイン済みの状態からスタートします。
import { test, expect } from '@playwright/test';
test.describe('マイページ機能のテスト', () => {
test('プロフィール情報が表示されること', async ({ page }) => {
// ログイン後のページに直接アクセス可能
await page.goto('/profile');
// ログイン状態でないと表示されない要素を検証
await expect(page.getByText('ユーザー設定')).toBeVisible();
await expect(page.getByText('登録情報')).toBeVisible();
});
test('設定変更が保存できること', async ({ page }) => {
await page.goto('/profile');
await page.getByLabel('ニックネーム').fill('新しい名前');
await page.getByRole('button', { name: '保存' }).click();
await expect(page.getByText('設定を更新しました')).toBeVisible();
});
});
ログイン状態を「使わない」テストが混在する場合の対処法
「未ログイン状態での挙動」や「新規登録フロー」をテストしたい場合、上記の設定のままだと自動的にログイン状態が適用されてしまいます。その場合は、テストファイルまたはテストグループ単位で storageState をリセット(空に)します。
import { test, expect } from '@playwright/test';
test.describe('非ログイン状態のテスト', () => {
// このブロック内では保存されたストレージ状態(Cookie等)を使用しない
test.use({ storageState: { cookies: [], origins: [] } });
test('未ログインでマイページにアクセスするとログイン画面にリダイレクトされること', async ({ page }) => {
await page.goto('/profile');
// ログイン画面にリダイレクトされることを確認
await expect(page).toHaveURL(/\/login/);
});
});
導入時の注意点とトラブルシューティング
1. セッション情報の有効期限切れ
保存された storageState(Cookieなど)の有効期限が短い場合、テスト実行中にセッションが切れることがあります。テスト環境のトークン有効期限をテスト実行時間より長く設定するか、テスト実行前に毎回 setup プロジェクトが走るように設定を調整してください。
2. セキュリティとGit管理
保存される playwright/.auth/user.json には、実際のアクセストークンやセッションCookieが含まれます。これを誤ってGitリポジトリにコミットしないよう、必ず .gitignore に追加してください。
# .gitignore
playwright/.auth/
3. 状態のクリーンアップ
テスト間で状態が干渉し合うのを防ぐため、テスト対象のアプリケーションがLocalStorageに一時的な状態(入力途中のフォームデータなど)を保持している場合は、各テストの beforeEach で必要に応じてクリアする処理を入れてください。
まとめ
Playwrightの dependencies と storageState を組み合わせることで、ログイン処理の重複を排除し、E2Eテストの実行時間を大幅に削減できます。プロジェクトの規模が大きくなるほどこの効果は顕著になるため、初期段階での導入を推奨します。
※技術仕様やAPIの挙動はPlaywrightのバージョンアップによって変更される可能性があります。実装の際は、必ず最新のPlaywright公式ドキュメントを確認してください。