本記事では、PlaywrightのE2Eテストで globalSetupstorageState を使い、ログイン状態を一度だけ取得して各テストで再利用する仕組みを解説します。

この方式により、ログインが必要なページのテストでも毎回ログイン操作を繰り返さずに済み、テスト全体を高速かつ安定的に実行できます。

この記事で得られること

  • globalSetupstorageStateログインを1回だけ実行し、全テストで再利用する実装
  • httpOnly Cookieを含むログイン状態が保存・注入されるしくみ
  • 実際にログインするテストとログイン済み状態から開始するテストの使い分け
  • globalSetup内で成功・失敗それぞれのトレースを記録するデバッグ手法

背景と課題

これまで、ログインが必要な画面のリグレッション確認を、リリースのたびに手動で実施していました。

対象画面が十数件にのぼり、毎回30分以上の確認工数がかかっていたうえ、ログインを伴う操作フローは手動では見落としが起きやすく、リリース後に不具合に気づくケースもありました。

機能追加のペースが上がり、確認対象もさらに増えてきたことをきっかけに、これらの確認をE2Eテストで自動化し、リグレッションを継続的に担保することにしました。

E2Eテストを導入するうえで課題になるのが認証の扱いです。

テストごとにログイン操作を繰り返すと、テスト数に比例して実行時間が増え、さらにログイン処理自体の不安定さがテスト全体の信頼性を下げます。

そこで、ログインを一度だけ実行してセッション情報を保存し、各テストで再利用する仕組みを globalSetupstorageState で構築しました。本記事はその構成と運用方法をまとめたものです。

前提環境

本記事は以下の環境で動作を確認しています。お使いの環境に合わせて読み替えてください。

ツールバージョン
Node.js20.18.0 (LTS)
@playwright/test1.49.1
Nuxt3.14.0
TypeScript5.6.3
実行OSmacOS 14 / Ubuntu 22.04 (CI)

ファイル構成

E2E専用の構成として、関連ファイルは次のように配置します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
src/
├── package.json                   # test:e2e スクリプトを追加
├── playwright.e2e.config.ts       # E2E専用Playwright設定
├── .env.e2e                       # 認証情報(gitignore済み・各自作成)
├── playwright/
│   └── .auth/
│       └── user.json              # ログイン済みCookie(gitignore対象・テスト実行時に自動生成)
└── tests/
    └── e2e/
        ├── global-setup.ts        # ログイン・storageState保存
        └── auth.spec.ts           # 認証フローのテスト

E2E専用の設定ファイルを分ける理由

E2Eテストは実APIを呼び出し、実際にログインしてセッションを取得します。スナップショット比較やユニットテストなど他の種類のテストとは、API・認証・実行タイミングの要件が異なります。

そのため設定を1ファイルに混在させると、「モック設定がE2Eにも適用されて実APIが呼ばれなくなる」「不要な globalSetup が走ってしまう」といった干渉が起きます。これを避けるため、E2E専用のPlaywright設定ファイルを用意し、設定・認証・実行環境を独立させて管理します。


設計の考え方

globalSetup と storageState の流れ

1
2
3
4
5
6
7
npm run test:e2e
  └── globalSetup(テスト全体で1回だけ実行)
        └── ブラウザでログイン操作
              └── Cookie を playwright/.auth/user.json に保存
                    └── 各テスト
                          ├── 認証フロー: storageState なし(Cookie空)で実行
                          └── ログイン済みフロー: user.json を読み込んでログイン済み状態で開始

storageState を使う理由

storageState を使わない場合、すべてのテストがログイン操作を繰り返すため遅くなります。globalSetup でログイン済みのCookieをファイルに保存し、各テストはそれを再利用します。これにより高速化できます。

Playwright 公式が推奨する project dependencies

Playwright公式ドキュメントでは、setup専用プロジェクトを依存関係として定義する project dependencies が推奨されています。本記事で扱う globalSetup オプション方式とは異なるアプローチです。project dependenciesでは、HTMLレポート上にセットアップが表示され、トレース記録やPlaywright fixturesもそのまま使えるメリットがあります。

