自動テストチュートリアル

Playwright、Seleniumなどの自動テストツールを学ぼう

Playwrightの自動待機と待機処理

⏳ テストの安定性を左右する「待機」の技術
「昨日動いたテストが今日は失敗する」の解決策

自動テストを作成していると、**「昨日動いたテストが、今日は失敗する。でも、もう一度実行したら成功する…」**という、気まぐれで不安定なテストに遭遇することがあります。

この問題のほとんどは、「待機」が原因です。

なぜ「待機」が必要なのか?

Playwrightの処理は非常に高速です。一方、Webサイトがデータを取得して画面に表示するには、コンマ数秒〜数秒の時間がかかります。

🏃‍♂️💨
テストコード
超高速で実行
🐢
Webサイト
表示に時間がかかる

テストコードは、電子レンジのタイマーが終わる前に「チン!」と音が鳴ったか確認しにいくような、せっかちなものです。

なので時より画面の表示が完了する前に「表示されていません!」と判断し、テストを失敗させてしまうこともあります。

この「テストコードの速さ」と「Webサイトの表示の速さ」のズレを吸収するために、「待機」の考え方が不可欠になります。

Playwrightの賢い「自動待機」

幸いなことに、Playwrightは非常に賢く、多くの場面でこの待機を自動で行ってくれます。これを**自動待機(Auto-waiting)**と呼びます。

✨ 自動待機の仕組み
Playwrightの公式ガイドにも記載してありますが click()fill() といった操作を行うとき、Playwrightは対象の要素が操作可能な状態になるまで、自動的に待ってくれます。

このおかげで、私たちは多くの「待機」を意識することなく、安定したテストを書くことができます。

自動待機だけでは足りないケース

Playwrightの自動待機は非常に優秀ですが、それだけではテストが安定しないことも、残念ながら多々あります。

特に、クリックした後に少し複雑な処理が動く画面などでは、この自動待機が効かずに、原因の分かりにくいテスト失敗が起きてしまうことがあります。

次は、こうした自動待機だけではカバーしきれない不安定さを解決するための、待機方法を学んでいきます。

様々な待機(wait)の方法と使い分け

1. 特定の要素を待つ locator(...).waitFor()

指定した要素が、画面上に表示されるまで待つための、最も直接的な待機コマンドです。

基本的な書き方

// 指定した要素が表示されるまで待つ
await page.locator("セレクタ").waitFor();

具体例

// idが "loading-spinner" の要素が表示されるまで待つ
await page.locator("#loading-spinner").waitFor();

2. ページの読み込み状態を待つ page.waitForLoadState()

ページの読み込み状態が、特定の段階に達するまで待機します。特に**「ネットワークが落ち着くまで待つ」**という指定が強力です。

基本的な書き方

// ネットワーク通信が落ち着くまで待つ
await page.waitForLoadState('networkidle');

指定できる状態

状態 説明
domcontentloaded HTMLの読み込みが終わるまで待つ
load 画像なども含め、ページリソースの読み込みが終わるまで待つ
networkidle ネットワーク通信がほぼなくなるまで待つ

3.【最後の手段】固定時間待機 page.waitForTimeout()

⚠️ 最後の手段

理由を問わず、指定した時間(ミリ秒)だけ、処理を強制的に停止します。

基本的な書き方

// 3秒待機
await page.waitForTimeout(3000);
他にも色々な待機方法が用意されてるので必要に応じて使い分けをしてください。

固定時間待機の考え方とリスク

固定時間待機に意味深に**【最後の手段】**と記述した理由をご説明いたします。

これは、テストを安定させるための「良い待機」ではなく、
テストを「遅く、かつ不安定にする」ための「悪い待機」だからです。

リスク1:テストが「遅く」なる

waitForTimeout(5000) は、「最大5秒待つ」という意味ではなく、**「必ず5秒間、何があっても待つ」**という命令です。

例えば、要素が表示されるまで時間がかかるため、安全のために5秒の待機を入れたとします。
その後、サーバーの性能が改善され、実際の表示は1秒で終わるようになったとしましょう。

しかし、テストコードは賢くありません。
処理が1秒で終わっていても、命令通り残りの4秒間を、何もせずにぼーっと待ち続けます
この小さな「待ちぼうけ」の時間が、テストの数だけ積み重なっていきます。

