【Playwright⑦】非同期処理とイベント待機

非同期処理は、UI操作やネットワークリクエストなど、時間のかかる処理を管理するために不可欠だ。E2Eテストにおいても、非同期処理を正確に扱うことで、予期せぬエラーやタイミングのずれを防ぎ、より信頼性の高いテストを実現できる。この記事では、Playwrightを使った非同期処理とイベント待機のテクニックを紹介し、具体的なシナリオでどのように活用できるかを解説する。

公式ドキュメント: https://playwright.dev/docs/events
公式ドキュメント: https://playwright.dev/docs/api/class-page#page-wait-for-request

イベント待機の基本

ページナビゲーションとイベント

Playwrightでは、waitForEventwaitForNavigation を使って、確実にイベントが完了するのを待つことができる。この機能は、リンククリック後のページ遷移をテストする場面で有効。

例えば、以下のコードはリンクをクリックした後、ページのナビゲーションが完了するまで待機する。

const navigationPromise = page.waitForNavigation();
await page.click('a#link');
await navigationPromise;

この手法を用いることで、テストがリンククリック後の遷移を正確に追跡し、予期せぬタイミングのずれによるエラーを防ぐ効果がある。

ネットワークリクエストの待機

waitForRequestwaitForResponse

API呼び出しや画像のロードなど、特定のネットワークリクエストが完了するのを待つことが求められるシナリオも多い。このような場合、waitForRequestwaitForResponse を使えば、リクエストやレスポンスを確実にキャプチャできる。

const requestPromise = page.waitForRequest('**/*logo*.png');
await page.goto('https://example.com');
const request = await requestPromise;
console.log(`Requested URL: ${request.url()}`);

これにより、指定したリソースが確実にリクエストされたかを検証し、バックエンドとの通信に依存する機能が正しく動作しているかを確認できる。

サンプル実装

この機能は、私も開発現場でかなり多く使ったため、
Nuxt3を使ったサンプルコードと実際のテストコードを紹介するので、具体的なイメージを掴んで欲しい。

リクエスト検証にはJSON Placeholderを使用する。

Vueテンプレート: pages/test/playwright/events.vue

まず、初期描画時にデータの取得を行い、一覧を描画する。

<template>
  <v-container>
    <h1>Posts</h1>
    <v-divider class="my-4" />
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </v-container>
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";

type Post = {
  userId: number;
  id: number;
  title: string;
  body: string;
};

const posts = ref<Post[]>([]);

const fetchData = async () => {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    posts.value = await response.json();
  } catch (error) {
    console.error(error);
  }
};

onMounted(() => {
  fetchData();
});
</script>

http://localhost:3000/test/playwright/eventsにアクセスすると、以下のような見た目になる。

次に、テストコードを実装する。

テスト: tests/events.spec.ts

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

test("waitForResponse", async ({ page }) => {
  // ページに遷移
  await page.goto("http://localhost:3000/test/playwright/events");
  // 最初の API リクエストが完了するのを待つ
  await page.waitForResponse("https://jsonplaceholder.typicode.com/posts");
  // API からのデータが正しく表示されているか確認する
  const postTitles = await page.locator("ul > li").allTextContents();
  // 少なくとも1件以上の表示があること
  expect(postTitles.length).toBeGreaterThan(0);
  // 1件目の投稿タイトルに特定の文字列が含まれていること
  expect(postTitles[0]).toContain("sunt aut facere repellat provident occaecati");
});

実際にテストに成功していることがわかる。

waitForRequestwaitForResponseの使い分け

waitForRequest と waitForResponse の使い分けは、テストの対象となる操作やシナリオに依存する。
具体的には、テストで「何を待機する必要があるか」によって使い分けを行う。

waitForRequest の使いどころ

waitForRequest は、特定のリクエストが送信されたことを確認したい場合に使用する。
例えば、ボタンをクリックしたときにAPIリクエストが発生するかをテストしたい場合など。
この時、レスポンスに関してはテストで関与しない。

waitForResponse の使いどころ

waitForResponse は、特定のリクエストに対するレスポンスが返ってきたことを確認したい場合に使用する。
特に、リクエストに対するレスポンスの内容やステータスコードを確認する必要がある場合など。

まとめ

非同期処理とイベント待機は、WEBアプリケーションのテスト(特に、動的コンテンツや外部APIとの連携が重要なシナリオ)で必須のため、これらのテクニックを適切に活用することで、テストの品質を向上できる。次回は、スクリーンショットを活用したビジュアルテストについて解説する。

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

もし参考になりましたら、下記のボタンで教えてください。

関連記事

コメント

この記事へのトラックバックはありません。