DELOGs
GitHub Actions ではじめる Playwright E2E CI

GitHub Actions ではじめる Playwright E2E CI

GitHub Actions で Playwright を動かし、結果をレポート & ブランチ保護まで設定

初回公開日

最終更新日

前回のおさらい
まだ読んでいない方は
はじめての Playwright ─ “録画” で体験する E2E テスト入門
でローカル録画 → 実行を体験してみてください。
本記事はその「続編」で、ローカルで動かしたテストを GitHub Actions に載せる のがゴールです。

0. この記事で得られるもの

💡 やること💪 得られるメリット
GitHub Actions で Playwright を自動実行push / PR ごとに “壊れていない” を機械が保証
HTML レポート をアーティファクト添付失敗したスクショや diff をチーム全員が確認
ブランチ保護ルールを設定テストが緑 ✓ でないと main にマージ不可 → 品質ゲート完成

1. 前提:ローカルで E2E テストが動く状態

  • Next.js + shadcn/ui のフォーム例を使っている(前回記事サンプル)
簡単なフォームサンプルをGitHubに用意してありますので、そちらを利用いただくとこの記事と同様の体験が可能です。
上記を利用する場合は下記を実行してください。
zsh
1# クローン生成(本記事用のディレクトリへ) 2git clone https://github.com/delogs-jp/playwright-e2e.git playwright-ci 3cd playwright-ci 4 5# 依存インストール(Playwright はまだ入っていない) 6npm install
お問い合わせフォーム(サンプル)

2. Playwrightとテストファイルの準備

この節ははじめての Playwright ─ “録画” で体験する E2E テスト入門 と重複する部分です。さらりと記述します。 今回はテストパターンは「スクリーンショット差分でレイアウト崩れを検知」と「正常パターンだけすばやくテスト」の2パターンを用意します。

Playwrightのインストール

zsh
1npm i -D @playwright/test 2npx playwright install # ブラウザバイナリを一括取得

スクリーンショット差分でレイアウト崩れを検知するテストファイルの作成

