できない.dev

Playwright の webServer が起動待ちでタイムアウトしてテストが始まらない

webServer は url か port が応答するまで待ち、既定では 60 秒で打ち切る。
ビルドを含む起動コマンドや、待ち先の URL が想定と違う設定が主な原因。
timeout を伸ばすか、待ち条件と起動コマンドを見直す。

公開:

要約

Timed out waiting 60000ms from config.webServer は、webServer に書いた起動コマンドを実行したあと、url または port が応答可能になるのを待ち切れなかった状態だ。
テスト本体のタイムアウト(既定 30 秒)とは別の設定なので、timeout を上げても直らない。

まず起動が遅いだけなのか、そもそも起動していないのかを切り分ける。

// playwright.config.ts
export default defineConfig({
  webServer: {
    command: "npm run start",
    url: "http://localhost:3000",
    timeout: 180 * 1000,
    stdout: "pipe",
  },
});

よくある原因

  1. 起動が 60 秒に収まっていない: webServer.timeout の既定値は 60000 ミリ秒である。npm run build && npm run start のようにビルドを含めると、CI では簡単に超える。
  2. 待ち先の URL が条件を満たさない: url を指定した場合、Playwright は 2xx / 3xx / 400 / 401 / 402 / 403 のいずれかが返るまで待つ。
    これ以外(500 やタイムアウト)を返し続けると待ち切れない。
  3. ホストやポートの不一致: アプリが 0.0.0.0 以外の特定インターフェースだけで待ち受けていたり、PORT 環境変数で別ポートに変わっていると、待ち先と一致しない。
  4. サーバーが即死している: 起動直後にエラー終了しているのに、stdout: 'ignore' でログを捨てているため「遅いだけ」に見えている。

解決策

1. timeout を実測に合わせる

まず手元で起動時間を測り、それより余裕のある値を入れる。

// playwright.config.ts
webServer: {
  command: "npm run start",
  url: "http://localhost:3000",
  timeout: 120 * 1000,
},

公式ドキュメント(新しいタブで開く)timeout の説明どおり、これは「プロセスが起動して応答可能になるまで待つ時間」であり、テスト 1 件あたりのタイムアウトとは独立している。

2. 起動ログを見る

原因の切り分けには標準出力が要る。ignore になっていたら外す。

// playwright.config.ts
webServer: {
  command: "npm run start",
  url: "http://localhost:3000",
  stdout: "pipe",
  stderr: "pipe",
},

ここで例外やポート衝突が見えるなら、タイムアウトは症状であって原因ではない。

3. ビルドと起動を分ける

CI ではテスト実行前にビルドを終わらせ、webServer.command は起動だけにする。

- run: npm run build
- run: npx playwright test

ビルド時間が webServer の待ち時間から外れるため、timeout を無闇に伸ばさずに済む。

4. 待ち先を素直なパスにする

url にはリダイレクトや認証を挟まないパスを指定する。
ヘルスチェック用のエンドポイントがあるならそれが最適だ。

// playwright.config.ts
webServer: {
  command: "npm run start",
  url: "http://127.0.0.1:3000/api/health",
  reuseExistingServer: !process.env.CI,
},

localhost の名前解決が IPv6 側に倒れて繋がらない環境もあるため、127.0.0.1 を直接書くと切り分けやすい。

この記事は役立ちましたか?