Skip to content

第 11 章 · 截图、视频与 Trace Viewer

本章目标:掌握元素/整页截图与视觉回归断言,学会录制测试视频,并能用 Trace Viewer 像看"行车记录仪"一样复盘失败用例的每一毫秒。

11.1 截图:从留档到断言

截图有三个层级,用途各不相同:

python
# ① 视口截图(默认):只截当前可视区域
page.screenshot(path="viewport.png")

# ② 整页截图:滚动拼接整个可滚动页面,像"很高的屏幕"一样完整呈现
page.screenshot(path="full.png", full_page=True)

# ③ 元素级截图:只截某个组件,适合做视觉基线
page.locator(".header").screenshot(path="header.png")

# ④ 不落盘,拿字节流自行处理
png_bytes = page.screenshot()

整页截图的实现是"虚拟拉高视口",因此对懒加载页面要先滚动触发加载;元素截图则自动等待该元素稳定可见。

11.2 视觉回归断言

expect(locator).to_have_screenshot() 把截图变成可重试的断言:首次运行生成基线图存入快照目录,之后每次运行做像素对比,不一致即失败。配合 pytest 运行时可用 --update-snapshots 刷新基线:

python
from playwright.sync_api import Page, expect

def test_header_visual(page: Page):
    page.goto("https://demo.playwright.dev/todomvc")
    expect(page.locator(".header")).to_have_screenshot("header.png")

视觉对比要警惕"环境噪声":字体渲染随操作系统变化、动画导致像素抖动、动态时间戳区域永远过不了对比。实践上应固定 viewport 与 device_scale_factor、冻结动画(CSS 上 animation: none),并把易变区域排除在截图范围外。

11.3 录制测试视频

在 context 级别开启录制,视频会在 context 关闭时才写盘——手动创建 context 时别忘了 close:

python
context = browser.new_context(
    record_video_dir="videos/",
    record_video_size={"width": 640, "height": 480},   # 默认按视口缩放到 800x800 内
)
page = context.new_page()
page.goto("https://demo.playwright.dev/todomvc")
# ... 测试步骤 ...
context.close()                       # 关闭后视频才可用

path = page.video.path()              # 之后可通过 page.video 获取文件路径
print("视频保存在:", path)

视频的价值在于给非技术人员看"测试到底做了什么";但它体积大、信息密度低,CI 里建议只对失败用例保留。

11.4 Trace Viewer:失败用例的黑匣子

Trace 是 Playwright 调试体系的王牌:它记录每一步动作前后的 DOM 快照、网络请求、console 日志,回放时可以时间旅行到任何一步查看页面当时的样子。API 层三行代码:

python
browser = chromium.launch()
context = browser.new_context()

# 开始记录:DOM 快照 + 截图 + 源码定位
context.tracing.start(screenshots=True, snapshots=True, sources=True)

page = context.new_page()
page.goto("https://playwright.dev")
# ... 测试步骤 ...

# 停止并导出为单个 zip
context.tracing.stop(path="trace.zip")

打开 trace 的两种方式:

bash
playwright show-trace trace.zip          # 本地 GUI 打开
# 或浏览器访问 https://trace.playwright.dev 拖入 zip
# 该站点完全在浏览器本地解析,数据不会外传;也支持传 URL 直接打开远程 trace

11.5 pytest 中的失败取证自动化

pytest-playwright 插件把上面的一切变成了命令行开关,无需手写 tracing 代码:

bash
pytest --tracing retain-on-failure   # 失败保留 trace,成功自动删除
pytest --video retain-on-failure     # 同样支持视频开关
pytest --screenshot only-on-failure  # 失败自动截图

--tracing 的三个取值:on(全部记录)、off(默认,不记录)、retain-on-failure(只留失败的)。产物统一落在 test-results/ 目录下。生产 CI 的标准配置就是 retain-on-failure 三件套:失败后把整个目录作为构建工件上传,排查问题不再靠猜。

开销权衡

trace 记录 DOM 快照有可感知的性能开销,所以默认关闭、只在需要时开启是对的。本地复现疑难 bug 时可以临时 --tracing on 精确定位。

本章小结

  • 截图分视口 / full_page / 元素级三级;字节流模式便于接入第三方像素对比服务;
  • to_have_screenshot 让视觉回归成为自动重试的断言,但要控制环境噪声;
  • 视频在 context 关闭时才落盘,--video retain-on-failure 是 CI 友好姿势;
  • Trace Viewer 通过 tracing.start/stop--tracing retain-on-failure 使用,配合 playwright show-trace 或 trace.playwright.dev 回放。

🧪 随堂测验

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

1. page.screenshot(full_page=True) 的行为是?

2. 关于录制视频,正确的说法是?

3. pytest-playwright 中只想为失败用例保留 trace,应使用?

4. 关于 trace.playwright.dev,正确的是?

🛠️ 动手实践

  1. 为 TodoMVC 演示页建立三个视觉基线(头部、输入框、列表项),故意改一个 CSS 后观察对比失败输出。
  2. 用 API 方式录制一段操作视频,验证"context 未 close 时 page.video.path() 不可用"这一行为。
  3. 故意写一个会失败的定位器,开 --tracing retain-on-failure 跑一次,再用 show-trace 找到失败瞬间并查看当时的 DOM 快照。

下一章:设备仿真与多浏览器