Skip to content

第 16 章 · CI 集成与 Docker

本章目标:把 E2E 套件跑进 GitHub Actions,用官方容器保证环境一致性,并在失败时自动留存 trace 等诊断工件。

16.1 CI 三步走

官方把 CI 接入总结为三步:

  1. 让 CI 机器能跑浏览器——Linux 上用官方 Docker 镜像,或用 CLI 装系统依赖;
  2. 安装 Playwright——pip install playwright && playwright install --with-deps
  3. 跑测试——pytest

其中 --with-deps 会顺带装好操作系统级依赖库(libnss3 等),漏掉它是"本地能跑、CI 报缺库"的头号原因。

16.2 GitHub Actions 基础工作流

官方示例工作流(Python 版):

yaml
# .github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

jobs:
  test:
    timeout-minutes: 60
    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   # 失败时保留 trace

      - name: Upload traces                       # 无论成败都上传工件
        uses: actions/upload-artifact@v5
        if: ${{ !cancelled() }}
        with:
          name: playwright-traces
          path: test-results/

两个细节值得咀嚼:

  • --tracing=retain-on-failure 是 pytest-playwright 提供的开关:只有失败用例才落盘 trace,成功的不浪费空间;
  • 上传工件的 if: ${{ !cancelled() }} 保证即使有测试失败、工作流被判定失败,trace 也照样传出来——否则你只能看到红叉看不到证据。

16.3 用官方容器获得一致环境

宿主机环境漂移(字体、时区、依赖版本)会让截图类断言莫名失败。官方镜像 mcr.microsoft.com/playwright/python 内置了全部浏览器和系统依赖,把 job 直接跑在容器里:

yaml
jobs:
  playwright:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/playwright/python:v1.61.0-noble  # 版本要与 pip 安装的 playwright 匹配
      options: --user 1001                                       # 非 root 运行更安全
    steps:
      - uses: actions/checkout@v6
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r local-requirements.txt
          pip install -e .
      - name: Run your tests
        run: pytest

版本对齐

镜像 tag 里的 Playwright 版本必须与你 pip install 的 playwright 大版本一致(如都用 1.61/1.62),否则驱动协议不匹配会直接报 executable 不存在或协议错误。镜像只含浏览器不含 Python 包,pip install playwright 仍需执行。

加速:两层缓存

  • pip 缓存actions/setup-python 自带 cache: pip
  • 浏览器缓存:非容器方案下缓存 ~/.cache/ms-playwright 目录,key 中带上 playwright 版本号,命中后跳过上百 MB 的下载。

16.4 本地 Docker 运行要点

想在容器里手动调试(或自建 runner),记住三个官方推荐参数:

bash
# E2E 测试属于可信代码,可直接 root 运行(root 下 Chromium 自动禁用沙箱)
docker run -it --rm --init --ipc=host \
  mcr.microsoft.com/playwright/python:v1.61.0-noble /bin/bash

# 爬取不可信网站时:改用独立用户 + seccomp 配置启用沙箱
docker run -it --rm --ipc=host \
  --user pwuser \
  --security-opt seccomp=seccomp_profile.json \
  mcr.microsoft.com/playwright/python:v1.61.0-noble /bin/bash
  • --ipc=host:Chromium 共享内存需求大,默认 64MB 的 IPC 分区会导致浏览器随机 OOM 崩溃——这是 Docker 跑 Chromium 最经典的坑;
  • --init:避免 PID=1 进程的特殊处理产生僵尸进程;
  • --cap-add=SYS_ADMIN:本地开发遇到奇怪的启动报错时可先加上排查(沙箱权限问题)。

16.5 失败诊断的完整闭环

CI 里一条用例挂了,理想的信息链是:

text
JUnit/终端输出(哪条挂了) → HTML 报告(步骤截图) → trace.zip(逐步回放+网络+控制台)

pytest 侧的对应产出:

bash
pytest \
  --junitxml=results/report.xml \      # CI 系统聚合展示
  --html=results/report.html \         # pytest-html 插件:带每步截图的静态报告
  --screenshot=only-on-failure \       # pytest-playwright:失败截图到 test-results/
  --video=retain-on-failure \          # 失败录像
  --tracing=retain-on-failure          # 失败 trace(第 11 章的 Trace Viewer 打开)

注意区分:Node 版 Playwright 有内置 HTML Reporter,而 Python/pytest 生态中 HTML 报告由第三方 pytest-html 提供,--tracing/--video/--screenshot 则是 pytest-playwright 插件的选项——两者职责不同,常配合使用。

16.6 本章小结

  • CI 三步:装浏览器依赖 → 装 Playwright → pytestinstall --with-deps 别省;
  • 官方容器镜像保证环境一致,tag 版本必须与 pip 包对齐;容器内记得 --ipc=host--init
  • --tracing=retain-on-failure + upload-artifact(if: !cancelled()) 构成失败取证闭环;
  • Python 生态的 HTML 报告来自 pytest-html,trace 才是最强证据。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. CI 上报错缺少 libnss3 等系统库,最直接的解法是?

2. 上传失败 trace 的 step 为什么要加 if: !cancelled()?

3. Docker 里运行 Chromium 必须加 --ipc=host 的原因是?

4. 关于官方容器镜像 mcr.microsoft.com/playwright/python,说法正确的是?

🛠️ 动手实践

  1. 给你的仓库写一份完整的 playwright.yml,包含 pip 与浏览器目录双层缓存,并实际触发一次运行。
  2. 故意让一条用例失败,从 Artifacts 下载 trace 并用 playwright show-trace 回放定位原因。
  3. 用官方镜像在本地起容器跑通你的套件,对比去掉 --ipc=host 后是否出现浏览器崩溃。

完成后进入下一章:APIRequestContext 与 API 测试