0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Azure DevOps の Pipeline で動かす cucumberからエラーログをとったメモ

Last updated at Posted at 2025-04-12

概要

Azure DevOpsのパイプラインの上でE2Eテストをしたかった。
前回、認証をパイプラインで動かすのに失敗したので、CI環境では認証はスキップするつくりにした。
それでもなかなか動かなかったので、試行錯誤した記録を残す。

この時点のソース

ソースコード

packages/bdd-e2e-test/azure-pipeline.yml
trigger:
  branches:
    include:
      - id/75/bddOnPipeline

jobs:
  - job: bdd_test
    displayName: 'Run BDD E2E tests'
    pool:
      vmImage: 'ubuntu-latest'

    services:
      postgres:
        image: postgres:17.4-alpine
        ports:
          - 5432:5432
        env:
          POSTGRES_USER: test_user
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: main
        options: >-
          --health-cmd="pg_isready"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=5

    steps:
      - checkout: self

      - task: UseNode@1
        inputs:
          version: '22.x'

      - script: |
          curl -fsSL https://bun.sh/install | bash
        displayName: 'Install Bun'

      - script: echo "##vso[task.setvariable variable=PATH]$(HOME)/.bun/bin:$(PATH)"
        displayName: 'Add Bun to PATH'

      - script: bun install
        displayName: 'Install Dependencies'

      - script: npx playwright install --with-deps chromium
        workingDirectory: apps/frontend
        displayName: 'download new browsers'

      - script: cp .dev.vars.ci .dev.vars
        workingDirectory: apps/backend
        displayName: 'Setting Backend env vars'

      - script: cp .env.sample .dev.local
        workingDirectory: apps/frontend
        displayName: 'Setting Frontend env vars'

      - script: |
          bun run dev > backend.log 2>&1 &
          echo $! > ../backend.pid
        workingDirectory: apps/backend
        displayName: 'Start Backend'

      # ホットリロードなど不要なので、bun run dev ではなく bun run preview を使う
      - script: |
          bun run preview:ci > frontend.log 2>&1 &
          echo $! > ../frontend.pid
        workingDirectory: apps/frontend
        displayName: 'Start Frontend'

      - script: |
          echo "Waiting for frontend server..."
          for i in {1..20}; do
            if curl -s http://localhost:5173 > /dev/null; then
              echo "Frontend server is up."
              break
            fi
            sleep 2
          done

          echo "Waiting for backend server..."
          for i in {1..20}; do
            if curl -s http://localhost:8787 > /dev/null; then
              echo "Backend server is up."
              break
            fi
            sleep 2
          done
        displayName: 'Wait for servers to start'

      - script: bun run migrate:azci
        workingDirectory: packages/database
        displayName: 'Migration RDB'

      - script: bun run bdd-test
        workingDirectory: packages/bdd-e2e-test
        displayName: 'Run E2E Tests'
        env:
          CI: true

      # 調査用にE2Eテストのスクリーンショットやcontentsを確認できるようにする
      - task: PublishBuildArtifacts@1
        condition: always()
        inputs:
          pathToPublish: 'packages/bdd-e2e-test/output'
          artifactName: 'e2e-output'
        displayName: 'Upload screenshots as artifacts'

      # 調査用にバックエンドのログを確認できるようにする
      - task: PublishBuildArtifacts@1
        condition: always()
        inputs:
          pathToPublish: 'apps/backend/backend.log'
          artifactName: 'backend-log'
        displayName: 'Upload screenshots as artifacts'

      - script: |
          kill $(cat backend.pid)
          kill $(cat frontend.pid)
        displayName: 'Cleanup Servers'
        workingDirectory: apps
        condition: always()

実行結果

image.png

調査記録

バックエンドのログ

PublishBuildArtifactsを使う。

      - script: |
+          bun run dev > backend.log 2>&1 &
          echo $! > ../backend.pid
        workingDirectory: apps/backend
        displayName: 'Start Backend'
      # 調査用にバックエンドのログを確認できるようにする
      - task: PublishBuildArtifacts@1
        condition: always()
        inputs:
+         pathToPublish: 'apps/backend/backend.log'
          artifactName: 'backend-log'
        displayName: 'Upload screenshots as artifacts