本記事では学習コスト・既存リソースとの整合性から globalSetup 方式を採用しています。HTMLレポートに統合されない点は context.tracing.start/stop で補います。リッチな統合を重視する場合はproject dependenciesの採用を検討してください(公式: Global setup and teardown)。


セットアップ手順

ファイル構成と全体の流れが把握できたところで、実際に動かすための準備を進めます。

なお、以降のコマンドはすべてpackage.jsonのあるディレクトリ(本記事ではsrc/)で実行します。

1. パッケージをインストールする

1
2
npm install -D @playwright/test dotenv
npx playwright install chromium

@playwright/test本体と、.env.e2eの読み込みで使うdotenvをインストールします。npx playwright install chromiumは、テストで使うブラウザ本体をインストールするコマンドです。

2. npm スクリプトを追加する

package.jsonscriptsへ次のコマンドを追加します。--configでE2E専用の設定ファイルを指定しています。

1
2
3
4
5
{
  "scripts": {
    "test:e2e": "playwright test --config=playwright.e2e.config.ts"
  }
}

3. .env.e2e を作成する

.env.e2e(gitignoreされているため各自で作成):

1
2
3
TEST_EMAIL=your-email@example.com
TEST_PASSWORD=your-password
API_BASE_URL=https://devwebapi.example.com

注: 本記事のドメイン(example.com)・Cookie名(sessionToken_dev)・認証情報はすべてダミー値です。実際の環境に合わせて読み替えてください。

4. playwright/.auth/ をgitignoreの対象にする

ログイン済みCookieの保存先playwright/.auth/は、テスト実行時に自動で作成されます。保存されるuser.jsonはセッショントークンを含むため、必ずgitignoreの対象にしてください。

1
2
# .gitignore に追加
playwright/.auth/

ここまでで実行に必要な準備が整いました。ここからは、実際に作成する次の3ファイルの中身を順に解説します。

  • 設定ファイル(playwright.e2e.config.ts
  • グローバルセットアップ(tests/e2e/global-setup.ts
  • テストの書き方(tests/e2e/auth.spec.ts

設定ファイル(playwright.e2e.config.ts

E2E専用の設定ファイルです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { fileURLToPath } from "url";
import path from "path";
import { defineConfig, devices } from "@playwright/test";
import dotenv from "dotenv";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, ".env.e2e") });

export default defineConfig({
  testDir: "./tests/e2e",
  globalSetup: "./tests/e2e/global-setup.ts",
  reporter: "html",
  fullyParallel: true,
  workers: 2,
  timeout: 60000,
  retries: 0,
  use: {
    baseURL: process.env.PLAYWRIGHT_BASE_URL ?? "https://devweb.example.com",
    ignoreHTTPSErrors: true,
    // PLAYWRIGHT_TRACE 環境変数で実行時に切り替え可能
    // 本設定では未指定時に "on"(全テスト記録)にフォールバックする。
    // Playwright 自体の trace デフォルトは "off"(公式は CI では "on-first-retry" 等を推奨)
    trace:
      (process.env.PLAYWRIGHT_TRACE as
        | "on"
        | "off"
        | "retain-on-failure"
        | "on-first-retry"
        | "on-all-retries") ?? "on",
  },
  projects: [
    {
      name: "Desktop Chrome",
      use: { ...devices["Desktop Chrome"] },
    },
  ],
});

ポイント:

  • globalSetup を指定することで、テスト実行前に一度だけログイン処理を実行できる
  • dotenv で .env.e2e から認証情報を読み込む(ESMプロジェクトのため import.meta.url から __dirname を生成する)

trace の設定値

trace はPlaywrightがテストの実行内容を記録するかどうかを制御します。記録されたトレースは npx playwright show-trace で確認できます。

設定値挙動用途
"off"記録しないPlaywright 標準のデフォルト
"on"全テストで常に記録する開発中・デバッグ時(※ 公式はパフォーマンス影響大として CI 非推奨)
"retain-on-failure"全テストで記録するが、成功テストは破棄するCI 環境(失敗時のみトレースを残せる)
"on-first-retry"最初のリトライ時のみ記録するretries を設定している場合(公式は CI でこちらを推奨)
"on-all-retries"すべてのリトライ時に記録するリトライごとの差分を追いたい場合

本記事の設定(前述のコード)では ?? "on" により未指定時のフォールバックを全テスト記録にしています。そのため PLAYWRIGHT_TRACE 環境変数を指定しない限り全テストのトレースが保存されます。ローカル開発では便利ですが、CIでは "on-first-retry" または "retain-on-failure" への切り替えを推奨します。

1
2
# 失敗時のみ保持したい場合(CI環境向け)
PLAYWRIGHT_TRACE=retain-on-failure npm run test:e2e

グローバルセットアップ(tests/e2e/global-setup.ts

テスト実行前に一度だけ呼ばれ、実際にブラウザでログインしてセッション情報を保存します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import { fileURLToPath } from "url";
import path from "path";
import { chromium, type FullConfig } from "@playwright/test";
import dotenv from "dotenv";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, "../../.env.e2e") });

