QR Send

スマホとPCのChrome間で、URLやテキストをQRコード1回のペアリングで送り合える自作Chrome拡張。アカウント不要・無料。

使ってみる →

【入門】PlaywrightをGitHub Actionsで自動実行する:ワークフローYAML・ブラウザキャッシュ・trace保存まで

Selenium・自動化

手元で動いたので満足していたら「CIに組み込んでください」と言われた

Playwrightのテストを手元で書いて、緑になるところまでは確認できた。満足していたら「これ、CIで毎回自動で回るようにしてもらえますか」と言われる。Playwrightを使い始めて最初にぶつかる壁がここです。

私も長年Selenium WebDriverを主戦場にしてきましたが、SeleniumからPlaywrightへ移行した記事で書いた通り、最近はほとんどPlaywrightです。ローカルで動くテストをGitHub Actionsに載せる作業自体は、そこまで難しくありません。ただし1年目のうちは「あるある」な詰まりどころが3つあります。この記事では、その3つを潰しながら最小構成のワークフローを組み立てます。

まず動かない。ブラウザが入っていないから

ローカルではnpx playwright testが普通に動くので、CIでも同じコマンドを置くだけで動くと思いますよね。ですが、いきなりワークフローにnpx playwright testだけを書くと、たいてい失敗します。

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright test

ChromiumもFirefoxもWebKitもGitHub Actionsのランナーには最初から入っていないので、ブラウザが見つからずエラーになります。ローカルでは一度npx playwright installを実行済みだったので忘れがちですが、CIのランナーは毎回まっさらな環境です。

公式Dockerイメージか、install –with-depsか

ブラウザを用意する方法は大きく2つです。ひとつはnpx playwright install --with-depsをステップに足す方法です。

      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test

--with-depsを付けると、ブラウザ本体だけでなくUbuntuランナー上で動かすのに必要なOSのライブラリ一式もまとめて入れてくれます。付け忘れると、ブラウザは入っているのに起動できないという別のエラーで詰まるので注意です。

もうひとつは、Microsoft公式が配布しているmcr.microsoft.com/playwrightイメージをコンテナとして使う方法です。

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/playwright:v1.55.0-noble # 執筆時点の最新系列。実際に使うタグは都度確認してください
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx playwright test

このイメージにはブラウザとOS依存パッケージがあらかじめ全部入っているので、インストールのステップ自体が不要です。ただしイメージのタグ(v1.55.0-nobleの部分)とpackage.json@playwright/testのバージョンを一致させる必要があります。ずれるとブラウザと噛み合わず謎のエラーが出るので、迷ったら--with-deps方式から試すのがおすすめです。

ブラウザバイナリをキャッシュする定石と、その罠

ではキャッシュでインストール時間を短縮しましょう。ブラウザのダウンロードは地味に時間がかかるので、毎回律儀にダウンロードするのはもったいない気がしますよね。actions/cacheでブラウザの保存先をキャッシュする定石は次の形です。

      - name: Cache playwright binaries
        uses: actions/cache@v4
        with:
          path: ~/.cache/ms-playwright
          key: playwright-browsers-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
      - run: npm ci
      - run: npx playwright install --with-deps

キーの設計を間違えると、古いブラウザを引き当てる罠にはまります。package-lock.jsonを含めずOS名だけをキーにしていると、Playwrightのバージョンを上げても古いキャッシュがヒットし続け、テストランナーが期待するリビジョンとキャッシュ済みのリビジョンがずれます。結果は「入っているはずなのに起動できない」というさっきの罠と同じ症状です。キーには必ずPlaywrightのバージョン(またはpackage-lock.jsonのハッシュ)を紐づけてください。

正直に書いておくと、Playwright公式は近年「ブラウザバイナリのキャッシュはあまり推奨しない」という立場です。キャッシュの復元時間と素直にダウンロードする時間があまり変わらないうえ、OS依存パッケージのインストールはそもそもキャッシュできないからです。私も試しましたが、体感できるほどの短縮にはならないプロジェクトもありました。

落ちた時にログだけ見ても原因がわからない

ワークフローが動くようになると、次は「CIでだけテストが落ちる。でもログを見ても原因がわからない」という壁です。ローカルなら画面を見ながらデバッグできますが、CIに画面はありません。ログに出るのはエラーメッセージくらいで、ページがどんな状態だったのかは分かりません。

playwright.config.tstracereporterを設定しておくと、失敗したテストの実行過程を記録として残せます。

// playwright.config.ts
export default defineConfig({
  reporter: [['html']],
  use: {
    trace: 'on-first-retry',
  },
});

これで、失敗して自動リトライされた1回目にtraceファイルが保存されます。あとはこのtraceとHTMLレポートをactions/upload-artifactで成果物として残すだけです。

      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: ${{ failure() }}
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 7

if: ${{ failure() }}を付けているので、失敗した時だけレポート一式をアップロードします。毎回成功時もアップロードしてストレージを圧迫する必要はありません。

ダウンロードしたレポートをローカルで開く

GitHub ActionsのUI上でArtifactsからzipをダウンロードし、展開してローカルで開きましょう。

npx playwright show-report playwright-report

これでローカルのshow-reportと同じ画面です。失敗したテストからtraceも開けます。以前traceをCLIだけで開く記事の通り、CIのtraceも同じコマンドで開けます。

npx playwright show-trace test-results/xxxx/trace.zip

trace viewerではクリックした瞬間のDOMのスナップショットやネットワーク通信まで時系列で追えます。ログだけでは分からなかったものが画面の状態として見えるので、ここまでやって初めて原因調査がまともにできます。

あわせて覚えておきたいCLIオプション

ワークフローYAML・キャッシュ・失敗時の証跡保存という3点は揃いました。CIで落ちたテストを手元でどう再現するかでも詰まりやすいので、CLIオプションを一通りまとめた記事も合わせて読んでおくとスムーズです。私自身、最初にCIへ組み込んだ時は「ブラウザが入っていない」「キャッシュが古いブラウザを引く」「落ちてもログしか残らない」の3つを順番に踏みました。この順番で潰せば1年目でも迷わないはずです。

まとめ

PlaywrightをGitHub Actionsで自動実行する時は、まずブラウザを用意する方法(--with-depsか公式イメージか)を決め、キャッシュを入れるならバージョンに紐づいたキー設計にすること。そして失敗した時のためにtraceとHTMLレポートをartifactとして必ず残しておくこと。この3点を押さえておけば、CIに載せる作業でつまずく箇所はかなり減らせます。

まずは--with-depsだけの最小構成から試してみてください。組んでみて別のエラーにぶつかった方は、ぜひコメントで教えてください。私も試行錯誤中です(正直、キャッシュの効果測定はまだ自分の中でも決着していません)。

コメント

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