実行結果の
image.png

Publishをクリックすると

image.png

出力されたログを確認できる
image.png

フロントエンド

DEBUG=pw:api でデバッグログを確認できる

packages/bdd-e2e-test/package.json
    "bdd-test": "DEBUG=pw:api cucumber-js --config cucumber.mjs --exit"

ヘッドレスブラウザのログは下記のようにBeforeでイベントをひろう。

packages/bdd-e2e-test/e2e/step-definitions/scenario.steps.ts
Before(async function (this) {
  const browser = await chromium.launch({
    headless: process.env.CI === 'true',
  }); // headless: true にするとブラウザが表示されない
  const context = await browser.newContext();
  this.page = await context.newPage();

  // ヘッドレスブラウザ―のコンソール出力をキャッチする
  this.page.on('console', (msg: any) => {
    if (msg.type() === 'error') {
      console.error(`[Browser Console Error]: ${msg.text()}`);
    } else if (msg.type() === 'warning') {
      console.warn(`[Browser Console Warning]: ${msg.text()}`);
    } else {
      console.log(`[Browser Console]: ${msg.text()}`);
    }
  });
  this.page.on('request', (request: any) =>
    console.log(`Request: ${request.method()} ${request.url()}`),
  );
  this.page.on('response', (response: any) => {
    console.log(`Response: ${response.status()} ${response.url()}`);
    if (response.status() >= 400) {
      console.error(`Error Response: ${response.status()} ${response.url()}`);
    }
  });
});

スクリーンショットを取ったり、page.contentでHTMLを出力したりで調査できる。

packages/bdd-e2e-test/e2e/step-definitions/scenario.steps.ts
When(
  'ユーザーが「 {string} 」リンクをクリックする',
  async function (this, text) {
    const { page } = this;

    await page.screenshot({
      path: 'output/screenshots/debug.png',
      fullPage: true,
    });
    const content = await page.content();
    fs.writeFileSync('output/debug.html', content);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(500);
    await page.screenshot({
      path: 'output/screenshots/after_networkidle.png',
      fullPage: true,
    });
    fs.writeFileSync('output/after_networkidle.html', await page.content());

    await page.waitForSelector(`a:has-text("${text}")`);
    await page.getByRole('link', { name: text }).nth(0).click();
  },
);

参考

Greenプルリク

余談

エラー検証中に下記のエラーがなかなか難しかった。
dbの接続を使いまわしていたら出たエラーだった。修正こみ

Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. This is a limitation of Cloudflare Workers which allows us to improve overall performance. (I/O type: Writable)

追記: Neon Proxyのログ

      - script: |
          # ログファイルパスを定義
          LOG_DIR=$(pwd)/neon-proxy-logs
          mkdir -p $LOG_DIR

          echo "Starting Neon Proxy..."
          docker run -d --name neon-proxy \
            -e PG_CONNECTION_STRING=postgres://postgres:postgres@host.docker.internal:5432/main \
            -p 4444:4444 \
            --add-host=host.docker.internal:host-gateway \
            ghcr.io/timowilhelm/local-neon-http-proxy:main

          # バックグラウンドでログ収集を開始
          docker logs -f neon-proxy > $LOG_DIR/neon-proxy.log 2>&1 &
          LOGGER_PID=$!
          echo $LOGGER_PID > $LOG_DIR/neon.pid

          # Proxy が立ち上がるまで待機
          echo "Waiting for Neon Proxy..."
          for i in {1..20}; do
            if curl -s http://db.localtest.me:4444/sql &>/dev/null; then
              echo "Neon Proxy is ready"
              break
            fi
            sleep 2
          done
        displayName: 'Start Neon Proxy'
      # Neon Proxyログをアーティファクトとして保存するためのタスク
      - task: PublishBuildArtifacts@1
        condition: always()
        inputs:
          pathToPublish: 'neon-proxy-logs'
          artifactName: 'neon-proxy-logs'
        displayName: 'Upload Neon Proxy logs as artifacts'

      - script: kill $(cat neon.pid)
        displayName: 'Cleanup Neon Proxy logs'
        workingDirectory: neon-proxy-logs
        condition: always()

ソースコード

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?