🌱

Playwright Test Agentsのseed.spec.tsって結局何なの?

に公開

はじめに

先日ようやくPlaywright Test Agentsを試すことができました。E2Eテストの作成や保守において、かなり強力なツールが登場したなという印象です。

https://youtu.be/Utbz2fI0vhM?si=amVaahSbEwsf7Ykm

この記事では、Playwright Test Agentsを使う中でつまずいた seed.spec.ts の役割について深堀りしていきます。公式ドキュメントの説明だけでは正直よくわからなかったので、MCPのコードを実際に読んで仕組みを理解するに至った過程を共有します。

公式ドキュメントの説明のつまずき

Playwright Test Agentsを使い始めて最初につまずいたのが seed.spec.ts の存在でした。

公式ドキュメントを見ても、執筆時点(2025/12/04)では以下のような一文が書かれているだけです。

公式ドキュメントのスクリーンショット

Seed tests provide a ready-to-use page context to bootstrap execution.

仕組みを理解した今となっては「なるほど」と思えるのですが、初めて見たときは正直よくわかりませんでした

具体的に何が不明確だったかというと:

  • 誰のための ready-to-use page contextなのか?
  • 誰が bootstrap executionするのか?

主語が省略されているせいで、この文章が指している対象がぼんやりしているのですよね。Playwrightのテスト実行時の話なのか、それともAgents特有の何かなのか...。

MCPのコードを読んでみる

ドキュメントを眺めていても埒が明かないので、MCP(Model Context Protocol:AIエージェントがツールを呼び出すための標準プロトコル)のコードを実際に見てみることにしました。

エージェントのプロンプトを確認

ポイントとなるのは初期化コマンドで生成される2つのエージェント設定ファイルです。

npx playwright init-agents --loop=vscode

このコマンドを実行すると、以下の2つが生成されます。

  • playwright-test-planner.md
  • playwright-test-generator.md

まずPlannerのプロンプトを確認してみると、こんな記述がありました。

1. **Navigate and Explore**
   - Invoke the `planner_setup_page` tool once to set up page before using any other tools
   - Explore the browser snapshot
   - Do not take screenshots unless absolutely necessary
   - Use `browser_*` tools to navigate and discover interface
   - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality

注目すべきは planner_setup_page ツールを使う よう指示している点です。

Generatorも同様に確認すると:

# For each test you generate
- Obtain the test plan with all the steps and verification specification
- Run the `generator_setup_page` tool to set up page for the scenario

こちらは generator_setup_page を使うよう指示されています。

MCPツールの実装を見てみる

では、これらのツールは何をしているのか?実装を見てみましょう。

https://github.com/microsoft/playwright/blob/f9e1797a0d6025a0cc499692d79bb10a806eadc1/packages/playwright/src/mcp/test/plannerTools.ts#L23C14-L40

export const setupPage = defineTestTool({
  schema: {
    // プロンプトに書かれていたツール名
    name: 'planner_setup_page',
    title: 'Setup planner page',
    description: 'Setup the page for test planning',
    inputSchema: z.object({
      project: z.string().optional().describe('Project to use for setup. For example: "chromium", if no project is provided uses the first project in the config.'),
      // デフォルトで seed.spec.ts を seedFile として使っている
      seedFile: z.string().optional().describe('A seed file contains a single test that is used to setup the page for testing, for example: "tests/seed.spec.ts". If no seed file is provided, a default seed file is created.'),
    }),
    type: 'readOnly',
  },

  handle: async (context, params) => {
    const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);
    // seed.spec.tsをまず実行している
    const { output, status } = await context.runSeedTest(seed.file, seed.projectName);
    return { content: [{ type: 'text', text: output }], isError: status !== 'paused' };
  },
});

ここで重要なのは context.runSeedTest() です。PlannerやGeneratorが任務を遂行する前に、まずseed.spec.tsを実行している ことがわかります。

謎が解けた:seed.spec.tsの正体

ここまで読めば、冒頭のドキュメントの意味がクリアになります。

Seed tests provide a ready-to-use page context to bootstrap execution.

これは言い換えると:

  • 誰のための ready-to-use page contextなのか?PlannerやGenerator(AIエージェント)のため
  • 誰が bootstrap executionするのか?PlannerやGeneratorが実行する

つまり、seed.spec.tsPlaywrightのテストのためのseedファイルではなく、PlannerやGeneratorがブラウザを操作・探索する前の「セットアップ用のファイル」 だったのです。

seed.spec.tsに書くべき内容

この仕組みを踏まえると、多くの場合 seed.spec.ts には以下のような内容を含めることになるでしょう。

  • PlannerやGeneratorの探索に使いたいユーザーのログイン処理
  • Plan/Generateに必要なデータの投入や環境の初期化処理

たとえば管理者画面のテストを生成したい場合、seed.spec.tsで管理者としてログインしておけば、Plannerはログイン後の状態から探索を始められるわけです。

具体的には、以下のようなコードが1例となります。

import { test, expect } from '@playwright/test';

const authFile = 'playwright/.auth/user.json';
const testUsername = 'testuser';