export const AUTH_FILE = "playwright/.auth/user.json";

export default async function globalSetup(_config: FullConfig) {
  const baseURL =
    process.env.PLAYWRIGHT_BASE_URL ?? "https://devweb.example.com";
  const email = process.env.TEST_EMAIL ?? "";
  const password = process.env.TEST_PASSWORD ?? "";

  const browser = await chromium.launch();
  const context = await browser.newContext({ ignoreHTTPSErrors: true });
  const page = await context.newPage();

  await context.tracing.start({ screenshots: true, snapshots: true });

  try {
    // ログイン操作
    await page.goto(`${baseURL}/login`);
    await page.getByRole("textbox", { name: "メールアドレス" }).fill(email);
    await page.getByRole("textbox", { name: "パスワード" }).fill(password);
    await page.getByRole("button", { name: "ログイン" }).click();
    await page.waitForURL(baseURL + "/");

    // ログイン済みの Cookie をファイルに保存
    await context.storageState({ path: AUTH_FILE });

    await context.tracing.stop({ path: "./test-results/setup-trace.zip" });
    await browser.close();
  } catch (error) {
    // 失敗時も必ずトレースを保存してからブラウザを閉じる
    await context.tracing.stop({
      path: "./test-results/failed-setup-trace.zip",
    });
    await browser.close();
    throw error;
  }
}

ポイント:

  • トレースと storageState はコンテキスト単位のAPIのため、browser.newContext() を明示的に呼び出して操作している
  • context.tracing.start/stop を try/catch で囲むことで、成功・失敗それぞれのトレースを保存できる

トレースファイルの保存先は次のとおりです。セットアップ失敗時の原因調査に役立ちます。

状況ファイル
セットアップ成功時test-results/setup-trace.zip
セットアップ失敗時test-results/failed-setup-trace.zip

なお、トレースにはログイン操作のネットワーク記録(認証情報・セッションCookieを含む)が保存されます。test-results/.gitignore の対象にし、CIでアーティファクトとして保存する場合は公開範囲に注意してください。

ログイン情報の保存のしくみ

ここでは、Cookieベースのセッション認証を例に説明します。

ログイン情報を保存する流れ

globalSetup では、実際にブラウザを起動してログインフォームを操作します。ログインが成功するとサーバーがレスポンスヘッダーに Set-Cookie を返し、ブラウザのコンテキストにCookieが保存されます。

1
2
3
4
5
6
7
1. page.goto("/login")          ブラウザでログインページを開く
2. フォームへ入力・送信           メールアドレスとパスワードを入力してログインボタンをクリック
3. page.waitForURL("/")         ログイン成功後のリダイレクトを待つ
                                サーバーが Set-Cookie ヘッダーを返す
                                ブラウザのコンテキストに Cookie が自動保存される
4. context.storageState(...)    コンテキストが持つ Cookie をまるごとファイルに書き出す

context.storageState() はブラウザコンテキストが保持しているCookieをすべてJSONファイルに書き出します。Cookie認証のほか、origins キーにlocalStorageベースの認証状態も保存されます(sessionStorageは保存対象外です)。IndexedDBはv1.51以降で indexedDB: true を指定した場合のみ保存されます。

