GitHub Actions × PlaywrightでE2Eテストを自動化する方法|CI/CD設定をゼロから解説

テスト自動化

GitHub ActionsとPlaywrightを組み合わせることで、コードをプッシュするたびにE2Eテストが自動実行されるCI/CDパイプラインを、追加費用なしで構築できます。

📌 この記事はこんな方におすすめ

  • PlaywrightのE2EテストをCI/CDに組み込みたいQAエンジニア・開発者
  • GitHub Actionsを使ったことがなく、設定ファイルの書き方を一から学びたい方
  • プッシュのたびに自動テストが走る環境を手軽に作りたい方
  • テスト結果レポートをGitHub上で確認したい方

✅ この記事を読むと得られること

  • GitHub ActionsのYAML設定ファイルをゼロから書けるようになる
  • Playwright × pytestのテストをCI環境で自動実行できる
  • HTMLレポートをGitHub Actionsのアーティファクトとして保存・確認できる

👤 この記事を書いた人

QAエンジニアとして実務でSelenium・Playwright・pytestを活用したテスト自動化に従事。GitHub Actionsへの組み込みも実際のプロジェクトで経験しており、ハマりやすいポイントを含めて現場目線で解説します。実装コードはGitHubで公開中:github.com/YOSHITSUGU728/automated-testing-portfolio

📌 結論:この記事で作れるもの

  • 自動テスト実行:mainブランチへのプッシュ・PRで自動的にE2Eテストが走る
  • レポート保存:テスト結果HTMLをアーティファクトとしてGitHub上から確認できる
  • 無料で運用:GitHub Actionsはパブリックリポジトリ無制限・プライベートも月2,000分無料

ローカルでテストが通っても、チームの誰かがプッシュしたコードで壊れてしまうことはよくあります。CI/CDにE2Eテストを組み込むことで「誰がプッシュしても自動でテストが走り、失敗したら通知が来る」という仕組みを作れます。この記事ではGitHub Actions × Playwright × pytestの構成で、実際に動くCI/CDパイプラインをゼロから構築する手順を解説します。

CI/CDとGitHub Actionsの基本

CI(継続的インテグレーション)とは、コードのプッシュやPRをトリガーに、自動でビルド・テストを実行する仕組みです。GitHub ActionsはGitHubに組み込まれたCI/CDサービスで、リポジトリに .github/workflows/ フォルダを作ってYAMLファイルを置くだけで動きます。