test.describe('Test group', () => {
  // requestはPlaywrightのAPIRequestContext
  // https://playwright.dev/docs/api/class-apirequestcontext
  test('seed', async ({ page, request }) => {
    // ログインページにアクセス
    await page.goto('/');

    // ログインフォームに入力
    await page.getByLabel('ユーザー名').fill(testUsername);
    await page.getByLabel('パスワード').fill('password123');
    await page.getByRole('button', { name: 'ログイン' }).click();

    // ログイン成功を確認
    await expect(page).toHaveURL('/products');

    // テスト用にユーザーのデータをリセット
    // ※ これはアプリ側にテストデータ初期化用のAPIがある想定の例です
    //    実際のプロジェクトでは、必要に応じて独自の初期化処理を実装してください
    const resetResponse = await request.post('/api/test/reset', {
      data: { username: testUsername },
    });
    expect(resetResponse.ok()).toBeTruthy();

    // ログイン状態を保存
    await page.context().storageState({ path: authFile });
  });
});

このように、ログイン処理やテストデータのリセットなど、エージェントが探索を始める前に必要な準備をseed.spec.tsに記述します。

既存のsetup/fixturesとの違いは?

ここで一つ疑問が湧きました。

「そもそもPlaywrightって似たような仕組み持ってなかったっけ?」

Global Setup / Teardown

Playwrightには setup のやり方がプラクティスとしてドキュメントにもあります。

https://playwright.dev/docs/test-global-setup-teardown

Fixtures

さらにはFixturesという概念もあり、テストを堅牢に書くための仕組みが用意されています。

https://playwright.dev/docs/test-fixtures

決定的な違い

これらと seed.spec.ts は根本的に目的が異なります。

仕組み 誰のため いつ実行される
Global Setup テスト実行のため npx playwright test 実行時
Fixtures テスト実行のため 各テスト実行時
seed.spec.ts AIエージェントのため Planner/Generator起動時

seed.spec.tsは Playwrightのテストランナーが実行するものではなく、AIエージェントがMCPツール経由で実行するもの です。テスト実行とは完全に別のライフサイクルで動いています。

生成されるコードのコメントについて

もう一点、混乱の元になっていたのが、PlannerやGeneratorが生成するテストコードのコメントです。

// spec: specs/basic-operations.md
// seed: tests/seed.spec.ts  // <-- このコメントがややこしい

import { test, expect } from '../fixtures';

test.describe('Adding New Todos', () => {
  test('Add Valid Todo', async ({ page }) => {
    // 1. Click in the "What needs to be done?" input field
    const todoInput = page.getByRole('textbox', { name: 'What needs to be done?' });
    // ...
  });
});

この // seed: tests/seed.spec.ts というコメントを見て、「もしかしてこの記述をトリガーに seed.spec.ts がPlaywrightのテスト実行時にも走るの?」と思ったりしたんですよね。

結果的に、このコメントは単なるメタデータ でした。どのseedファイルを使って生成されたかを記録しているだけで、テスト実行時に何か特別な動作をするわけではありません。

魔法のような新機能が増えたわけではなく、あくまで「このテストはこのseed環境で生成しましたよ」という情報を残しているだけです。

中〜大規模プロジェクトでの活用イメージ(仮説)

ここまで理解できると、中規模から大規模なプロジェクトでの活用イメージも見えてきます。

複数のseedファイルを用意する

先ほど見たMCPツールの実装では、seedFile パラメータが渡せることが確認できました。これを活用すれば、様々なアクターやユースケースに応じて複数のseedファイルを用意できるはずです。

tests/
├── seeds/
│   ├── admin-seed.spec.ts      # 管理者でログイン済み
│   ├── member-seed.spec.ts     # 一般会員でログイン済み
│   ├── guest-seed.spec.ts      # 未ログイン状態
│   └── checkout-seed.spec.ts   # カートに商品が入った状態
└── ...

Planner/Generatorを起動する際に、目的に応じたseedファイルを指定することで、効率的にテスト計画・生成ができるようになるのではないかと予想しています。

メリットとデメリット

メリット

  • ログイン処理など、毎回の探索で繰り返す必要がある操作を省略できる
  • 特定の状態(カートに商品がある、等)からテスト生成を始められる
  • アクター(管理者/一般ユーザー/ゲスト)ごとにテスト生成の起点を分けられる

デメリット

  • seedファイルの管理が必要になる(アプリの変更に追従が必要)
  • seedファイル自体のメンテナンスコストがかかる(これは仕方がない)
  • 複数のseedファイルがあると、どれを使うべきか判断が必要(複雑なアプリになるほどこれも仕方がない)

銀の弾丸ではありませんが、適切に使えばテスト生成の効率は上がりそうです。

まとめ

この記事では、Playwright Test Agentsの seed.spec.ts について掘り下げてきました。

ポイント

  • seed.spec.tsAIエージェント(Planner/Generator)のため のファイル
  • Playwrightのテスト実行時ではなく、エージェント起動時にMCPツール経由で実行される
  • 既存のGlobal SetupやFixturesとは 目的もライフサイクルも別物
  • 生成されたテストの // seed: ... コメントは 単なるメタデータ

まだ新しい機能なのでドキュメントが追いついていない部分もありますが、MCPのコードを読むことで仕組みを理解できたので、今後は迷わず使えそうです。

いずれにせよ、Playwright Test Agentsはうまく活用することでE2Eテストとの付き合い方が楽しくなりそうです。今後の発展にも期待したいと思います!

関連動画

Playwrightについてもっと知りたい方は、以下の動画もぜひご覧ください。

Discussion