httpOnly でJavaScriptから読めないCookieも、ブラウザコンテキストが保持しているため漏れなく保存されます。

1
2
await context.storageState({ path: AUTH_FILE });
// → playwright/.auth/user.json に保存される

実際に保存されるファイルの内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
  "cookies": [
    {
      "name": "sessionToken_dev",
      "value": "(セッショントークン)",
      "domain": ".example.com",
      "path": "/",
      "expires": 1775028901,
      "httpOnly": true,
      "secure": false,
      "sameSite": "Lax"
    },
    {
      "name": "isLoggedIn_dev",
      "value": "true",
      "domain": ".example.com",
      "path": "/",
      "expires": 1775028901,
      "httpOnly": false,
      "secure": false,
      "sameSite": "Lax"
    }
  ],
  "origins": []
}

この例では、APIサーバーが検証するセッショントークンと、フロントエンドがログイン状態を判定するためのフラグの2つが保存されています。保存されるCookieの種類や名前はアプリの認証実装によって異なります。

各テストで storageState を読み込む

test.use({ storageState: AUTH_FILE }) を指定すると、テスト開始時にブラウザコンテキストへCookieが注入されます。

1
2
3
4
5
6
7
8
9
test.describe("ログイン済みフロー", () => {
  test.use({ storageState: AUTH_FILE }); // ← user.json のCookieをブラウザに注入

  test("TOPページが表示される", async ({ page }) => {
    // この時点でブラウザは user.json の Cookie を保持している
    await page.goto("/");
    // ...
  });
});

ブラウザが .example.com ドメインへリクエストを送る際に自動でCookieが付与されるため、サーバー側のセッション検証も通ります。


