Roll With IT

tamakiのIT日記

CI 環境構築で直面した E2E テスト自動化の壁 〜Google の bot 対策による脅威のディフェンス力〜

はじめに

Next.js と Rails を使ってオリジナルの Web アプリを開発しています。

github.com

Playwright を導入し E2E テストの実装は問題なくできましたが、その後 CI でのテストの自動化がうまくいかず数日ハマってしまいました。今回の記事ではその原因と結果についてまとめています。

Playwright 導入については以下記事にまとめています。

shirotamaki.hatenablog.com

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 と疑われログインが拒否された時にブラウザに表示されるエラー内容:

error6_5_png.png

テスト用アカウントに届いた Google からの通知内容:

重大なセキュリティ通知_-_test_taro_outdoor_heart_sutra_gmail_com_-_Gmail.png

対応として、 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

Notification_Center.png

環境変数は取得できているか?

環境変数にちゃんと欲しい値が渡っているか確認しました。

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 上で確認する時:

Notification_Center.png

上記のif: always()ですが、他のジョブが成功したかに関わらず、完了後に常に実行されます。

参考: GitHub Actions のワークフロー構文 - GitHub Docs