Playwright CI 实战指南:在持续集成环境中稳定运行浏览器自动化测试
本文基于 Playwright 官方文档 docs/src/ci.md 编写,系统讲解如何把 Playwright 测试接入各类 CI 平台(GitHub Actions、Azure Pipelines、CircleCI、Jenkins、GitLab CI 等),覆盖浏览器依赖安装、workers 与 globalTimeout 两大关键配置、各平台完整工作流配置、分片(sharding)并行策略,以及浏览器启动故障排查与有头模式运行等实战技巧。读完本文,你可以直接复制可用的 CI 配置,并结合 Playwright 源码理解每个配置项背后的实现机制。
三步走:让 CI Agent 跑起 Playwright 测试
Playwright 测试完全可以在 CI 环境中执行,官方为常见 CI 提供商提供了示例配置。整体流程分为三步:
第 1 步:确保 CI Agent 能运行浏览器。在 Linux agent 上使用官方 Docker 镜像(见 docs/src/docker.md),或使用 Playwright CLI 安装系统依赖(--with-deps,该选项在 CLI 中的定义可参考 packages/playwright-core/src/cli/program.ts)。
第 2 步:安装 Playwright。各语言生态的安装命令如下:
# Install NPM packages
npm ci
# Install Playwright browsers and dependencies
npx playwright install --with-deps
pip install playwright
playwright install --with-deps
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
dotnet build
pwsh bin/Debug/netX/playwright.ps1 install --with-deps
第 3 步:运行测试:
npx playwright test
pytest
mvn test
dotnet test
关键配置一:CI 环境中的 workers 设置
官方建议在 CI 环境中把 workers 设置为 1,优先保证稳定性与可复现性。顺序执行确保每个测试独占全部系统资源,避免潜在冲突。如果你拥有性能强劲的自托管 CI 系统,也可以启用并行;对于更宽的并行度,考虑分片(sharding)——把测试分发到多台 CI 机器上。
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
// Opt out of parallel tests on CI.
workers: process.env.CI ? 1 : undefined,
});
源码佐证:从 packages/playwright/src/common/config.ts 可以看到,当配置中没有显式指定 workers 时,默认值是 '50%';而 resolveWorkers 函数 会把百分比解析为「CPU 核数 × 百分比」并至少为 1。这意味着在 CI 容器(如 GitHub Actions 的 2 核 runner)上不设置 workers 时,Playwright 默认就会按核数并行——这正是官方建议显式设为 1 的原因:核心数很少的 CI 机器上盲目并行容易造成资源争抢与偶发超时。
关键配置二:始终设置 globalTimeout
在 CI 中务必设置 global timeout。默认情况下,一次测试运行没有上限时长:一旦某个测试套件挂起、或随着测试规模增长超出了 CI 提供商的 job 时限,运行会在中途被 runner 杀掉,从而无法生成测试报告。
设置了 globalTimeout 后,Playwright 会自己停止整个运行:
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Fail the run after an hour, so that the reporters still produce a report.
globalTimeout: 60 * 60 * 1000,
});
源码佐证:配置解析位于 packages/playwright/src/common/config.ts,globalTimeout 的解析优先级为「CLI 覆盖值 → 用户配置值 → 默认值 0」,其中 0 表示不限时——这与文档中「默认没有上限」的说明完全一致。执行侧的 runTasks 函数 只有在 globalTimeout 大于 0 时才会计算 deadline;超时后 TaskRunner 会中断后续任务并向 reporter 上报 Timed out waiting Xs for the ... to run 错误,保证 reporter 有机会收尾输出完整报告。
此外,下文给出的示例均不设置 job 级超时(如 GitHub Actions 的 timeout-minutes)。如果你确需添加,请让它显著高于 globalTimeout,确保总是由 Playwright 先停止。
CI 平台配置:GitHub Actions
Playwright 的命令行工具可以在 CI 中安装所有操作系统依赖。
push/pull_request 触发(JavaScript)
测试将在 main/master 分支的 push 或 pull request 时运行。工作流会安装全部依赖、安装 Playwright 浏览器,然后运行测试,并上传 HTML 报告作为 artifact:
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
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
- uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
push/pull_request 触发(Python / Java / .NET)
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.13'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Ensure browsers are installed
run: python -m playwright install --with-deps
- name: Run your tests
run: pytest --tracing=retain-on-failure
- uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: playwright-traces
path: test-results/
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '25'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Ensure browsers are installed
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
- name: Run tests
run: mvn test
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup dotnet
uses: actions/setup-dotnet@v5
with:
dotnet-version: 8.0.x
- name: Build & Install
run: dotnet build
- name: Ensure browsers are installed
run: pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps
- name: Run your tests
run: dotnet test
分片执行(Sharded)
GitHub Actions 支持跨多个 job 分片测试,可参考官方 sharding 文档了解分片原理、GitHub Actions 示例(如何把测试分发到多台机器运行)以及如何合并 HTML 报告。
容器化运行(Via Containers)
通过 jobs.<job_id>.container 选项让 job 运行在容器内,好处是:不污染宿主环境依赖;为截图/视觉回归测试在不同操作系统间提供一致的环境。
JavaScript 版:
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
options: --user 1001
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Run your tests
run: npx playwright test
Python / Java / .NET 版本分别使用 mcr.microsoft.com/playwright/python:v%%VERSION%%-noble、mcr.microsoft.com/playwright/java:v%%VERSION%%-noble、mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble 镜像,容器内已完成浏览器与系统依赖预装,因此步骤中不需要再执行 install --with-deps,只需安装依赖包并直接运行测试即可(%%VERSION%% 为文档构建时替换为具体 Playwright 版本的占位符)。
部署后触发(On deployment)
以下工作流在 GitHub Deployment 进入 success 状态后启动测试。Vercel 等 PaaS 服务支持这一模式,你可以在它们部署出的环境上运行端到端测试:
name: Playwright Tests
on:
deployment_status:
jobs:
test:
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
env:
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
Python、Java、.NET 版本的写法同理:监听 deployment_status 事件、在 success 时运行,并把 PLAYWRIGHT_TEST_BASE_URL 环境变量指向 ${{ github.event.deployment_status.target_url }}(不同测试 runner 对环境变量名的约定可能不同,需自行适配)。
Fail-Fast:--only-changed 预检
大型测试套件执行耗时很长。通过 --only-changed 参数先做一轮预检,可以优先执行最可能失败的测试文件,在 Pull Request 阶段获得更快的反馈、并略微降低 CI 消耗。--only-changed 通过分析测试套件的依赖图来检测受改动影响的测试文件——这是一种启发式方法,可能漏掉测试,因此预检之后必须始终跑完整测试套件。
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
# Force a non-shallow checkout, so that we can reference $GITHUB_BASE_REF.
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run changed Playwright tests
run: npx playwright test --only-changed=origin/$GITHUB_BASE_REF
if: github.event_name == 'pull_request'
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
源码佐证:CLI 参数定义于 packages/playwright/src/program.ts,其帮助文本说明该参数「只运行 HEAD 与 ref 之间有变更的测试文件,默认对比所有未提交的改动,仅支持 Git」。实际检测逻辑在 packages/playwright/src/runner/vcs.ts 的 detectChangedTestFiles 中:它执行 git diff <base> --name-only 与 git ls-files --others --exclude-standard 收集变更文件,再交给 cc.affectedTestFiles 换算为受影响的测试文件。值得注意的是该函数会显式检测 shallow clone(git rev-parse --is-shallow-repository)——这正是上方 YAML 中必须设置 fetch-depth: 0 的原因,否则浅克隆仓库无法解析基线引用,会直接抛出错误。
CI 平台配置:Docker
官方提供了预构建 Docker 镜像,可直接使用,也可作为参考来改造你自己的 Docker 定义。建议遵循 Recommended Docker Configuration 以获得最佳性能。
从 docs/src/docker.md 可以看到三条关键推荐:
- 使用
--init标志,避免 PID=1 进程的特殊处理(僵尸进程的常见原因); - 使用 Chromium 时建议使用
--ipc=host,否则 Chromium 可能内存不足而崩溃; - 若本地开发时 Chromium 启动出现奇怪错误,可尝试
docker run --cap-add=SYS_ADMIN。
CI 平台配置:Azure Pipelines
Windows 或 macOS agent 无需额外配置,安装 Playwright 后直接运行测试即可。Linux agent 可选用官方 Docker 容器运行容器化 job,或使用命令行工具安装所有必要依赖。
JavaScript:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: UseNode@1
inputs:
version: '22'
displayName: 'Install Node.js'
- script: npm ci
displayName: 'npm ci'
- script: npx playwright install --with-deps
displayName: 'Install Playwright browsers'
- script: npx playwright test
displayName: 'Run Playwright tests'
env:
CI: 'true'
Python:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.13'
displayName: 'Use Python'
- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
displayName: 'Install dependencies'
- script: playwright install --with-deps
displayName: 'Install Playwright browsers'
- script: pytest
displayName: 'Run Playwright tests'
Java:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: JavaToolInstaller@1
inputs:
versionSpec: '25'
jdkArchitectureOption: 'x64'
jdkSourceOption: AzureStorage
- script: mvn -B install -D skipTests --no-transfer-progress
displayName: 'Build and install'
- script: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
displayName: 'Install Playwright browsers'
- script: mvn test
displayName: 'Run tests'
.NET:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: UseDotNet@2
inputs:
packageType: sdk
version: '8.0.x'
displayName: 'Use .NET SDK'
- script: dotnet build --configuration Release
displayName: 'Build'
- script: pwsh bin/Release/net8.0/playwright.ps1 install --with-deps
displayName: 'Install Playwright browsers'
- script: dotnet test --configuration Release
displayName: 'Run tests'
上传 playwright-report 并集成测试结果
以下配置让 pipeline 在任一 Playwright 测试失败时整体失败;同时通过 PublishTestResults 任务把测试结果集成进 Azure DevOps:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: UseNode@1
inputs:
version: '22'
displayName: 'Install Node.js'
- script: npm ci
displayName: 'npm ci'
- script: npx playwright install --with-deps
displayName: 'Install Playwright browsers'
- script: npx playwright test
displayName: 'Run Playwright tests'
env:
CI: 'true'
- task: PublishTestResults@2
displayName: 'Publish test results'
inputs:
searchFolder: 'test-results'
testResultsFormat: 'JUnit'
testResultsFiles: 'e2e-junit-results.xml'
mergeTestResults: true
failTaskOnFailedTests: true
testRunTitle: 'My End-To-End Tests'
condition: succeededOrFailed()
- task: PublishPipelineArtifact@1
inputs:
targetPath: playwright-report
artifact: playwright-report
publishLocation: 'pipeline'
condition: succeededOrFailed()
注意:JUnit reporter 需要在 playwright.config.ts 中相应配置:
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [['junit', { outputFile: 'test-results/e2e-junit-results.xml' }]],
});
分片执行(Azure Pipelines, sharded)
trigger:
- main
pool:
vmImage: ubuntu-latest
strategy:
matrix:
chromium-1:
project: chromium
shard: 1/3
chromium-2:
project: chromium
shard: 2/3
chromium-3:
project: chromium
shard: 3/3
firefox-1:
project: firefox
shard: 1/3
firefox-2:
project: firefox
shard: 2/3
firefox-3:
project: firefox
shard: 3/3
webkit-1:
project: webkit
shard: 1/3
webkit-2:
project: webkit
shard: 2/3
webkit-3:
project: webkit
shard: 3/3
steps:
- task: UseNode@1
inputs:
version: '22'
displayName: 'Install Node.js'
- script: npm ci
displayName: 'npm ci'
- script: npx playwright install --with-deps
displayName: 'Install Playwright browsers'
- script: npx playwright test --project=$(project) --shard=$(shard)
displayName: 'Run Playwright tests'
env:
CI: 'true'
容器化执行(containerized)
在 job 层面直接指定 container(按语言选择对应镜像),容器内已预装浏览器,无需 install --with-deps:
trigger:
- main
pool:
vmImage: ubuntu-latest
container: mcr.microsoft.com/playwright:v%%VERSION%%-noble
steps:
- task: UseNode@1
inputs:
version: '22'
displayName: 'Install Node.js'
- script: npm ci
displayName: 'npm ci'
- script: npx playwright test
displayName: 'Run Playwright tests'
env:
CI: 'true'
Python / Java / .NET 分别使用 mcr.microsoft.com/playwright/python:…、mcr.microsoft.com/playwright/java:…、mcr.microsoft.com/playwright/dotnet:… 镜像,步骤简化为「安装依赖 → 运行测试」即可。
CI 平台配置:CircleCI
在 CircleCI 上运行 Playwright 与 GitHub Actions 非常相似。在 config 的 agent 定义中加入 docker: 指定官方预构建镜像即可:
executors:
pw-noble-development:
docker:
- image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
Python / Java / .NET 同理,把镜像换成 mcr.microsoft.com/playwright/{python,java,dotnet}:v%%VERSION%%-noble。
资源档位注意:使用 docker agent 定义时,你需要显式指定 Playwright 运行的 resource class 为 medium 档位。Playwright 的默认行为是把 workers 数设置为检测到的 CPU 核数(medium 档位为 2)。把 workers 数设置得高于核数会导致不必要的超时和失败——这与前文 resolveWorkers 按核数解析 '50%' 默认值的机制相呼应。
CircleCI 分片
CircleCI 的 CIRCLE_NODE_INDEX 从 0 开始计数,因此需要覆盖默认并行环境变量:给 CIRCLE_NODE_INDEX 加 1 后再传给 --shard:
playwright-job-name:
executor: pw-noble-development
parallelism: 4
steps:
- run: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npx playwright test --shard=${SHARD}/${CIRCLE_NODE_TOTAL}
CI 平台配置:Jenkins
Jenkins 的 pipeline 支持 Docker agent,使用 Playwright Docker 镜像即可运行测试:
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright:v%%VERSION%%-noble' } }
stages {
stage('e2e-tests') {
steps {
sh 'npm ci'
sh 'npx playwright test'
}
}
}
}
Python 版本在容器内执行 pip install -r requirements.txt + pytest;Java 版本执行 mvn -B install -D skipTests --no-transfer-progress + mvn test;.NET 版本执行 dotnet build + dotnet test,镜像分别为 mcr.microsoft.com/playwright/{python,java,dotnet}:v%%VERSION%%-noble。
CI 平台配置:Bitbucket Pipelines、GitLab CI、Google Cloud Build 与 Drone
Bitbucket Pipelines 支持将公共 Docker 镜像作为构建环境,直接使用官方镜像:
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
GitLab CI 同样使用官方公共 Docker 镜像:
stages:
- test
tests:
stage: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
script:
...
各语言镜像选择规则与其他平台一致(python / java / dotnet 变体)。
GitLab 分片:GitLab CI 支持用 parallel 关键字把 job 拆分为多个并行小 job(命名为 job_name 1/N … job_name N/N):
stages:
- test
tests:
stage: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
parallel: 7
script:
- npm ci
- npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
GitLab 还支持 parallel:matrix:单个 job 在一条 pipeline 内以不同变量值运行多次。下例中 2 个 PROJECT 值 × 10 个 SHARD 值 = 共 20 个 job:
stages:
- test
tests:
stage: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
parallel:
matrix:
- PROJECT: ['chromium', 'webkit']
SHARD: ['1/10', '2/10', '3/10', '4/10', '5/10', '6/10', '7/10', '8/10', '9/10', '10/10']
script:
- npm ci
- npx playwright test --project=$PROJECT --shard=$SHARD
Google Cloud Build:
steps:
- name: mcr.microsoft.com/playwright:v%%VERSION%%-noble
script:
...
env:
- 'CI=true'
Drone:
kind: pipeline
name: default
type: docker
steps:
- name: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
commands:
- npx playwright test
不建议缓存浏览器二进制文件
官方不建议缓存浏览器二进制:恢复缓存所花的时间与直接下载二进制的时间相当,而且在 Linux 上还必须安装操作系统依赖——这部分是不可缓存的。
如果你仍然希望在 CI 运行之间缓存浏览器二进制,请缓存这些目录,并以 Playwright 版本的哈希作为缓存 key。
调试浏览器启动失败
Playwright 支持 DEBUG 环境变量在执行期间输出调试日志。排查 Error: Failed to launch browser 错误时,把它设为 pw:browser 会非常有帮助:
DEBUG=pw:browser npx playwright test
DEBUG=pw:browser pytest
DEBUG=pw:browser mvn test
DEBUG=pw:browser dotnet test
在 CI 中以有头模式(headed)运行测试
Playwright 默认以 headless 模式启动浏览器。Linux agent 上运行有头模式需要安装 Xvfb——官方 Docker 镜像 与 GitHub Action 已预装 Xvfb。在有 Xvfb 的环境中以有头模式运行浏览器,只需在命令前加 xvfb-run:
xvfb-run npx playwright test
xvfb-run pytest
xvfb-run mvn test
xvfb-run dotnet test
小结:CI 配置要点速查
| 要点 | 建议 | 依据 |
|---|---|---|
| 浏览器依赖 | npx playwright install --with-deps 或官方 Docker 镜像 |
docs/src/ci.md、docs/src/docker.md |
| workers | CI 中设为 1,自托管强机器可并行、跨机用 shard |
docs/src/test-sharding.md、resolveWorkers |
| globalTimeout | 始终设置(如 1 小时),且 job 级超时须高于它 | runTasks |
| 报告 | 容器化/镜像环境保证跨 OS 视觉一致;上传 playwright-report |
各平台配置示例 |
| 大套件 | --only-changed 预检 + 全量兜底;注意 fetch-depth: 0 |
detectChangedTestFiles |
| 排查 | DEBUG=pw:browser;有头模式用 xvfb-run |
docs/src/ci.md |
以上所有配置均可在当前仓库的 docs/src/ci.md 中查阅原始版本,配合 docs/src/docker.md 的镜像说明与 docs/src/test-sharding.md 的分片详解,即可搭建完整的 Playwright CI 流水线。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00