🎭

Playwright でのテスト信頼性向上 - 画像アップロード編

に公開

はじめに

最近WebアプリケーションのPlaywrightを用いたE2Eテストのテスト信頼性を向上する(flakinessを解消する)ために、用いた手法を本記事で紹介します。

解消したかったこと

Webアプリケーションで画像をアップロードして、その後にアップロードした画像が表示されることを確認するE2Eテストを実装していました。この「アップロードした画像が表示されること」を確認するために、画像要素のスクリーンショットによる判定をしていました。

const [fileChooser] = await Promise.all([
  page.waitForEvent("filechooser"),
  page.getByRole("button", {name: "画像を選択"}).click(),
]);
await fileChooser.setFiles("avatar-image.png");
await page.getByRole("button", { name: "画像をアップロード" }).click();

await expect(page.getByRole("img", { name: "avatar" })).toHaveScreenshot("expected-image.png");

ところが、toHaveScreenshot の判定が、アップロードされた画像が画面に表示される前に実行されてしまうことがあり、ときどき失敗していました。

解消方法

画像要素のsrc属性を確認する

画像要素のsrc属性が、アップロードした画像のURLに変わるまで待つようにしました。
明示的にsrc属性が変わることを待機するように記述する必要はなくtoHaveAttributeで属性が変わるまで待機してくれます(auto-waitingありがたい)。

+await expect(page.getByRole("img", { name: "avatar" })).toHaveAttribute("src", /avatar-image\.png$/);
 await expect(page.getByRole("img", { name: "avatar" })).toHaveScreenshot("expected-image.png");

画像取得のレスポンスを待機する

対象のWebアプリケーションでは、画像アップロード後に画像を取得するためのAPIを呼び出していました。そこで、画像取得のレスポンスが返ってくるまで待機するようにしました。

- await fileChooser.setFiles("avatar-image.png");
- await page.getByRole("button", { name: "画像をアップロード" }).click();
+ await Promise.all([
+  page.waitForResponse((response) =>
+    response.url().match("/\/api\/images\/avatar-image\.png$") &&
+    response.request().method() === "GET" &&
+    response.status() === 200
+  ),
+  await fileChooser.setFiles("avatar-image.png"),
+  await page.getByRole("button", { name: "画像をアップロード" }).click(),
+ ]);

最終的なコード

const [fileChooser] = await Promise.all([
  page.waitForEvent("filechooser"),
  page.getByRole("button", {name: "画像を選択"}).click(),
]);
await Promise.all([
  page.waitForResponse((response) =>
    response.url().match("/\/api\/images\/avatar-image\.png$") &&
    response.request().method() === "GET" &&
    response.status() === 200
  ),
  await fileChooser.setFiles("avatar-image.png"),
  await page.getByRole("button", { name: "画像をアップロード" }).click(),
]);
await expect(page.getByRole("img", { name: "avatar" })).toHaveAttribute("src", /avatar-image\.png$/);
await expect(page.getByRole("img", { name: "avatar" })).toHaveScreenshot("expected-image.png");

おわりに

以上、Playwrightでのテスト信頼性向上のために行ったことを紹介しました。画像の反映待ちは、よくある課題かと思いますので、同じような課題を抱えている方の参考になれば幸いです。

GitHubで編集を提案

Discussion