第 11 章 · 截图、视频与 Trace Viewer
本章目标:掌握元素/整页截图与视觉回归断言,学会录制测试视频,并能用 Trace Viewer 像看"行车记录仪"一样复盘失败用例的每一毫秒。
11.1 截图:从留档到断言
截图有三个层级,用途各不相同:
# ① 视口截图(默认):只截当前可视区域
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 刷新基线:
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:
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 层三行代码:
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 的两种方式:
playwright show-trace trace.zip # 本地 GUI 打开
# 或浏览器访问 https://trace.playwright.dev 拖入 zip
# 该站点完全在浏览器本地解析,数据不会外传;也支持传 URL 直接打开远程 trace11.5 pytest 中的失败取证自动化
pytest-playwright 插件把上面的一切变成了命令行开关,无需手写 tracing 代码:
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,正确的是?
🛠️ 动手实践
- 为 TodoMVC 演示页建立三个视觉基线(头部、输入框、列表项),故意改一个 CSS 后观察对比失败输出。
- 用 API 方式录制一段操作视频,验证"context 未 close 时 page.video.path() 不可用"这一行为。
- 故意写一个会失败的定位器,开
--tracing retain-on-failure跑一次,再用 show-trace 找到失败瞬间并查看当时的 DOM 快照。