文章列表
3 分钟阅读

用 Playwright 给静态博客做视觉回归测试

更新说明:新增博客工程实践复盘文章。


系列:博客工程实践

第 2 / 2 篇

  1. 代码高亮从手写到 Expressive Code 的改造记录
  2. 用 Playwright 给静态博客做视觉回归测试

静态博客看起来不像复杂应用,但样式其实很容易被改坏。导航、搜索页、文章页、代码块、深浅色、移动端菜单,只要 CSS 改动稍微大一点,就可能出现肉眼没及时发现的问题。

我后来给博客加了 Playwright smoke test 和视觉回归。它不追求覆盖所有页面,而是守住几个关键入口。

为什么静态博客也需要浏览器测试

脚本检查能发现 frontmatter、链接、SEO 和构建产物问题,但发现不了这些问题:

  • 移动端导航打不开
  • 搜索筛选下拉不可用
  • 阅读进度条被遮住
  • 代码块主题没有跟随深浅色切换
  • 某次 CSS 改动让首页模块错位
  • 文章目录浮层打不开或关不掉

这些问题只有浏览器跑起来才看得到。

先做 smoke test

第一步是确认关键页面能打开,没有浏览器错误。

tests/smoke.spec.ts
test('关键页面可以打开且没有浏览器错误', async ({ page }) => {
const errors: string[] = [];
page.on('pageerror', (error) => errors.push(error.message));
for (const path of ['/', '/blog/', '/search/', '/series/']) {
await page.goto(path);
await expect(page.locator('h1').first()).toBeVisible();
}
expect(errors).toEqual([]);
});

这类测试很朴素,但价值很高。它能快速发现构建后页面脚本报错、路由不存在、首屏关键元素没渲染这类问题。

搜索页适合做交互测试

搜索页不是纯静态内容,它会加载 search-index.json,再做筛选、键盘操作和 URL 同步。

await page.goto('/search/');
await expect(page.locator('#search-status')).toContainText('共有');
await page.locator('#search-input').fill('FastAPI');
await expect(page.locator('#search-results')).toContainText('FastAPI');

移动端筛选折叠也要测。否则桌面端没问题,手机上用户却找不到分类和标签筛选。

视觉回归守住关键页面

我只给首页、搜索页、文章页做截图。不是因为其他页面不重要,而是这三个页面最能代表整体布局。

await expect(page).toHaveScreenshot('chromium-home.png', {
animations: 'disabled',
maxDiffPixelRatio: 0.03,
});

截图测试不是让页面永远不能变,而是让变化必须被看见。比如移动端搜索筛选改成默认收起后,截图会失败;确认这是预期变化,再更新基线。

文章页要测代码块和主题

文章页最复杂:目录、代码块、复制按钮、深浅色、相关文章、系列列表都在这里。

我会检查这些点:

  • Expressive Code 是否挂载
  • 复制按钮是否有中文提示
  • 行号是否存在
  • 重点行是否显示
  • diff 行是否有样式
  • 终端块是否存在
  • 深色模式下代码背景不是白色

代码块改造本身可以看 代码高亮从手写到 Expressive Code 的改造记录,测试里只需要验证它在真实页面上的关键表现。

这种测试比单纯截图更具体。截图告诉你“变了”,断言告诉你“哪个功能坏了”。

无障碍检查也能抓视觉问题

有一次我把终端代码块背景调得太深,浅色主题下 token 颜色对比度不够。肉眼看着只是“有点暗”,Axe 直接报了 color contrast。

const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);

所以无障碍检查不只是为了形式,它也能帮助发现真实的视觉质量问题。

什么时候更新截图

只有确认是预期 UI 变化时才更新截图。比如:

  • 页面布局主动调整
  • 移动端交互方式变化
  • 设计系统统一样式
  • 代码块视觉改造

如果只是随手改 CSS 后截图失败,不要急着更新基线。先看 diff 图,确认不是溢出、遮挡或错位。

总结

Playwright 给静态博客带来的不是“测试覆盖率好看”,而是改页面时更有底。内容检查管数据,构建检查管产物,浏览器测试管真实体验。

我现在更倾向于把博客当成一个小型产品维护。只要有搜索、主题切换、代码块、移动端导航和截图基线,Playwright 就值得加。