テストの書き方(tests/e2e/auth.spec.ts

ログイン操作に関わるテストは、次の2パターンに分けて書きます。

パターンstorageState用途
認証フロー使わない(空のCookieで開始)ログイン機能そのものの検証
ログイン済みフローglobalSetupで保存したuser.jsonを使用ログイン後の画面・機能の検証

どちらのテストも同じファイルに書けます。冒頭の共通部分は次のとおりです。

1
2
3
4
5
import { test, expect } from "@playwright/test";
import { AUTH_FILE } from "./global-setup";

const TEST_EMAIL = process.env.TEST_EMAIL ?? "";
const TEST_PASSWORD = process.env.TEST_PASSWORD ?? "";

パターン1: 実際にログイン操作を行うテスト(認証フロー)

ログイン機能そのものを検証するテストです。実際にフォームを操作してログインし、成功後の状態を確認します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// storageState を使わず、実際にログイン操作を行う
test.describe("認証フロー", () => {
  // 空の storageState を指定し、未ログイン状態から開始する
  test.use({ storageState: { cookies: [], origins: [] } });

  test("ログイン成功 → TOPページへ遷移", async ({ page }) => {
    await page.goto("/");
    await page.getByRole("button", { name: "ログイン" }).click();
    await page
      .getByRole("textbox", { name: "メールアドレス" })
      .fill(TEST_EMAIL);
    await page.getByRole("textbox", { name: "パスワード" }).fill(TEST_PASSWORD);
    await page.getByRole("button", { name: "ログイン" }).click();
    await page.waitForURL("/");
    // TOPページの描画完了を待つ
    await expect(page.locator("footer")).toBeVisible();

    await expect(page).toHaveURL("/");
  });
});

空のstorageStateを明示しておくと、設定やほかのテストの状態にかかわらず、常に未ログインの状態から開始できます。

パターン2: ログイン済み状態から開始するテスト(ログイン済みフロー)

ログイン後の画面・機能を検証するテストです。test.use({ storageState: AUTH_FILE })を指定するとglobalSetupの保存したCookieが注入され、ログイン操作なしでログイン済み状態から開始できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// globalSetup で保存した storageState を使用する
test.describe("ログイン済みフロー", () => {
  // user.json の Cookie を注入し、ログイン済み状態で開始する
  test.use({ storageState: AUTH_FILE });

  test("TOPページが表示される", async ({ page }) => {
    await page.goto("/");
    // TOPページの描画完了を待つ
    await expect(page.locator("footer")).toBeVisible();

    await expect(page).toHaveURL("/");
  });
});

ログインが必要な画面のテストは、基本的にこのパターン2で書きます。パターン1を使うのはログイン機能そのものを検証するときだけです。

ログイン再利用で削減できるコード

storageState を使わない場合、ログインが必要な各テストへ次のログイン操作を書く必要があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// storageState を使わない場合: 全テストにこのログイン操作が必要
test("TOPページが表示される", async ({ page }) => {
  await page.goto("/login");
  await page.getByRole("textbox", { name: "メールアドレス" }).fill(TEST_EMAIL);
  await page.getByRole("textbox", { name: "パスワード" }).fill(TEST_PASSWORD);
  await page.getByRole("button", { name: "ログイン" }).click();
  await page.waitForURL("/");

  // ここからが本来のテスト内容
  await expect(page.locator("footer")).toBeVisible();
  await expect(page).toHaveURL("/");
});

storageState を再利用すると、このログイン操作5行がtest.use({ storageState: AUTH_FILE })の1行に置き換わります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// storageState を使う場合: test.use の1行でログイン済み状態から開始できる
test.describe("ログイン済みフロー", () => {
  test.use({ storageState: AUTH_FILE });

  test("TOPページが表示される", async ({ page }) => {
    await page.goto("/");
    await expect(page.locator("footer")).toBeVisible();
    await expect(page).toHaveURL("/");
  });
});

テストが10件あれば、50行分のログイン操作と10回分のログイン実行を削減できます。実行時間に上乗せされるログイン処理はglobalSetupの1回だけになり、テスト数が増えても変わりません。後述の実測では、このログイン処理1回あたり約2.3秒を要していました。テストが増えるほど、この差は積み上がります。

削減できるのはコード量だけではありません。ログイン処理の失敗ポイントもglobalSetupの1箇所に集約されるため、テスト全体の安定性が向上します。


実測: ログイン方式別の実行時間

ここまでの「ログインを1回に集約する」効果を、実際に計測しました。

計測方法

同一スイート内に、本体処理(TOPページを開いて描画完了を待つだけの軽量処理)をそろえた2方式のテストを各50件ずつ用意しました。計測対象は、各テストの**「ログイン済みでページが表示できるまで」の所要時間**です。

方式各テストの処理
A. 毎テストログインテストごとにフォームから実ログイン → TOP表示
B. storageState 再利用globalSetupuser.jsonを注入 → TOP表示

本体処理を同一にしているため、両者の差はそのままログイン操作のオーバーヘッドを表します。

  • 実行: @playwright/test(Desktop Chrome / workers: 1
  • 試行: 各方式50件
  • 環境: dev環境のAPIに対する実ログイン

結果

指標A. 毎テストログインB. storageState 再利用
1テストあたり平均2,576 ms290 ms
中央値2,488 ms274 ms
最小〜最大1,916〜5,423 ms258〜466 ms
50件の合計128.8 s14.5 s

1テストあたり平均で約2.3秒(約8.9倍)短縮でき、50件では合計で約114秒(約1分54秒)の差が出ました。Aは毎回API認証の往復が入るため平均2.58秒・ばらつきも大きい(最大5.4秒)一方、Bは注入済みCookieによる遷移コストのみで平均0.29秒と安定しています。

工数への効き方

冒頭で触れたとおり、対象画面は十数件あり、手動リグレッションでは毎回30分以上かかっていました。これをE2Eに置き換えると、storageState方式ではログインはglobalSetupの1回(≈数秒)に集約され、画面数が増えてもログイン回数は1回のままです。

仮に対象が15画面の場合、毎テストログイン方式ではログインだけで 2.3秒 × 15 ≈ 35秒 を消費します。storageState方式ではこの大半を削減できます。テスト本体(実際の検証)の時間は方式によらず一定です。そのため、画面数が増えるほどログイン集約の効果は積み上がります

上記はログインのオーバーヘッドを切り出して計測した値です。実際のスイートの総時間はテスト本体の内容に依存します。


テストの実行

設定ファイル・グローバルセットアップ・テストの3ファイルがそろったら、テストを実行します。

1
npm run test:e2e

実行のたびにglobalSetupがログインし、playwright/.auth/user.jsonを更新します。テスト完了後はnpx playwright show-reportで結果を確認できます。

Playwrightが生成したHTMLレポート。テストの合否・実行時間と「View Trace」リンクが確認できる

レポートには各テストの合否と実行時間、View Traceへのリンクが並びます。storageState再利用により、ログイン済み前提の検証だけがテスト本体として記録されます。


CIでの実行

CIでは認証情報を.env.e2eとしてコミットできないため、リポジトリのSecretsに登録し、実行時に環境変数として注入します。globalSetupprocess.env.TEST_EMAIL/process.env.TEST_PASSWORDを参照するため、設定ファイルの変更は不要です。

GitHub Actionsでの例を示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: E2E

on:
  pull_request:

jobs:
  e2e:
    runs-on: ubuntu-22.04
    defaults:
      run:
        working-directory: src
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20.18.0
      - run: npm ci
      # ブラウザ本体とOSの依存パッケージをまとめて入れる
      - run: npx playwright install --with-deps chromium
      - run: npm run test:e2e
        env:
          # Secrets から認証情報を注入する
          TEST_EMAIL: ${{ secrets.TEST_EMAIL }}
          TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
          # CI では失敗時のみトレースを残す
          PLAYWRIGHT_TRACE: retain-on-failure
      # 失敗時もレポートとトレースを成果物として保存する
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: playwright-report
          path: |
            src/playwright-report/
            src/test-results/
          retention-days: 7

ポイント:

  • --with-deps でブラウザ実行に必要なOS依存パッケージも同時にインストールする(CIのクリーン環境で必要)
  • PLAYWRIGHT_TRACE=retain-on-failure で、失敗したテストのトレースだけを残す
  • if: ${{ !cancelled() }} により、テストが失敗してもレポートとトレースをアップロードする

注意: トレース(test-results/)にはログイン操作のネットワーク記録(認証情報・セッションCookie)が含まれます。アーティファクトの公開範囲を限定し、保持期間(retention-days)も必要最小限にしてください。


トラブルシューティング

globalSetup が失敗したとき

1
npx playwright show-trace test-results/failed-setup-trace.zip

Traceビューアでログイン操作の各ステップ・ネットワークリクエスト・スクリーンショットを確認できます。

Trace ビューアでログイン失敗を調査している画面。左のアクション一覧で失敗したステップが赤く示され、右にはログイン失敗のエラーが表示されたページ、下部にはConsole・Networkログが並ぶ

上の例では、ログインフォーム送信後に「ログインに失敗しました」と表示され、/loginから遷移しなかったことが一目で分かります。各ステップのDOMスナップショット・ネットワーク・コンソールログがそろっているため、失敗の原因(認証情報の誤り、APIエラーなど)を素早く切り分けられます。

ログイン済みフローのテストが認証エラーで失敗するとき

playwright/.auth/user.json を開き、Cookieが保存されているかを確認します。中身が空に近い場合、globalSetup のログインは実際には成功していません。test-results/setup-trace.zip をTraceビューアで開き、ログイン操作の流れを確認してください。

なお、globalSetup は実行のたびにログインし直すため、古いuser.jsonが残り続けることはありません。


まとめ

PlaywrightのE2Eテスト導入として、次の構成を紹介しました。

  • E2E専用の設定ファイルを用意し、他のテストから独立して管理する
  • globalSetupでログインを1回だけ実行し、storageStateでログイン状態を全テストへ再利用する
  • テストは「認証フロー」と「ログイン済みフロー」の2パターンに分けて書く
  • globalSetup内でトレースを記録し、セットアップ失敗時も原因を調査できるようにする

ログインの扱いをglobalSetupへ集約したことで、テストの実行時間とコード量を抑えながら、ログインが必要な画面のリグレッションを継続的に確認できるようになりました。

冒頭で触れたとおり、より統合度の高いセットアップを求める場合はproject dependenciesを検討してください(公式: Global setup and teardown)。

参考文献