用途
proving-changes 用于证明一个修复或功能改动端到端有效且不会破坏其他功能。它面向“不会阅读代码的评审者”,要求提供足以让怀疑者信服的证据:每一项断言都必须有相应的观察结果,若断言为假,该观察结果应当不同。
它不替代单元测试、类型检查或 lint,但明确指出这些检查只能作为辅助,不能单独支撑“已端到端验证”的结论。当一个测试 mock 了缺陷所在的边界时,无论缺陷是否修复该测试都会通过,因此不能据此声称验证成功。
主要能力
该技能提供一套结构化的证明工作流:
-
列出断言与场景:写下改动正确的必要条件,以及每个条件的展示场景。包括报告者提供的原始场景(相同消息、仓库形态、平台、浏览器、文本大小、账号状态或版本)、改动触及的每个表面(Web、移动端、桌面应用、交互式 CLI、无头 CLI、API、SDK)及用户可见状态(加载、失败、恢复)、一个对照场景(邻近行为不应改变)、共享代码的相邻功能,以及评审者接下来会问的问题(是否破坏其他功能、性能开销前后对比、资源清理、跨平台、重启/重载/重连后是否仍有效)。
-
在未改动代码上复现:用同一脚本或流程在改动前的代码上运行失败场景并捕获失败。可通过 stash 改动、检出基础提交或构建旧版本实现。需重启服务器、worker 和客户端,避免长驻进程继续提供旧代码;检查版本字符串、构建哈希、日志行或文件校验和以确认实际执行的代码。对于重构或新测试框架,需植入故意行为变更以确认证明能检测到它。若失败无法复现,after 运行不能证明任何事,应调整环境直到复现,或明确说明并降低断言强度。功能工作没有失败可复现,则捕获起始状态作为对比基准。
-
走真实路径:按从强到弱的顺序驱动改动——部署产品或其 staging 副本的真实界面、完整本地栈(真实 UI、服务器、后台 worker、客户端及真实外部服务或其 staging/sandbox 版本)、一个真实组件与其真实邻居(如真实 CLI 对真实服务器)、通过公共接口的集成测试、单元测试与 mock。应使用环境允许的最强级别,并在报告中注明级别。若必须走捷径,需说明跳过了哪些代码。对于打包软件,应测试实际发布的产物(构建的容器、bundle、二进制或已安装包),因为源树测试通过但包中缺失文件仍会导致生产崩溃。
-
应用改动并重跑同一场景:在改动后的代码上重跑完全相同的流程,运行之间不改变数据、时序、注入延迟或视口。若缺陷过快难以观察,两次运行均以相同方式减速,并展示减速确实生效。运行第 1 步的整个矩阵,而不仅是报告的场景。
-
收集独立证据:每项断言收集多种证据以互相覆盖盲点。视觉证据:各状态截图、运动或时序重要时的录像、前后对比图、快速过渡的帧条。状态证据:DOM 与无障碍事实、数据库行、磁盘文件和 git 状态、API 响应、进程列表。日志:带时间戳的服务器、客户端和 worker 行,跨组件关联以显示所走代码路径。数字:计数、延迟、大小;性能需报告相同输入下重复运行的中位数,并说明测量了什么、在哪里测量。单张图片可能误导,每张截图需辅以状态事实(如属性值、行数或日志行)。演示 fixture 应真实,否则只能证明管道连通而非用户看到有用输出。
-
信任前检查每次运行:像评审者一样对照断言检查每个产物,查看帧并阅读数字。出现以下情况应丢弃该次运行、重跑并报告被丢弃的运行:进程仍运行旧代码;状态从前一次运行遗留(如选择、缓存或打开的对话框);捕获发生在动画、滚动或重试计时器期间;某个设置步骤静默失败(如缺少标志、错误账号或客户端断开);出现断言未预料的错误。将运行间无法解释的差异视为发现,两侧各运行足够次数以区分基础代码上的 flakiness 与改动引入的 flakiness。
-
证明将要发布的内容:在报告前 rebase 到当前目标分支并重跑判定性场景,因为针对旧基线的证明不覆盖将要合并的代码。需对完整 diff 负责:每一行删除、注释变更、触及的共享文件、配置编辑和密钥,要么证明其必需,要么移除。重构需要行为相同的证据,而不仅是测试通过。之后清理证明在共享系统中创建的内容:测试账号、组织、sandbox、分支和 staging 服务中的行。
按改动类型的判定性证据
- 视觉或布局缺陷:同一状态的前后截图;测量的位置或大小;每个受影响的大小、主题和输入方式。
- 交互或流程:真实流程的录像;每步后的状态事实;重载后的状态。
- 竞态、崩溃或时序缺陷:强制时序下复现的失败;显示修复前错误交错及其消失的日志;修复被回退时会失败的测试。
- 分布式或后端行为:跨组件的带时间戳日志;前后数据库和 API 状态;失败和恢复路径。
- 性能:相同输入下重复运行的前后中位数;显示时间去向的 profile。
- 重构:前后在输入矩阵上录制的相同行为;比较能检测到的植入变更。
- 安全或访问:拒绝场景被拒绝、允许场景被允许,针对真实身份提供者或其 staging 版本;无附带撤销。
- 交付(“是否上线”):部署版本包含该提交;生产日志或指标显示新路径运行。
报告证明
开头用一句话说明证明了什么以及在什么层级,例如“在本地栈上以真实 runner 端到端验证;尚未部署。”随后包括:案例表(before、after、预期结果);内联嵌入的截图和录像,每个标注所展示状态;判定性事实:日志行、状态值和数字;证明过程中出现的问题及解决方法,包括无效运行和修正后的断言;未证明的内容及原因(如未测试平台、生产时序或跳过的表面);产物和复现脚本的位置,以便评审者重跑证明。断言不应大于证据。存在缺口时应称证明为“强”而非“不可辩驳”,并指出缺口。被问是否确定时,给出实际信心及提高信心的方法。诚实的“不,且这是我未测试的内容”比过度断言更有用。需区分“已修复”与“尚未演练”:生产日志中的沉默意味着该场景未发生,除非证明它发生过并被处理。
常见失败方式
端到端测试调用了内部 API,因此通过但面向用户的 UI 从未发送新值;单元测试 mock 了真实行为即缺陷的依赖,修复在生产中静默无效;before 运行使用陈旧服务器进程,日志与测试代码矛盾;缺陷只在一个运行时(如原生应用 web view)复现,另一浏览器通过不能证明什么;修复移除了有意保留的代码,看起来像罪魁祸首,只有询问被移除的注释才揭示并非如此;打包步骤遗漏新文件,部署服务启动时本会崩溃;演示显示占位输出,证明流式传输而非功能;证明针对落后多个提交的基线运行,合并改变了结果。
适用场景与限制
适用于修复、功能开发、重构、性能优化、安全改动和交付上线验证等需要向评审者提供发布依据的场景。限制在于:它要求存在可复现的失败或可对比的起始状态,且需要较真实的环境与时间投入;对于无法复现失败且无明确断言的探索性工作,或环境限制无法走真实路径时,其证明强度会下降,需要明确标注未证明的部分。