Playwright 第13章:CI/CD 集成

将 Playwright 测试集成到 CI/CD 流水线中可以实现自动化测试的持续运行。本章介绍 GitHub Actions 配置、Docker 运行、测试分片以及报告上传等 CI/CD 最佳实践。

GitHub Actions 配置

基础工作流配置

# .github/workflows/playwright.yml
name: Playwright Tests

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 6 * * *'  # 每天 6:00 运行

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - uses: actions/setup-node@v4
      with:
        node-version: 20
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Install Playwright Browsers
      run: npx playwright install --with-deps

    - name: Run Playwright tests
      run: npx playwright test

    - uses: actions/upload-artifact@v4
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

多浏览器并行测试

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        browser: [chromium, firefox, webkit]
        shardIndex: [1, 2, 3]
        shardTotal: [3]

    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: 20
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Install Playwright
      run: npx playwright install --with-deps

    - name: Run tests
      run: |
        npx playwright test \
          --project=${{ matrix.browser }} \
          --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
      env:
        CI: true

    - name: Upload report
      uses: actions/upload-artifact@v4
      if: always()
      with:
        name: report-${{ matrix.browser }}-shard-${{ matrix.shardIndex }}
        path: playwright-report/
        retention-days: 7

注意:GitHub Actions 中的 ${{ }} 是 GitHub Actions 的表达式语法,在 YAML 文件中按原样编写即可。但如果在 TypeScript 模板字符串中嵌入 YAML 示例,需要确保不冲突。

合并分片报告

jobs:
  merge-reports:
    if: always()
    needs: [test]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: 20
        cache: 'npm'

    - name: Download all artifacts
      uses: actions/download-artifact@v4

    - name: Install dependencies
      run: npm ci

    - name: Merge reports
      run: npx playwright merge-reports --reporter html ./report-*/

    - name: Upload merged report
      uses: actions/upload-artifact@v4
      with:
        name: merged-report
        path: playwright-report/
        retention-days: 30

报告部署到 GitHub Pages

- name: Deploy report to GitHub Pages
  if: always()
  uses: peaceiris/actions-gh-pages@v3
  with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: ./playwright-report
    destination_dir: test-reports
    keep_files: true

Docker 运行

Playwright Docker 镜像

Playwright 官方提供预装了浏览器和系统依赖的 Docker 镜像:

# Dockerfile
FROM mcr.microsoft.com/playwright:v1.45.0-focal

WORKDIR /app

# 复制依赖文件
COPY package*.json ./
RUN npm ci

# 复制源码
COPY . .

# 运行测试
CMD ["npx", "playwright", "test"]

Docker Compose 配置

# docker-compose.yml
version: '3.8'
services:
  playwright:
    build: .
    environment:
      - CI=true
      - BASE_URL=http://webapp:3000
    volumes:
      - ./playwright-report:/app/playwright-report
      - ./test-results:/app/test-results
    depends_on:
      - webapp

  webapp:
    build: ./webapp
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=test

在 Docker 中运行测试

# 构建镜像
docker build -t playwright-tests .

# 运行测试
docker run --rm \
  -v $(pwd)/playwright-report:/app/playwright-report \
  -v $(pwd)/test-results:/app/test-results \
  playwright-tests

# 使用 Docker Compose
docker compose up --abort-on-container-exit

分片测试(Shard)

分片工作原理

分片将测试集划分为多个片段,每个片段在独立的 worker 上并行执行:

# 将测试分为 4 片,同时在 4 个 runner 上执行
npx playwright test --shard=1/4
npx playwright test --shard=2/4
npx playwright test --shard=3/4
npx playwright test --shard=4/4

# 合并结果
npx playwright merge-reports --reporter html ./shard-results/

分片配置

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  // 开启分片报告合并
  reporter: process.env.CI ? [
    ['blob', { outputDir: './blob-report' }],
    ['html', { outputFolder: './playwright-report' }],
  ] : [
    ['html'],
    ['list'],
  ],
});

CI 中的分片策略

jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
    - name: Run tests
      run: npx playwright test --shard=${{ matrix.shard }}/4

  report:
    needs: [test]
    steps:
    - name: Merge blob reports
      run: npx playwright merge-reports --reporter html ./blob-report/

无头模式配置

不同环境下的无头配置

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    // CI 中使用无头模式
    headless: process.env.CI ? true : false,

    // Linux 环境需要额外参数
    launchOptions: process.platform === 'linux' ? {
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-gpu',
      ],
    } : {},
  },
});

视频和截图记录

export default defineConfig({
  use: {
    // CI 中记录失败截图
    screenshot: process.env.CI ? 'only-on-failure' : 'off',

    // CI 中记录失败视频
    video: process.env.CI ? 'retain-on-failure' : 'off',

    // CI 中记录 Trace
    trace: process.env.CI ? 'on-first-retry' : 'off',
  },
});

性能优化

CI 加速策略

// playwright.config.ts
export default defineConfig({
  // 仅在 CI 中使用重试
  retries: process.env.CI ? 2 : 0,

  // CI 中限制并行数
  workers: process.env.CI ? 4 : undefined,

  // 全局超时
  timeout: process.env.CI ? 60000 : 30000,
});

缓存策略

- name: Cache Playwright browsers
  uses: actions/cache@v3
  with:
    path: ~/.cache/ms-playwright
    key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-playwright-

其他 CI 平台配置

GitLab CI

# .gitlab-ci.yml
stages:
  - test

playwright:
  stage: test
  image: mcr.microsoft.com/playwright:v1.45.0-focal
  script:
    - npm ci
    - npx playwright test
  artifacts:
    when: always
    paths:
      - playwright-report/
    expire_in: 30 days

Jenkins Pipeline

// Jenkinsfile
pipeline {
    agent {
        docker { image 'mcr.microsoft.com/playwright:v1.45.0-focal' }
    }
    stages {
        stage('Install') {
            steps {
                sh 'npm ci'
            }
        }
        stage('Test') {
            steps {
                sh 'npx playwright test'
            }
            post {
                always {
                    archiveArtifacts artifacts: 'playwright-report/**', allowEmptyArchive: true
                }
            }
        }
    }
}

总结

CI/CD 集成是 Playwright 测试自动化的关键环节。GitHub Actions 提供最便捷的集成方式,Docker 确保环境一致性,分片策略实现高效并行执行。建议在 CI 中开启视频和截图记录便于问题排查,合理设置重试策略平衡稳定性和耗时。报告上传和部署为团队提供可视化的测试结果,是持续改进测试质量的重要依据。