エラーの読み方・デバッグの基礎
自動テストを書いていると、必ず「エラー」に遭遇します。赤い文字で表示されるエラーメッセージを見ると、思わず身構えてしまいますが、心配しないでください。
エラーは敵ではありません。 むしろ、「何が、どこで、なぜ間違っているのか」を教えてくれる、最も親切なヒントなのです。エラーメッセージを正しく読み解くスキルは、自動テストを使いこなす上で非常に重要になります。
テストが失敗する瞬間のリアルタイムな動き
エラーメッセージの詳細を読む前に、テストが失敗するまでのエディタ画面上のサイン(前触れ)を見ていきましょう。
多くの場合、テストは問題が発生している行で一時的にピタッと停止し、「waiting...」と表示されます。これは、Playwrightが要素を見つけようと健気に待機しているサインです。
そして、最終的にテストが失敗すると、エディタが問題の行を赤いマークや波線でハイライトし、「問題が起きているのはここですよ!」と視覚的に教えてくれます。
このハイライトされた部分にカーソルを合わせたりクリックしたりすることで、エラーの概要が表示され、原因究明の第一歩を踏み出すことができます。
エラーメッセージの構造を理解する
Playwrightが出すエラーメッセージは、一見複雑に見えますが、実は決まった構造になっています。探偵が手がかりを整理するように、以下の3つのポイントに注目してみましょう。
典型的なエラーメッセージの例①:タイムアウトエラー
Error: Timed out 5000ms waiting for expect(locator).toBeVisible()
Locator: getByRole('button', { name: 'ログイン' })
Expected: visible
Received: hidden
Call log:
- expect.toBeVisible with timeout 5000ms
- waiting for getByRole('button', { name: 'ログイン' })
...
at /path/to/your/project/tests/login.spec.ts:15:45
このメッセージから、以下の3つの重要な情報を読み取れます。
| ポイント | メッセージ | 翻訳 |
|---|---|---|
| 何が起きたのか?(結論) | Error: Timed out 5000ms waiting for expect(locator).toBeVisible() |
toBeVisible()(見えるはず)という期待を5秒間待ったけど、タイムアウトしましたよ |
| なぜ起きたか?(理由) | Expected: visible / Received: hidden |
要素が見えることを期待していたのに、実際には隠れたままでした |
| どこで起きたか?(場所) | at /.../login.spec.ts:15:45 |
login.spec.ts というファイルの15行目あたりで問題が起きましたよ |
このように、エラーメッセージは「(場所)で、(理由)のため、(結論)というエラーが起きた」という構成になっています。まずはこの構造を理解し、どこから読めばいいのかを把握しましょう。
典型的なエラーメッセージの例②:テキスト不一致エラー
これも同じように3つのポイントで読み解いていきましょう。
| ポイント | メッセージ | 翻訳 |
|---|---|---|
| 何が起きたのか?(結論) | Error: expect(locator).toHaveText(expected) failed |
toHaveText()という期待が失敗しました |
| なぜ起きたか?(理由) | Expected string: "予約完了しました" / Received string: "予約を完了しました" |
期待していた文字列と、実際に画面にあった文字列が異なっていました |
| どこで起きたか?(場所) | Locator: locator('h5.modal-title') |
モーダルのタイトル部分で問題が起きていることが分かります |
よく見比べると、助詞の「を」があるかないかだけの違いだと分かります。このように、たった一文字、あるいはスペースが一つ違うだけでもテストは失敗として正確に検知してくれます。
自動テストでよく出会うエラーの種類
SyntaxError(構文エラー)
簡単に言えば、自身の実装に間違いがある場合に発生します。
エラーの具体例:
SyntaxError: Unexpected token 'const'
発生例:
test('フォームに入力する', async ({ page }) => {
const name = 'Taro'
const email = 'taro@example.com';
const message = 'こんにちは';
await page.locator('#name').fill(name)
const email = 'test@example.com'; // ← ここで再宣言してエラーになる
await page.locator('#email').fill(email);
});
原因: 同じスコープで const を2回宣言している。
elements found for selector(複数要素に一致)
エラーの具体例:
Error: strict mode violation: 4 elements found for selector "#submit"
発生例:
画面内に同じ要素が複数あり、何番目の要素を取得するかを指定していない場合に発生します。例えば「このプランで予約」をクリックする処理をしたいけど、同じボタンが4つあるからどれをクリックしたらいいのかわからないと怒られています。
原因: 画面上に、定義した要素が複数存在する場合に発生するエラーです。
このエラーが出たら、ほぼ確定落ちだと判断して大丈夫です。
スクリーンショットの確認方法
Playwrightは、テストが失敗した瞬間の画面を画像として自動的に保存する機能を備えています。
このスクリーンショットを見ることで、エラーメッセージだけでは分からない画面のレイアウト崩れや、予期せぬポップアップの表示など、エラー原因を特定するための視覚的な情報を得ることができます。
スクリーンショットが保存される場所とタイミング
スクリーンショットは、テストが失敗した場合にのみ、プロジェクトフォルダ内に自動で作成される test-results というフォルダの中に保存されます。
【重要】フォルダは毎回上書きされます
test-results フォルダの中身は、次回のテスト実行時に一度クリア(削除)され、その回のテスト結果で上書きされます。
そのため、前回の失敗で保存されたスクリーンショットは、テストを再実行すると消えてしまいます。必要なスクリーンショットは、原因調査が終わるまで残しておくか、別の場所にコピーするように注意してください。
【重要】「通常モード」でのみ自動撮影される
この便利なスクリーンショット機能ですが、通常モードで実行した際に、テストが失敗した場合にのみ自動で撮影されます。
デバッグの考え方
エラーに遭遇したとき、一番やってはいけないのは、焦ってやみくもにコードを修正することです。
| ステップ | やること |
|---|---|
| 1. エラーメッセージを読む | まずは落ち着いて、上で説明した3つのポイント(何が、なぜ、どこで)を読み解きます |
| 2. 仮説を立てる | 「セレクタが間違っているのかも?」「待機が足りないのかも?」という仮説を立てます |
| 3. 検証する | スクリーンショットを見たり、開発者ツールで調べたりして、仮説が正しいかを確認します |
| 4. 修正して再実行 | 原因が特定できたら、コードを修正して、もう一度テストを実行します |
デバッグは、まさに探偵の仕事です。エラーメッセージという「手がかり」を元に、原因という「犯人」を突き止めるプロセスを楽しみましょう。この経験を繰り返すことで、より早く、正確に問題を解決できるようになります。