用 Playwright 给页面做回归截图
改样式最怕“这边修好了,那边塌了”。尤其是响应式布局,改一个断点很容易连带影响另一档宽度。 这篇记一下我用无头浏览器做回归截图的流程,成本很低,但能挡住大部分低级事故。
为什么要截图,而不是只写断言
断言只能验证你想得到的东西。布局问题往往出在你没想到的地方——文字换行、元素被挤出视口、 卡片高度不一致。截图的价值在于“把没想到的部分也留下来”,人工扫一眼就能发现异常。
它不能替代断言,两者是配合关系:断言守住确定的规则,截图兜住不确定的观感。
最小可用的做法
核心就三件事:固定视口、等页面稳定、按需注入数据。
const ctx = await browser.newContext({
viewport: { width: 390, height: 844 }, // 手机档
deviceScaleFactor: 2 // 高清屏截图更清楚
})
const page = await ctx.newPage()
await page.goto(url, { waitUntil: 'networkidle' })
await page.waitForTimeout(600) // 留给动画/图表渲染
await page.screenshot({ path: 'shot.png' })
宽度别只截一档。我习惯取 320 / 390 / 768 / 1440 四档,覆盖最窄的手机、常见手机、 平板断点和桌面。
先量数值,再看图
截图是给人看的,但很多问题可以先用数值卡住,比人工看更靠得住。 比如“有没有横向溢出”这一条,我每次都量:
const overflow = await page.evaluate(() =>
document.documentElement.scrollWidth - document.documentElement.clientWidth
)
// 任何宽度下都应该等于 0
同类可量化的还有:字体实际计算值、元素命中测试(判断遮罩是否真的挡住了下层按钮)、 可滚动区域是否真的能滚。这几项用脚本验证,比盯着截图靠谱。
页面依赖接口时怎么截
真实页面往往要登录、要拉数据,直接截图会得到一片空白。两种处理方式:
- 拦截请求返回固定数据:适合只验样式的情况,把接口 mock 掉, 数据用真实响应导出一份,避免手写导致结构与实际不一致。
- 起一个隔离预览:只挂载目标组件,绕过路由与登录。 适合细看单个页面,代价是要维护一点脚手架。
一个小技巧:mock 数据直接从线上接口导出成 JSON 再内联进脚本, 比手抄字段更省事,也不会因为字段名写错而“测了个假页面”。
几个踩过的坑
- 字体缺失导致排版失真。容器里没有中文字体时,文字会渲染成方框, 而且宽度和真实情况不一样——这样的截图不能用来判断布局。
- 全页截图会把 fixed 定位的元素拉长。抽屉、弹窗在 fullPage 截图里会显得异常, 这不是页面的问题,改成按视口截图即可。
-
等得不够。图表、懒加载图片没渲染完就截图,会得到一堆空白。
networkidle之后再加一点固定等待通常就够。
最后一点建议:把截图脚本随代码一起提交,改 UI 时跑一遍。 它不需要接进 CI 才能发挥作用——本地跑一次、人看一眼,收益就已经很大了。
← 返回首页