关于 run-goldens-rebaseline
面向 Flutter 开发者的视觉基准图更新流程技能,强调人工审查而非用更新基准掩盖测试失败。它规定环境、检查图像、清理旧文件及单独提交的步骤。
主要功能
- 01先验证非图像断言
- 02限定基准更新环境
- 03逐张检查变更图像
- 04清理孤立图像和失败产物
- 05基准图单独提交并复测
适用场景
- 01确认预期界面变更后更新基准图
- 02排查不同环境造成的图像差异
- 03审查整组视觉基准变化
- 04防止 CI 自动改写基准图
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ zakariaf/ flutter-skills --skill run-goldens-rebaseline安装后在 Claude Code 中输入/run-goldens-rebaseline确认已加载。
详细介绍
黄金图重新基线
批准黄金图会覆盖 UI 过去的唯一记录。这是测试套件中唯一一个会破坏断言而不是运行断言的操作,因此这是一个手动、自由度低、由人工执行的工作流:按顺序执行步骤,不要自行变通,也绝不要为了消除失败而运行它。
双通道黄金图策略、测试框架,以及黄金图为何是最弱的视觉断言,都属于 widget-golden-and-a11y-testing。本技能仅包含更改基线的流程。
不容妥协的规则
- 黄金图失败是一个问题,不是待办事项。 重新生成任何内容前,先回答:我是否有意更改这些像素?如果无法对每张变更的图像都明确回答“是”,那么这就是回归问题,应修复代码。
- 先让真正的断言全部通过。 重新设定基线前,计算几何、点击目标尺寸、溢出、文本缩放和纯 Dart 对比度测试都必须通过。原因:黄金图无法断言任何内容——一张裁切了不可读文本的获批截图也会永远通过。断言才是门槛;图像只是用于比较差异。
- 只能在固定的批准环境中重新设定基线。 必须使用生成已提交图像时的相同操作系统和 Flutter 版本。原因:字体栅格化因主机而异,因此在其他环境中批准会让所有图像都被主机噪声改写,永久破坏其他人的比较结果。
- 必须运行过
loadAppFonts()。 否则,真实字体通道会把每个字形都渲染为 Ahem 方框,你批准的就会是一堵矩形墙,而且它会永远“通过”。 - 绝不要在 CI 中运行
--update-goldens,也绝不要用它来修复红色流水线。 会重写自身检查对象的门槛等于毫无断言(ci-pipeline-and-gates)。批准是本地进行、由人工审核的操作。 - 绝不要批准不稳定的黄金图。 如果黄金图在代码未更改时发生变化,那就是环境或动画稳定问题——应让帧泵到稳定状态、消除时间依赖,或删除黄金图。重新批准只会掩盖问题,直到下次运行时再次出现。
- 逐张用肉眼检查每张变更的图像。 不看数量,也不看差异统计——要看图像。原因:这就是整个审核过程;发现无关屏幕发生变化,正是这套流程存在的目的。
- 一次性批准所有受影响的图像,绝不要只批准其中一部分。 只批准预期会变化的图像,会让其他图像继续失败,并引发第二轮未经审核的操作。
- 删除残留文件。 重命名或删除黄金图测试后,对应的 PNG 会永久留存,而且不会触发任何失败。删除过时文件也是同一变更的一部分。
- **将图像作为独立提交提交,并与移动这些图像的变更放在同一个 PR 中,**提交说明要写明更改了什么以及为什么。原因:二进制文件混在代码提交中会让代码差异难以阅读,审核者也无法区分有意重新设定基线和夹带的变更。
有序工作流
- 确认此次更改是有意的,并确认非 golden 测试套件(几何、溢出、文本缩放、对比度、a11y)全部通过。
- 不加标志运行一次失败的 golden 测试,并阅读失败输出。
Flutter 会在 golden 文件旁写入
failures/*_testImage.png、*_masterImage.png和*_isolatedDiff.png— 在做出任何决定前,先打开差异图。 - 确认你使用的是基准环境(固定的操作系统,以及与生成已提交基线时相同的
flutter --version)。 - 仅针对 golden 标签重新生成基线:
flutter test --update-goldens --tags golden # or a single file while iterating: flutter test --update-goldens test/golden/notes_screen_golden_test.dart - 列出实际发生更改的文件,并逐一打开:
意料之外的图像意味着回归。停止操作,回退这些图像(git status --porcelain -- '*.png'git checkout -- <paths>),并修复代码。 - 删除孤立文件 — 不再被任何测试引用的 golden 文件:
# Every committed golden whose filename appears in no test source. for f in $(git ls-files 'test/**/goldens/*.png'); do grep -rq "$(basename "$f")" test --include='*.dart' || echo "orphan: $f" done - 删除
failures/产物,以免它们被提交。 - 验证:不带标志重新运行测试套件。
如果仍有测试失败,说明刚写入的基线无法复现结果 — 可能是动画尚未稳定、值随时间变化,或字体未加载。flutter test --tags golden - 单独提交图像,例如:
test(goldens): rebaseline notes screen — row height 40→48 (design review FIX-12)。
验证(阻断性 — PR 合并前必须通过)
flutter test --tags golden在不带--update-goldens的情况下通过,并连续运行两次,以发现运行结果不稳定的 golden。- 已打开每个更改过的 PNG,并确认其符合预期;没有无关内容发生变化。
- 不存在
failures/目录、孤立 PNG,且.github/workflows/中没有任何--update-goldens。 - 几何、对比度和 a11y 断言 — 真正能有效发现问题的那些断言 — 仍然全部通过。
反模式
- 测试一红就直接使用
--update-goldens— 这会删除断言,而不是阅读断言结果。 - 在与生成基线时不同的机器或 Flutter 版本上重新生成基线 — 会用依赖主机环境的光栅化结果重写所有图像;其他人的测试套件都会失败。
- 未调用
loadAppFonts()就重新生成基线 — 一整屏 Ahem 方框会被当成正确结果。 - 在 CI 工作流中使用
--update-goldens— 此后门禁将永远不再验证任何内容。 - 将图像与代码更改一起提交 — 审查者无法区分有意的基线更新与意外更改。
- 只为部分失败的测试重新生成基线 — 其余测试会在下一次运行时失败,然后在未经审查的情况下被重新生成基线。
- 重命名测试后留下孤立 PNG — 这些无用文件再也不会触发测试失败。
- 反复更新持续变化的 golden — 这是需要修复的抖动测试,而不是需要更新的基线。
- 提交
failures/*_testImage.png— 这些文件会造成噪声,还会悄悄成为第二套无人信任的“参考”图像。
完成标准
- 视觉更改是有意的,并且已逐一目视检查所有更改过的图像。
- 重新生成基线之前,非 golden 的几何、溢出、文本缩放、对比度和 a11y 测试均已通过,且现在仍然通过。
- 在固定的基准环境中重新生成基线,并确保已调用
loadAppFonts()。 - 受影响的整组图像在一次操作中全部重新生成基线;没有意外更改。
- 已删除孤立的 golden 文件;已移除
failures/产物。 -
flutter test --tags golden在不带该标志的情况下连续通过两次。 - 图像在同一个 PR 中单独提交,提交说明写明更改原因。
- CI 配置中没有任何
--update-goldens。
相关技能
widget-golden-and-a11y-testing— 两条黄金测试通道、pumpApp测试框架、loadAppFonts(),以及为什么黄金测试是整个测试套件中最弱的断言。ci-pipeline-and-gates— 门禁负责验证,绝不负责认可;固定运行器规则。design-review-workflow— 能合理地产生有意视觉变更的评审流程。design-system-structure— 导致所有黄金测试结果都发生变化的令牌修改源自何处。testing-strategy— 实际上应该承担主要验证职责的断言。
参考资料
- Flutter —
matchesGoldenFile:https://api.flutter.dev/flutter/flutter_test/matchesGoldenFile.html - Flutter —
flutter test选项(--update-goldens、--tags):https://docs.flutter.dev/reference/flutter-cli - Flutter —
GoldenFileComparator/LocalFileComparator:https://api.flutter.dev/flutter/flutter_test/GoldenFileComparator-class.html golden_toolkit/alchemist—loadAppFonts():https://pub.dev/packages/alchemist
评论
支持 Markdown