はじめに
Next.js と Rails を使ってオリジナルの Web アプリを開発しています。
Playwright を導入し E2E テストの実装は問題なくできましたが、その後 CI でのテストの自動化がうまくいかず数日ハマってしまいました。今回の記事ではその原因と結果についてまとめています。
Playwright 導入については以下記事にまとめています。
CI 環境構築
ローカル環境下でパスした E2E テストの自動化に取り組みました。
GitHub Actions に yml ファイルを用意し自動化のためのワークフローを記述しました。
name: "Frontend E2E Test" on: push: branches: ["main"] pull_request: branches: ["main"] jobs: e2e-test: runs-on: ubuntu-latest services: postgres: image: postgres:14.8 ports: - "5432:5432" env: POSTGRES_DB: rails_test POSTGRES_USER: rails POSTGRES_PASSWORD: password env: RAILS_ENV: test DATABASE_URL: "postgres://rails:password@localhost:5432/rails_test" steps: - name: Checkout uses: actions/checkout@v3 - name: Install Ruby and gems uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 with: ruby-version: "3.2.1" bundler-cache: true - name: Install libvips run: sudo apt install -y libvips working-directory: ./backend - name: Install dependencies run: | cd backend bundle install working-directory: ./backend - name: Set up database schema and Start Rails server run: | bundle exec rails db:schema:load bundle exec rails db:reset RAILS_ENV=test bundle exec rails s & sleep 30 working-directory: ./backend - name: Setup Node.js 18.x uses: actions/setup-node@v3 with: node-version: 18.x - name: Install dependencies run: npm ci working-directory: ./frontend - name: Install Playwright Browsers run: npx playwright install --with-deps working-directory: ./frontend - name: Start Next.js server run: | npm run dev & sleep 30 working-directory: ./frontend - name: Run Playwright tests run: npx playwright test working-directory: ./frontend/playwright
しかし、エラーが発生しテストが回りません。
Error occurred during API request: AxiosError: connect ECONNREFUSED ::1:3000
原因と結論
今回発生したエラーの原因、そして結論を説明します。
今回エラーが発生している箇所は、Google ログイン認証のステップであることがわかりました。
テスト用に準備した Google アカウントの Email を利用しログインを実行する際、Google 側の bot 対策に引っかかり Google ログイン認証を通過できない状況です。ローカル環境では下記エラーは起きません。しかし、GitHub Actions CI 環境下においてはエラーが発生する状況です。
bot と疑われログインが拒否された時にブラウザに表示されるエラー内容:
テスト用アカウントに届いた Google からの通知内容:
対応として、 bot と認定されないように Google 認証を行う方法、また Google 認証ログイン自体をモック化し対応する方法も検討しましたが、どちらも有効な手立てが見つかりませんでした。
そのため、CI 環境下での E2E テストは断念する結論に至りました。
E2E テストは、ローカル環境下では問題なくパスできるため、動作確認は担保されていると判断したためです。
デバッグ
結果としては、E2E テストを CI 環境下では実施しない判断となりましたが、「CI 環境構築において Playwright を使った E2E テスト」の実装に伴って取り組んだ内容を記録として残します。
環境変数の管理
next サーバーで使用する環境変数が正しく設定ができていなかったため見直しました。
// .github/workflows/frontend-test.yml - name: Start Next.js server run: | npm run dev & env: GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }} GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }} NEXTAUTH_URL: ${{ secrets.NEXTAUTH_URL }} NEXTAUTH_URL_INTERNAL: ${{ secrets.NEXTAUTH_URL_INTERNAL }} NEXT_PUBLIC_GEOCODING_API_KEY: ${{ secrets.NEXT_PUBLIC_GEOCODING_API_KEY }} NEXT_PUBLIC_GOOGLE_MAPS_API_KEY: ${{ secrets.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY }} NEXT_PUBLIC_RAILS_API_URL: ${{ secrets.NEXT_PUBLIC_RAILS_API_URL }} NEXT_SECRET: ${{ secrets.NEXT_SECRET }} RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} working-directory: ./frontend
環境変数は取得できているか?
環境変数にちゃんと欲しい値が渡っているか確認しました。
console.log で確認する例:
// frontend/playwright/global-setup.ts import { userEmail, userPassword, baseURL } from "playwright/config/index"; console.log("========================================================"); console.log(userEmail); console.log(userPassword); console.log(baseURL); console.log("========================================================");
ひとつ注意点ですが、ローカルではちゃんと値の表示は確認できますが、GitHub Actions の secrets に保存した値は console に出力したときに、***
とマスクされて出力されます。GitHub 上の仕様かと思われます。
Run npx playwright test ======================================================== *** *** *** ========================================================
デバッグ用で撮影したスクショを GitHub に保存する設定
ローカル環境下においてはスクショを保存し確認できていたのですが、GitHub 上で確認ができておらずデバッグを困難にしていました。
下記のプログラムで GitHub 上でも確認が可能になります。
参考: ワークフロー データを成果物として保存する - GitHub Docs
// .github/workflows/frontend-test.yml - name: Archive screenshots uses: actions/upload-artifact@v3 with: name: screenshots path: ./frontend/playwright/screenshots if: always()
全画面をスクショする場合、以下を任意の箇所へ配置しておきます。
await page.screenshot({ path: "playwright/screenshots/error.png", fullPage: true, });
GitHub 上で確認する時:
上記のif: always()
ですが、他のジョブが成功したかに関わらず、完了後に常に実行されます。