分片

简介

默认情况下,Playwright 会【并行】运行测试文件,并尽量充分利用机器上的 CPU 核心。为了实现更大的并行性,您可以通过在多个机器上同时运行测试来进一步扩展 Playwright 的测试执行。这种操作模式被称为 “分片”(Sharding)。在 Playwright 中,分片意味着将测试拆分成更小的部分,称为 “分片”(shards)。每个分片就像一个可以独立运行的单独任务,目的是通过将测试拆分来加速测试执行时间。

当您对测试进行分片时,每个分片可以独立运行,充分利用可用的 CPU 核心。这通过并行执行任务来帮助加速测试过程。

在 CI 流水线中,每个分片可以作为一个独立的任务运行,利用 CI 流水线中的硬件资源(如 CPU 核心)加速测试运行。

在多个机器上分片测试

要对测试套件进行分片,可以在命令行中传递 --shard=x/y。例如,将测试套件分为四个分片,每个分片运行四分之一的测试:

npx playwright test --shard=1/4
npx playwright test --shard=2/4
npx playwright test --shard=3/4
npx playwright test --shard=4/4

现在,如果您在不同的任务中并行运行这些分片,您的测试套件将完成得更快,约为原来时间的四分之一。

请注意,Playwright 只能分片可以并行运行的测试。默认情况下,这意味着 Playwright 会对测试文件进行分片。更多细节请参考【并行性指南】。

分片的平衡

分片可以在两种粒度级别上进行,具体取决于您是否使用了 testProject.fullyParallel 选项。这个设置会影响测试在分片之间的平衡分布。

启用 fullyParallel 时的分片

fullyParallel: true 启用时,Playwright Test 会在多个分片之间并行运行单个测试,确保每个分片都能平均分配测试任务。这实现了测试级别的粒度,意味着每个分片将尽力平衡运行的测试数量。这是确保分片负载均衡的首选模式,因为 Playwright 可以根据测试总数优化分片执行。

未启用 fullyParallel 时的分片

如果没有启用 fullyParallel 设置,Playwright Test 默认使用文件级粒度,意味着整个测试文件会被分配到分片。在这种情况下,文件中测试的数量会显著影响分片的分配。如果您的测试文件大小不均衡(即某些文件的测试数量远多于其他文件),某些分片可能会运行更多的测试,而其他分片则可能会运行较少的测试,甚至没有。

关键要点:

  • 启用 fullyParallel: true:测试按单个测试级别进行分片,从而实现更均衡的分片执行。

  • 未启用 fullyParallel:测试按文件级别进行分片,因此为了平衡分片,建议保持测试文件的数量较少且大小均衡。

  • 为了在 CI 环境中确保最有效地使用分片,特别是在目标是均衡分配负载时,建议启用 fullyParallel: true。否则,您可能需要手动组织测试文件以避免不平衡。

合并来自多个分片的报告

在之前的例子中,每个测试分片都有自己的测试报告。如果您希望生成一个包含所有分片测试结果的合并报告,可以执行以下步骤。

首先,在 CI 运行时添加 blob 报告到配置文件中:

playwright.config.ts
export default defineConfig({
  testDir: './tests',
  reporter: process.env.CI ? 'blob' : 'html',
});

Blob 报告包含所有运行的测试信息、结果以及所有测试附件(例如跟踪和截图差异)。Blob 报告可以合并并转换为任何其他 Playwright 报告。默认情况下,Blob 报告会生成在 blob-report 目录中。

要合并多个分片的报告,可以将 Blob 报告文件放入同一个目录中,例如 all-blob-reports。Blob 报告名称包含分片编号,因此它们不会发生冲突。

然后,运行以下命令合并报告:

npx playwright merge-reports --reporter html ./all-blob-reports

这将生成一个标准的 HTML 报告,保存到 playwright-report 目录中。

GitHub Actions 示例

GitHub Actions 支持通过 jobs.<job_id>.strategy.matrix 选项将测试分片到多个任务中。matrix 选项将为每个可能的选项组合运行一个独立的任务。

以下示例展示了如何配置任务,在四台机器上并行运行测试,然后将报告合并为一个单一报告。在此示例中,别忘了将 reporter: process.env.CI ? 'blob' : 'html' 添加到 playwright.config.ts 配置文件中。

  1. 我们首先向任务配置添加一个 matrix 选项,其中包含 shardTotal: [4],即我们希望创建的分片总数,以及 shardIndex: [1, 2, 3, 4],即包含分片编号的数组。

  2. 然后,我们使用 --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} 选项运行 Playwright 测试命令,这将为每个分片运行一次测试。

  3. 最后,我们将 Blob 报告上传到 GitHub Actions 工件,这样报告可以供其他任务使用。

.github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  playwright-tests:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4]
        shardTotal: [4]
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: lts/*
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright browsers
      run: npx playwright install --with-deps

    - name: Run Playwright tests
      run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}

    - name: Upload blob report to GitHub Actions Artifacts
      if: ${{ !cancelled() }}
      uses: actions/upload-artifact@v4
      with:
        name: blob-report-${{ matrix.shardIndex }}
        path: blob-report
        retention-days: 1

所有分片完成后,您可以运行一个独立的任务,合并报告并生成合并后的 HTML 报告。为了确保执行顺序,我们通过添加 needs: [playwright-tests] 让 merge-reports 任务依赖于 playwright-tests。

.github/workflows/playwright.yml
jobs:
...
  merge-reports:
    # Merge reports after playwright-tests, even if some shards have failed
    if: ${{ !cancelled() }}
    needs: [playwright-tests]

    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: lts/*
    - name: Install dependencies
      run: npm ci

    - name: Download blob reports from GitHub Actions Artifacts
      uses: actions/download-artifact@v4
      with:
        path: all-blob-reports
        pattern: blob-report-*
        merge-multiple: true

    - name: Merge into HTML Report
      run: npx playwright merge-reports --reporter html ./all-blob-reports

    - name: Upload HTML report
      uses: actions/upload-artifact@v4
      with:
        name: html-report--attempt-${{ github.run_attempt }}
        path: playwright-report
        retention-days: 14

现在,您可以看到报告已经合并,并且一个合并的 HTML 报告可以在 GitHub Actions 工件标签中查看。

image 2024 12 16 18 20 44 980

Merge-reports CLI

npx playwright merge-reports path/to/blob-reports-dir 命令读取传入目录中的所有 Blob 报告并将它们合并成一个报告。

当合并来自不同操作系统的报告时,您需要提供一个明确的合并配置,以便区分应该使用哪个目录作为测试根目录。

支持的选项:

  • --reporter reporter-to-use

    指定生成的报告类型,可以使用逗号分隔多个报告类型。

    例如:

    npx playwright merge-reports --reporter=html,github ./blob-reports
  • --config path/to/config/file

    指定带有输出报告器的 Playwright 配置文件。使用此选项可以将额外的配置传递给输出报告器。此配置文件可以与生成 blob 报告时使用的配置文件不同。

    示例:

    npx playwright merge-reports --config=merge.config.ts ./blob-reports
    merge.config.ts
    export default {
      testDir: 'e2e',
      reporter: [['html', { open: 'never' }]],
    };