項目内容
実行環境Ubuntu / Windows / macOS が選択可能
無料枠パブリックリポジトリ:無制限 プライベート:月2,000分
トリガーpush・pull_request・schedule・手動実行など
設定ファイル.github/workflows/*.yml
Playwright対応公式Dockerイメージあり・ヘッドレス実行に対応

① プロジェクト構成

今回使用するプロジェクトの構成です。

my_project/
├── .github/
│   └── workflows/
│       └── playwright.yml    # GitHub Actions設定ファイル
├── tests/
│   ├── conftest.py
│   └── test_saucedemo.py     # Playwrightテスト
├── requirements.txt          # 依存パッケージ一覧
└── pytest.ini                # pytest設定

② requirements.txt の準備

CI環境でインストールするパッケージを requirements.txt にまとめます。

pytest
pytest-playwright
pytest-html
playwright
💡 ポイント:バージョンを固定したい場合は pytest==7.4.0 のように書きます。CI環境でも同じバージョンが使われるため、ローカルと挙動が一致しやすくなります。playwrightpytest-playwright が依存として入れる場合もありますが、環境によっては入らないケースがあるため、明示的に記載しておくのが安全です。

③ テストコードの確認

CI上で実行するPlaywrightテストのサンプルです。SauceDemoのログインをテストします。

# tests/test_saucedemo.py
from playwright.sync_api import Page

def test_ログイン_正常系(page: Page):
    page.goto("https://www.saucedemo.com/")
    page.fill("#user-name", "standard_user")
    page.fill("#password", "secret_sauce")
    page.click("#login-button")
    assert page.url.endswith("/inventory.html")

def test_ログイン_パスワード誤り(page: Page):
    page.goto("https://www.saucedemo.com/")
    page.fill("#user-name", "standard_user")
    page.fill("#password", "wrong_password")
    page.click("#login-button")
    error_msg = page.locator(".error-message-container").text_content()
    assert "Epic sadface" in error_msg
# pytest.ini
[pytest]
testpaths = tests
addopts = -v --tb=short --html=reports/report.html --self-contained-html

④ GitHub Actions YAMLファイルの作成(メイン)

これが今回の核心です。.github/workflows/playwright.yml を作成します。

# .github/workflows/playwright.yml

name: Playwright E2E Tests

# ① トリガー設定:mainへのpush・PRで自動実行
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    # ② 実行環境:Ubuntu最新版
    runs-on: ubuntu-latest

    steps:
      # ③ リポジトリのコードをチェックアウト
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v4

      # ④ Pythonのセットアップ
      - name: Python 3.11 をセットアップ
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      # ⑤ 依存パッケージのインストール
      - name: 依存パッケージをインストール
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      # ⑥ Playwrightブラウザのインストール
      - name: Playwrightブラウザをインストール
        run: playwright install chromium --with-deps

      # ⑦ reportsフォルダを作成(ないとアーティファクト保存が失敗する)
      - name: reportsフォルダを作成
        run: mkdir -p reports

      # ⑧ テスト実行
      - name: E2Eテストを実行
        run: pytest

      # ⑨ テスト結果レポートをアーティファクトとして保存
      - name: レポートをアップロード
        uses: actions/upload-artifact@v4
        if: always()    # テスト失敗時も必ず実行
        with:
          name: playwright-report
          path: reports/
          retention-days: 30

各ステップの意味をまとめます:

ステップ何をしているか
① トリガーmainへのpushまたはPR作成時に自動実行
② runs-onUbuntuの最新版を実行環境として使用
③ checkoutGitHubのコードをCI環境にクローン
④ setup-pythonPython 3.11をCI環境にインストール
⑤ pip installpipをアップグレード後、requirements.txtのパッケージをインストール
⑥ playwright installChromiumブラウザと依存ライブラリをインストール
⑦ mkdir -p reportsレポート保存用フォルダを事前に作成(ないと保存ステップが失敗する)
⑧ pytestテストを実行(失敗時はジョブが失敗扱いになる)
⑨ upload-artifactHTMLレポートをGitHub上に30日間保存

⑤ 実行結果の確認方法

YAMLファイルをGitHubにプッシュすると、自動的にワークフローが起動します。確認手順は以下のとおりです。

手順操作
① Actionsタブを開くGitHubリポジトリの上部メニューから「Actions」をクリック
② ワークフローを選択「Playwright E2E Tests」を選択して実行履歴を確認
③ ログを確認各ステップをクリックすると実行ログが表示される
④ レポートをダウンロードページ下部の「Artifacts」から playwright-report をダウンロード

実行ログのサンプル

Run pytest
========================= test session starts ==========================
platform linux -- Python 3.11.0, pytest-7.4.0
collected 2 items

tests/test_saucedemo.py::test_ログイン_正常系      PASSED  [ 50%]
tests/test_saucedemo.py::test_ログイン_パスワード誤り  PASSED  [100%]

========================== 2 passed in 8.43s ===========================

⑥ 応用:スケジュール実行・複数ブラウザ対応

毎日深夜に自動実行する

プッシュ時だけでなく、定期的にテストを実行したい場合は schedule を追加します。

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: "0 0 * * *"   # 毎日UTC 0:00(日本時間 9:00)に実行

複数ブラウザで並列テスト

strategy: matrix を使うとChromium・Firefox・WebKitの3ブラウザでテストを並列実行できます。

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        browser: [chromium, firefox, webkit]

    steps:
      # ... 前のステップと同じ ...

      - name: Playwrightブラウザをインストール
        run: playwright install ${{ matrix.browser }} --with-deps

      - name: E2Eテストを実行(${{ matrix.browser }})
        run: pytest --browser ${{ matrix.browser }}

      - name: レポートをアップロード
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: report-${{ matrix.browser }}
          path: reports/
💡 実務Tip:3ブラウザ並列にすると実行時間はほぼ変わらずにブラウザカバレッジが3倍になります。ただし無料枠の消費も3倍になるので、mainブランチのみ3ブラウザ・PRはChromiumのみ、という使い分けが実務でよく採用されます。

FAQ

Q. GitHub Actionsは本当に無料で使えますか?

パブリックリポジトリは無制限で無料です。プライベートリポジトリは月2,000分の無料枠があります。Playwright × pytestのテストは1回あたり1〜3分程度が多いので、個人プロジェクトや小規模チームなら無料枠で十分なケースがほとんどです。

Q. テストが失敗したときに通知を受け取れますか?

はい。GitHubのアカウント設定で「Actions」の通知をオンにすると、ワークフローが失敗した際にメールが届きます。Slack通知を設定したい場合は slackapi/slack-github-action を使うとYAML数行で実現できます。

Q. ローカルで動いたテストがCIで失敗するのはなぜ?

最も多い原因は①環境差異(Pythonバージョン・OSの違い)、②ヘッドレスモードでの動作差異、③テスト対象サービスへのネットワーク接続失敗の3つです。--headedオプションなしで実行してみること、requirements.txtのバージョンを固定すること、が最初の対処になります。

Q. テスト対象がlocalhost(ローカルサーバー)の場合はどうすればいい?

GitHub Actionsのステップ内でサーバーを起動すれば対応できます。例えばPythonのFlaskアプリなら run: python app.py & でバックグラウンド起動し、その後 pytest を実行するステップを追加します。外部サービス(DB・APIサーバー)が必要な場合は services キーでDockerコンテナを起動することもできます。

⚠️ GitHub Actions × Playwrightでよくあるはまりポイント8選

CI環境特有のトラブルが多いのがGitHub Actions × Playwrightの組み合わせです。ローカルで動いたのにCIで失敗する……という経験をしないために、事前に把握しておきましょう。

playwright install を忘れてブラウザが見つからない

CI環境にはPlaywrightのブラウザが入っていません。pip install pytest-playwright でPythonパッケージをインストールしても、ブラウザ本体は別途 playwright install chromium --with-deps が必要です。--with-deps を忘れると Linux の依存ライブラリが不足してブラウザが起動しません。

if: always() を書かないとテスト失敗時にレポートが保存されない

アーティファクトのアップロードステップに if: always() を書かないと、テストが失敗した瞬間にジョブが中断してレポートが保存されません。失敗時こそレポートが必要なので、必ず書きましょう。

③ YAMLのインデントミスでワークフローが起動しない

GitHubのYAMLはインデントに非常に厳格です。スペース2つと4つの混在、タブ文字の混入などで「Invalid workflow file」エラーになります。yamllint.com でYAMLの文法チェックをしてからプッシュするのが確実です。

reports/ フォルダが存在しないとアーティファクト保存が失敗する

pytestの実行でテストが全件スキップされた場合など、reports/ フォルダが作られないことがあります。その場合、upload-artifact ステップも失敗します。回避策として、アップロード前に run: mkdir -p reports を追加するか、if-no-files-found: warn オプションをアーティファクト設定に追記しておきましょう。

⑤ ヘッドレスモードで要素が見つからない(ローカルは通るのにCIで失敗)

CI環境はデフォルトでヘッドレスモードで実行されます。ヘッドフルモードと比べてレンダリングのタイミングに差があり、page.locator()が要素を見つけられないことがあります。page.wait_for_selector()expect(locator).to_be_visible() を使って明示的な待機を追加することで解決できます。

⑥ matrix並列実行でアーティファクト名が衝突してレポートが上書きされる

複数ブラウザの並列テストで全て同じ name: playwright-report にすると、後から完了したジョブが前のレポートを上書きしてしまいます。name: report-${{ matrix.browser }} のようにブラウザ名を含めて一意にしましょう。

actions/checkout@v4 などのバージョンを省略すると予告なく動作が変わる

uses: actions/checkout@main のように最新ブランチを指定すると、アクションが更新されたタイミングで突然ワークフローが壊れることがあります。@v4 のようにメジャーバージョンを固定しておくのが安全です。

⑧ pipキャッシュが残って ModuleNotFoundError が解消しない

actions/setup-pythoncache: "pip" を設定している場合、requirements.txt を更新してもキャッシュが残って古い状態のまま実行されることがあります。「ローカルでは動くのにCIだけ ModuleNotFoundError が出る」という場合はキャッシュが原因のことが多いです。

# キャッシュを有効にする場合(requirements.txtのハッシュが変わると自動で更新される)
- uses: actions/setup-python@v5
  with:
    python-version: "3.11"
    cache: "pip"          # requirements.txt が変わると自動でキャッシュを破棄

# キャッシュを無効にしてクリーンインストールする場合
- uses: actions/setup-python@v5
  with:
    python-version: "3.11"
    # cache を書かなければキャッシュなし(毎回クリーンインストール)

原因不明のModuleNotFoundErrorに遭遇したら、GitHubの「Actions → Caches」からキャッシュを手動削除して再実行するのが最速の解決策です。

📋 この記事のまとめ

  • GitHub Actions.github/workflows/ にYAMLを置くだけで動くCI/CDサービスで、パブリックリポジトリは無料
  • playwright install chromium –with-deps はCIで必須・忘れると起動しない
  • if: always() をアーティファクト保存ステップに付けることで、失敗時もレポートを確認できる
  • schedule を追加すれば毎日定刻に自動テストを走らせてサービスの品質を継続監視できる
  • matrix で複数ブラウザの並列テストが簡単に実現でき、クロスブラウザの品質保証に効果的

CI/CDにE2Eテストを組み込むと「誰がプッシュしても品質が担保される」状態になります。最初はChromiumのみ・mainブランチのみのシンプルな構成から始めて、慣れてきたらスケジュール実行や複数ブラウザ対応に拡張していきましょう。

タイトルとURLをコピーしました