特に、何百ものテストを一度に実行するリグレッションテストでは、この数秒の無駄が積み重なり、テスト全体の実行時間が数分、数十分と、どんどん長くなってしまうのです。

これは、開発のスピードを大きく下げる原因になります。

リスク2:テストが「不安定(フレーキー)」になる

waitForTimeout は、テストを遅くするだけでなく、非常に不安定にする大きな原因にもなります。

いつもは3秒で終わる処理のために、余裕をもって waitForTimeout(5000)(5秒待機)を設定したとします。

しかし、ある日ネットワークが少し混雑し、その処理に 5.1秒 かかってしまいました。

結果、5秒の待機では足りず、テストは失敗します。
このように、固定時間待機は、その日のサーバーの調子やネットワーク環境といった、
私たちには予測できない要因によって簡単に崩壊してしまうのです。

使う際の、大切な心構え

locator(...).waitFor()page.waitForLoadState() といった優秀な待機コマンドを使っても、なぜかタイミングが合わずにテストが失敗してしまう、という非常に厄介な状況は必ずあります。

これは、画面の裏側で動いている複雑な処理などが原因で、通常の待機方法では検知しきれない場合に起こります。

そういった、waitFor系コマンドを試したけど改善されない、本当にどうしようもない場合の「最後の手段」として、固定時間待機をご利用ください。

固定時間待機を使う場合の2つのルール

1️⃣ 待機時間を現実的な範囲に
ユーザーが耐えられないような長すぎる待機時間(例:10秒)を入れてしまうと、たとえテストが成功しても、実際のユーザー体験を反映していません。

「テストをパスさせることが目的ではない」ことを意識してください。
2️⃣ なぜ待機するかをコメントに
この理由付けについては、後ほど詳しく説明します。

待機処理には、必ず「コメント」を残してください

理由1:将来、不要になった「待機」を安全に消せるようにするため

Webサイトの仕様は、日々変わっていきます。

例えば、「サーバーの応答が遅いから」という理由で3秒の待機を入れていたとしても、半年後にサーバーが新しくなれば、その待機はもう必要ないかもしれません。

コメントがなければ、未来の開発者は「この3秒の待機は、消していいものか、それとも何か重要な理由があるのか…?」と悩み、怖くて消すことができません

理由が書かれていれば、「サーバーが新しくなったから、この待機はもう不要だな」と、自信を持ってコードを改善できます。

理由2:必要な「待機」が、勝手に消されるのを防ぐため

逆に、特定の環境でだけ発生する不安定さを解決するために、やむを得ず待機を入れている場合もあります。

コメントがなければ、他の人があなたのコードを見たときに、「この待機は無駄だから消してしまおう」と、良かれと思って消してしまうかもしれません。

その結果、一度対応したはずの特定の環境でだけテストが失敗すると、不安定さを再発させることになります。

具体的な書き方

コメントは、// の後に、誰が読んでも分かるように、「何を待っているのか」や「なぜ待つ必要があるのか」を具体的に書くのがポイントです。

// 画面遷移後、非同期処理を待たないと後続のクリックにスカる
await page.waitForLoadState('domcontentloaded');

// ファイルアップロード後、5秒待たないと一覧画面に反映されない
await page.waitForTimeout(5000);
このように、一行の「なぜ?」を書き添えるだけで、書いたテストコードは、
未来のチームにとって、はるかにメンテナンスしやすく、信頼性の高い財産になるのです。

やってみよう

「待機(wait)」コマンドを実際に体験してみましょう。要素の出現を待つ方法や、指定した時間だけ処理を止める方法などを学びます。

演習ファイル

tests/document-4/lesson-07.spec.ts

手順動画

ここで紹介する待機処理のうち、waitForTimeout() 以外は目に見えて「ちゃんと待ってる!」と実感しづらいかもしれません。

そのため動画では、あえて「存在しない要素」を指定して、実際には存在しないにもかかわらず、処理がしっかり待機していることを確認しています。

進め方

  1. 演習ファイルを実行し、待機処理がどのように動作するか確認してください

  2. 興味がある方は、以下のように試してみると理解が深まります

    • waitForTimeout() の時間を長めに設定してみる
    • 存在しない要素を指定して、waitFor 系の処理が要素の表示を待つ挙動を確かめる