tests/contact-visual.spec.tsというファイルを下記内容で作成します。
ts : contact-visual.spec.ts
1import { test, expect } from "@playwright/test"; 2 3test("お問い合わせフォームのレイアウト", async ({ page }) => { 4 await page.goto("/"); // playwright.config.tsでBaseurlを指定するのでパスだけ指定 5 await page.setViewportSize({ width: 1280, height: 720 }); 6 7 await expect(page).toHaveScreenshot("contact-baseline.png", { 8 threshold: 0.01, // 許容差分 1% 9 }); 10});

フォームの正常パターンだけテストするテストファイルの作成

tests/contact-happy.spec.tsというファイルを下記内容で作成します。
ts : contact-happy.spec.ts
1import { test, expect } from "@playwright/test"; 2 3test("お問い合わせフォーム 正常送信", async ({ page }) => { 4 await page.goto("/"); // playwright.config.tsでBaseurlを指定するのでパスだけ指定 5 6 await page.getByLabel("お名前").fill("テスト太郎"); 7 await page.getByLabel("メールアドレス").fill("taro@example.com"); 8 await page.getByLabel("お問い合わせ内容").fill("Playwright の動作確認です。"); 9 10 await page.getByRole("button", { name: "選択してください" }).click(); 11 await page.getByRole("option", { name: "質問" }).click(); 12 13 await page.getByRole("button", { name: "送信" }).click(); 14 15 await expect(page).toHaveURL(/\/thanks/); 16 await expect( 17 page.getByRole("heading", { name: "送信ありがとうございました" }) 18 ).toBeVisible(); 19});

2. Playwright に “webServer” を設定

CI では 「サーバーを立てる → テスト → 自動終了」 が理想。
プロジェクト直下にplaywright.config.ts を作成して下記を記述します。
ts : playwright.config.ts
1import { defineConfig } from "@playwright/test"; 2import path from "path"; 3 4const PORT = 3010; // ローカルと CI で共通ポート 5 6export default defineConfig({ 7 testDir: "./tests", 8 retries: 1, 9 10 use: { 11 baseURL: `http://localhost:${PORT}`, // テストファイルで指定するのは面倒なので 12 }, 13 14// すべてのスナップショットに共通のテンプレート 15 snapshotPathTemplate: 16 "{testDir}/__screenshots__/{testFilePath}/{arg}{ext}", 17 18// スナップショットの差分を検知-テストファイル側の設定が優先されるが、この設定がデフォルトに 19// この設定がないと、完全一致しないとNGになってしまう 20expect: { 21 toHaveScreenshot: { 22 /* 1.5% まで許容(必要に応じて微調整) */ 23 maxDiffPixelRatio: 0.015, // 0.015 = 1.5 % 24 }, 25 }, 26 27 /* サーバーを自動起動 */ 28 webServer: { 29 command: `npm run dev -- -p ${PORT}`, // Next.js を 3010 で起動 30 port: PORT, 31 reuseExistingServer: !process.env.CI, 32 }, 33});
  • port … ローカルで複数のプロジェクトを立ち上げたときにポートが重複して、実行エラーになるのを避けるために使わなそうなポートを指定
  • baseURL … テストファイルで指定するのは面倒なのでここで指定。useブロックで指定
  • command … 開発ビルドでも本番ビルドでも OK
  • reuseExistingServer … CI 上では常に fresh、ローカルは再利用で時短

3. GitHub Actions ワークフローを作成

プロジェクト直下に
text
1.github/ 2└─ workflows/ 3 └─ playwright.yml
.github/workflows/playwright.yml

playwright.yml(最小構成+レポート出力)

yml : playwright.yml
1name: E2E (Playwright) 2 3on: [push, pull_request] 4 5jobs: 6 e2e: 7 runs-on: ubuntu-latest 8 9 steps: 10 # 1) ソース取得 11 - uses: actions/checkout@v4 12 13 # 2) Node 環境 14 - uses: actions/setup-node@v4 15 with: 16 node-version: 22.17.0 17 18 # 3) 依存をインストール(Playwright の JS 本体もここで入る) 19 - run: npm ci 20 21 # 4) Playwright ブラウザ & 依存ライブラリをインストール 22 - name: Install Playwright browsers 23 run: npx playwright install --with-deps 24 25 # 5) TypeScript 型チェック 26 - run: npx tsc --noEmit 27 28 # 6) Playwright テスト(HTML レポート) 29 - run: npx playwright test --reporter=html 30 31 # 7) レポートをアーティファクト化(失敗しても必ず実行) 32 - uses: actions/upload-artifact@v4 33 if: always() # ← 失敗しても必ず実行 34 with: 35 name: playwright-report # 名前は自由(日本語も可) 36 path: playwright-report # フォルダ or ファイルを指定 37 retention-days: 3 # 保存日数(最大 90 日) 38 39 # 8) Next.js 本番ビルド(任意だが品質ゲートに有益) 40 - run: npm run build
補足:
ステップ役割
npx playwright install --with-depsPlaywright ブラウザ & 依存ライブラリをインストール
--reporter=html失敗スクショ & diff が HTML で閲覧可能
アーティファクト失敗調査・デザイナー共有に便利。期限は retention-days で調整

アーティファクトとは?

これは今回はじめて出てきた言葉です。これは、CI の実行が終わったあとにも“手元に残しておきたいファイル” をGitHub が一時的に保管してくれる仕組み です。
  • GitHub Actions の “アーティファクト” に関する主な制限と動き
項目仕様詳細・補足
アップロードできるサイズ1アーティファクト最大 ≈ 2 GB
1ワークフロー実行あたり総量 10 GB
これは actions/upload-artifact が内部で 2 GB を上限にチャンク転送しているためです(公式 README より)。巨大ファイルは分割か圧縮を推奨します。
リポジトリ/アカウントごとのストレージ枠プライベート・リポジトリはプラン別枠に加算される
例:GitHub Free500 MBTeam2 GB など
パブリック・リポジトリは課金対象外(実質無制限)。枠を超えると 新しいアップロードが失敗 し、枠を空けるか支払い上限を上げるまで保存できません。
保持期間 (retention)デフォルト 90 日
公開Repo:1-90 日
非公開Repo:1-400 日
upload-artifactretention-days 入力や、リポジトリ/組織設定で変更可能。
自動削除タイミング期間を過ぎたアーティファクトは自動パージされる削除・期限切れによる空き容量反映は 6〜12 時間ごと に更新
古いものから勝手に消えるか?いいえ(キャッシュとは挙動が違う)保存枠に上限があるのは 総量。超過すると“最新アップロードが失敗”するだけで、古いアーティファクトは手動または retention 期限で消さない限り残ります。
対して actions/cache は総量 10 GB を超えると 最終アクセスが古い順 に自動破棄される
古いものから勝手に消えるわけではないので、retention-daysでプロジェクトに合わせた適切な期間を指定する必要があります。容量を超えるとエラーになってテスト実行ができなくなってしまいます。

4. レイアウト崩れを検知用に一度テスト実行

レイアウト崩れを検知するには、ベースラインとなるキャプチャーが必要になります。これは一度ローカルでテスト実行することでキャプチャーがtests/配下に作成されるので、それを一緒にPushすることで、Git Actions でnpx playwright test --reporter=htmlを実行するだけで差分チェックが可能になります。
zsh
1npx playwright test tests/contact-visual.spec.ts --reporter=html --update-snapshots
ついでに、フォームの正常終了側もあわせてテストして、テスト設定に不具合がないかチェックしておきます。
zsh
1npx playwright test --reporter=html
上記のように(yamlファイルに記載したコマンドですが)テストファイルを指定しないとtests/ 配下のファイルをすべてテストしてくれます。

5. Push → Actions が走るか確認

GithubのリポジトリにPushします。下記は当サイトの環境にPushする例ですが、接続設定部分については皆さんの環境にあわせて変更してください。
zsh
1# ご自分の環境に合わせてGit Hubに接続 2git remote set-url origin git@github-delogs:delogs-jp/playwright-ci.git 3 4# 全てステージしてコミット 5git add . 6git commit -m "ci: Add Playwright E2E workflow" 7 8git push -u origin main
  1. Actions タブ に “E2E (Playwright)” が生成 → ジョブ進行中
  2. 数分後に 緑 ✓ なら成功
  3. playwright-report アーティファクトをダウンロード → index.html を開くとローカルと同じ UI
Actions 緑チェック
  • レポートのダウンロードの場所が少しわかりづらいのですが、上図の該当ワークフローをクリックして詳細を開き、詳細画面の下部にあります。下図の赤丸の場所です。
Actions のアーティファクト欄

6. ブランチ保護で「緑 ✓ 以外はマージ不可」に

過去記事(GitHub設定編:最小構成 CI)と同じ手順ですが、
対象リポジトリの Settings → Branchesを開き 「Add classic branch protection rule」をクリック して下図のようにします。
ブランチの保護設定画面
  • Branch name pattern: main
  • Require a pull request before mergingにチェック(任意)
  • Require status checks to pass before mergingにチェック
  • Require status checks…: e2e を選択
  • 下部のCreateボタンをクリック
これで テストが赤 × の PR はマージできない 安全ゲートが完成。

7. 失敗を体験 → 修正フロー

はじめての Playwright ─ “録画” で体験する E2E テスト入門 と同様にレイアウトのチェックでエラーを起こしてしっかり動くかを検証してみます。
過去記事(GitHub設定編:最小構成 CI)と同じ手順なので、項目だけ記述しておきます。
  • ブランチを作成 git switch -c feature/error-sample
  • フォームのボタン className="my-4"my-[999px] に変えて、Push git push -u origin feature/error-sample
  • Actions が赤 × → 差分スクショ付きレポート
  • 修正コミット → Push → 緑 ✓ → PR → マージ
チームメンバー全員が「壊したら赤 ×、直したら緑 ✓」を体験できます。

参考リンク

この記事の執筆・編集担当
DE

松本 孝太郎

DELOGs編集部/中年新米プログラマー

ここ数年はReact&MUIのフロントエンドエンジニアって感じでしたが、Next.jsを学んで少しずつできることが広がりつつあります。その実践記録をできるだけ共有していければと思っています。