チュートリアル
Shotomatic Team
読了まで約16分

Playwrightでスクリーンショットテストを行う方法

Playwrightで視覚的な基準画像を作り、ブラウザ別に実行し、安定した待機条件や差分しきい値、更新手順を設定する方法を解説します。

Playwrightのスクリーンショットテスト用コードを表示したノートパソコン

Playwrightのスクリーンショットテストは、公開前に気づきたいUIの変化を検出するためのものです。テストでページを開き、表示が安定するまで待ち、画像を撮影して、承認済みの基準画像と比較します。通常のスクリーンショット自動化ビジュアルリグレッションテストの違いは、この比較にあります。

ここでは公開ページの例として、Shotomaticの機能ページ https://www.shotomatic.com/ja/features を使います。この手法がより役立つのは、データ、ログイン状態、アニメーション、テスト用セレクタを制御できる自社アプリです。

開示: 私たちはShotomaticを開発しているため、例には公開中の機能ページを使っています。Playwrightの説明は、現行の公式ドキュメントをもとにしています。

URL一覧から画像ファイルを作るだけなら、Playwrightによる通常のスクリーンショット自動化から始めてください。この記事では、基準画像、画像比較、ブラウザプロジェクト、レビューというテスト用途を扱います。

スクリーンショットテストが役立つ場面

通常のアサーションでは見落としやすい表示崩れを検出したいときに向いています。

適している例は次のとおりです。

  • ヒーロー、料金、登録セクションなどが重要なマーケティングページ
  • 状態の多いデザインシステムのコンポーネント
  • レイアウトが重要な決済、オンボーディング、ダッシュボード画面
  • モバイル幅で崩れやすいレスポンシブページ
  • CSSの変更でコンテンツがずれたり隠れたりする可能性があるページ

向いていない例もあります。

  • フィード、広告、時刻、ユーザー投稿などが絶えず変わるページ
  • 見た目の仕上がりが重要ではないページ
  • テキスト、role、動作のアサーションで十分に確認できているフロー
  • 不安定なページが何百もあり、差分を確認する体制がないサイト全体

まずは重要な画面を数枚選びます。何でも監視対象にすると、スクリーンショットテストは不要な失敗が増えます。

Playwright Testをインストールする

新規または既存のNodeプロジェクトでは、Playwrightの公式インストーラーからテストランナー、設定ファイル、サンプルテスト、ブラウザのインストール手順をまとめて用意できます。

$ npm init playwright@latest

インストーラーでは、TypeScriptとJavaScriptの選択、テストの保存先、GitHub Actionsワークフローの追加、ブラウザのインストールについて尋ねられます。設定後にテストを実行します。

$ npx playwright test

この記事の例では、tests/ 以下にTypeScriptファイルを置きます。

最初のスクリーンショットテストを作る

tests/features-page.spec.ts を作成します。

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

test("features page has a stable desktop layout", async ({ page }) => {
  await page.goto("https://www.shotomatic.com/ja/features");

  await expect(
    page.getByRole("heading", {
      name: /Shotomaticでできること/i,
    }),
  ).toBeVisible();

  await expect(page).toHaveScreenshot("features-page-desktop.png", {
    fullPage: true,
  });
});

page.screenshot()との大きな違いは、アサーションであることです。Playwright TestのtoHaveScreenshot()は基準画像を作成するか、現在の画像を基準画像と比較します。初回の実行では、まだ存在しない基準画像を書き出します。2回目以降は、その保存済み画像と新しいスクリーンショットを比較します。

テストを実行します。

$ npx playwright test tests/features-page.spec.ts

初回は基準画像がないため、新しい期待画像が作られます。コミットする前に内容を確認してください。基準画像は無関係な生成物ではなく、テストの期待値です。

ページの一部だけをテストする

ページ全体のスクリーンショットは大きなレイアウト変化を見つけられる一方、下部にある無関係な変更でも失敗しやすくなります。多くのチームでは、セクションやコンポーネント単位の基準画像のほうが保守しやすいでしょう。

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

test("features comparison cards stay aligned", async ({ page }) => {
  await page.goto("https://www.shotomatic.com/ja/features");

  const comparisonHeading = page.getByRole("heading", {
    name: /作りたい記録から選ぶ/i,
  });
  const comparisonSection = page.locator("section").filter({
    has: comparisonHeading,
  });

  await expect(comparisonHeading).toBeVisible();
  await expect(comparisonSection).toHaveScreenshot("features-comparison-section.png");
});

