系列:博客工程实践
- 代码高亮从手写到 Expressive Code 的改造记录
- 用 Playwright 给静态博客做视觉回归测试
静态博客看起来不像复杂应用,但样式其实很容易被改坏。导航、搜索页、文章页、代码块、深浅色、移动端菜单,只要 CSS 改动稍微大一点,就可能出现肉眼没及时发现的问题。
我后来给博客加了 Playwright smoke test 和视觉回归。它不追求覆盖所有页面,而是守住几个关键入口。
为什么静态博客也需要浏览器测试
脚本检查能发现 frontmatter、链接、SEO 和构建产物问题,但发现不了这些问题:
- 移动端导航打不开
- 搜索筛选下拉不可用
- 阅读进度条被遮住
- 代码块主题没有跟随深浅色切换
- 某次 CSS 改动让首页模块错位
- 文章目录浮层打不开或关不掉
这些问题只有浏览器跑起来才看得到。
先做 smoke test
第一步是确认关键页面能打开,没有浏览器错误。
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 就值得加。