「このセクションの見た目が崩れていないか」という局所的な確認にはlocatorのスクリーンショットを使います。ページ全体のレイアウトが重要なら、ページのスクリーンショットが適しています。

ブラウザとデバイスのプロジェクトを追加する

Playwrightのテストランナーは、名前を付けた複数のプロジェクトで同じテストを実行できます。単純な撮影スクリプトとの違いがはっきりする部分です。ブラウザ、デバイス、viewport、スナップショット名をテストマトリクスに含められます。

playwright.config.ts の例です。

import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
  testDir: "./tests",
  use: {
    baseURL: "https://www.shotomatic.com",
    trace: "on-first-retry",
  },
  projects: [
    {
      name: "desktop-chromium",
      use: {
        ...devices["Desktop Chrome"],
        viewport: { width: 1440, height: 1000 },
      },
    },
    {
      name: "mobile-safari",
      use: {
        ...devices["iPhone 13"],
      },
    },
  ],
});

テストでは相対URLを使います。

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

test("features page visual baseline", async ({ page }) => {
  await page.goto("/ja/features");
  await expect(page.getByRole("main")).toBeVisible();

  await expect(page).toHaveScreenshot("features-page.png", {
    fullPage: true,
  });
});

Playwrightはプロジェクトごとに別のスナップショットを保存します。デスクトップとモバイルの表示が同じであるかのように扱わず、それぞれの基準画像を並べて管理できます。デバイスごとの表示を確認したいなら、単一のviewportで撮るより適した方法です。

ページの状態を安定させる

不要な差分の多くは、ページの状態が安定していないために起きます。Playwrightはスクリーンショットのアサーション中、CSSアニメーションとトランジションを初期設定で無効にします。それでも、変化するデータ、遅れて表示されるコンテンツ、広告、ユーザー固有の要素は画像を変化させます。

撮影前には、明確な条件を待ちます。

await page.goto("/ja/features");
await expect(page.getByRole("main")).toBeVisible();
await expect(page.getByText("手を離して撮影")).toBeVisible();

主な待機条件として固定時間のタイムアウトに頼らないでください。カード、見出し、表、画像などがそろって初めてページの準備が整うなら、その条件を直接待ちます。

画面外のコンテンツが遅延読み込みされるページでは、ページ全体を撮影する前にスクロールします。

await page.evaluate(async () => {
  const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
  const viewportHeight = window.innerHeight;

  for (let y = 0; y < document.body.scrollHeight; y += viewportHeight) {
    window.scrollTo(0, y);
    await delay(100);
  }

  window.scrollTo(0, 0);
});

ページに必要なら、このような補助関数を使ってかまいません。後から読む人がスクロールの理由を理解できるよう、テストの近くに置きましょう。

変化する要素を非表示またはマスクする

時刻、アバター、広告、ユーザー名、読み込み表示、動画のサムネイルなど、視覚的な比較に含めるべきではない要素もあります。

主な方法は二つあります。

特定のlocatorをマスクします。

await expect(page).toHaveScreenshot("features-page.png", {
  fullPage: true,
  mask: [page.locator("[data-testid='release-date']")],
});

または、スクリーンショットの撮影時にスタイルシートを適用します。

await expect(page).toHaveScreenshot("features-page.png", {
  fullPage: true,
  stylePath: "./tests/screenshot.css",
});

tests/screenshot.css の例です。

[data-testid="release-date"],
[data-testid="animated-cursor"] {
  visibility: hidden !important;
}

テストを通すためだけに、実際の製品UIを隠してはいけません。マスクは、確認したい見た目とは関係のない変動要素に使います。

差分のしきい値は慎重に設定する

Playwrightでは、限られたピクセル差を許容できます。

await expect(page).toHaveScreenshot("features-page.png", {
  fullPage: true,
  maxDiffPixels: 100,
});

小さな描画差には便利ですが、本当の不具合まで見逃すおそれがあります。しきい値は低く保ち、必要な理由を記録してください。比較条件を緩める前に、ページの状態を安定させる方法を優先します。

スクリーンショットのアサーションに共通する初期値は、playwright.config.ts にも設定できます。

import { defineConfig } from "@playwright/test";

export default defineConfig({
  expect: {
    toHaveScreenshot: {
      maxDiffPixels: 100,
    },
  },
});

基準画像を確認して更新する

スクリーンショットテストが失敗したときに考えるべきなのは、「どうすればテストが通るか」ではありません。「この表示変更は想定どおりか」を確認します。

不具合ならUIを修正し、テストをやり直します。意図した変更なら、基準画像を更新します。

$ npx playwright test --update-snapshots

続いて、pull requestで新しい基準画像を確認します。スナップショットの更新もコード変更と同じように扱ってください。誰かが変更内容と理由を把握したうえで承認する必要があります。

CIでスクリーンショットテストを実行する

スクリーンショットの比較は実行環境の影響を受けます。フォント、OS、ブラウザのバージョン、ハードウェア、headlessモードの違いでもピクセルは変わります。安定させるには、同じ環境で基準画像を作成して比較します。

実務では、次のような運用が一般的です。

  • CI、またはCIと一致するローカルコンテナで作った基準画像をコミットする
  • pull requestでスクリーンショット用プロジェクトを実行する
  • 差が出ることを前提にしない限り、macOSで作った基準画像をLinuxのCIで比較しない
  • Playwrightとブラウザのバイナリを計画的に更新する
  • 変更されたスナップショットを確認してから受け入れる

失敗の理由がわかりにくいときは、PlaywrightのHTMLレポートやtrace viewerを使います。スクリーンショットテストの失敗を判断するには、赤くなったビルドだけでなく、差分を確認できる情報が必要です。

通常のスクリーンショット自動化を使う場面

スクリーンショットテストは、自社で管理するUIの品質確認に使います。レビュー、報告、記録、コンテンツ制作のために画像を集める作業とは別です。

URLから画像ファイルを作りたいなら、Playwrightによる通常のスクリーンショット自動化を使います。

Playwright Testが不要で、Chrome中心の小さなスクリプトにしたいなら、Puppeteerによるスクリーンショット自動化が向いています。

テスト一式を保守せず、URL一覧をコードなしで撮影したいなら、ShotomaticのWebsite Captureを使えます。URLを追加し、撮影設定を調整し、結果を確認してからスクリーンショットを書き出します。人がレスポンシブ表示を確認する用途なら、この方法で十分な場合があります。合否判定まで自動化するなら、Playwright Testを使い続けてください。

よくある失敗

  • ページの広すぎる範囲をテストする: ページ全体の基準画像を作る前に、重要なセクションから始めます。
  • 変動するデータを撮影する: 毎回変わるコンテンツには、固定テストデータ、マスク、スタイルを使います。
  • 確認せずにスナップショットを更新する: 見た目の差分を確認してから基準画像を更新します。
  • ある環境で基準画像を作り、別の環境で比較する: 描画環境をそろえます。
  • ビジュアルテストを動作テストとして扱う: テキスト、role、ナビゲーション、操作は通常のアサーションでも確認します。

よくある質問

Playwrightでスクリーンショットテストはできますか?

はい。Playwright Testには、expect(page).toHaveScreenshot()expect(locator).toHaveScreenshot()によるスクリーンショットのアサーションが用意されています。

スクリーンショットテストと画像の保存は何が違いますか?

画像の保存はスクリーンショットファイルを作るだけです。スクリーンショットテストは新しい画像を承認済みの基準画像と比較し、差分が許容範囲を超えるとテストを失敗させます。

Playwrightの基準画像はどこに保存されますか?

初期設定では、テストファイル名に-snapshotsを付けたディレクトリに保存されます。Playwrightの設定にあるsnapshotPathTemplateで保存先を変更できます。

Playwrightの基準画像を更新するには?

見た目の変更が意図したものだと確認してから、--update-snapshotsを付けてPlaywright Testを実行します。

すべてのページにスクリーンショットテストを使うべきですか?

いいえ。重要で状態が安定したUIに絞って使います。動作は通常のアサーションで確認し、レイアウトの変化を検出したいページやコンポーネントに視覚的な基準画像を用意してください。

参考資料

上記の例は、現行の公式ドキュメントと照らし合わせています。

2026年版:Macで使えるTango代替ツール5選

Mac向けTango代替ツールを、ローカルガイド作成、オンラインWorkspace、デスクトップ撮影、アプリ内ガイダンス、動画、書き出しで比較します。

読了まで約7分
Macでデスクトップの作業手順を文書化する人

コードを書かずにWebサイトのスクリーンショットを自動化

Website Captureなら、URLリストをページごとの設定で撮影し、結果を確認して書き出せます。スクリプトの管理は不要です。

Playwrightでスクリーンショットテストを行う方法 | ブログ | Shotomatic