better-test · git:20261009.443953a · 2026-10-09 · sha256 87e0fcda93b9e28c
better-test git:20261009.443953aA
Immutable. This exact content never changes and is served at /api/v1/blob/87e0fcda93b9e28c.
--- name: better-test description: 验证改动、写测试、审查或清理测试时使用:验证方法、什么测试值得留、端到端测试写法、DELETE/REWRITE/KEEP 判决。 --- # Better Test 测试是负债。agent 自己写的单元、集成测试只复述实现:测试和代码出自同一份理解,不比实现更准;实测不提高正确率,只增加时间和费用。持久测试只有两种来源:用户给出或认可的用例,和覆盖关键用户流程的端到端测试。 只走一个分支: 1. 验证一次改动 → **验证**。 2. 用户要求测试,或工单给了用例 → **写测试**。 3. 审计或清理既有测试 → **清理与审计**。 ## 验证 按接近用户真实路径的顺序选最短方法,证据来自本次执行: 1. 项目已有测试、类型检查、构建中受影响的部分,或直接运行改动的命令; 2. **better-browser-use**:页面、DOM、截图、console、network; 3. curl 或 CLI:直接调用并核对响应内容; 4. **better-computer-use**:桌面应用或真机; 5. 都不可行:给用户"打开哪里 → 做什么 → 应看到什么"的最短清单,标注未验证。 修 bug 先按用户描述实际复现症状,修完走同一路径确认消失。同一路径第二次需要人工取证时,向用户提议补一条端到端测试。 ## 价值门 判既有测试和写新测试共用这一道门,六条全部成立才留: 1. **有来源**:保护的行为来自用户的需求、用例、bug 报告、公开合同或规格示例,不是 agent 对实现的理解。 2. **失败有意义**:一种可信回归会让它失败,且失败对应调用方或用户可见的问题。 3. **期望值独立**:期望值来自已知字面值、规格或示例,有可能与实现结果不一致。 4. **稳定接缝**:经公开接口或稳定 seam 观察,不依赖只为测试存在的生产导出、flag、wrapper 或注入点。 5. **抗重构**:行为不变的内部重构、无关文案或布局调整后仍然通过。 6. **唯一 owner**:该合同只在最低的可靠边界证明一次,且没有被现有测试、类型系统、编译器或 lint 等价保证。 ## 反模式 判断时按类对照;正则或文本命中只是线索,读完测试和被测代码才下结论。 - **同义反复**:按实现的算法重算期望值;断言声明等于自身;mock 返回什么就断言什么;期望值由被测 helper 或 renderer 自己产出。 - **变更探测器**:扫源码、import、标识符或字符串;数导出、路由、元素或清单行数;快照生成的 markup、组件树或 class 串;断言私有协作者、调用次数或调用形状。 - **重复**:同一场景在它穿过的每一层都重放一遍;近乎相同的用例(合并成表驱动);已被类型或编译保证的检查。 - **空洞**:没有断言或只证明"没崩";只测 getter、常量或框架能渲染。 - **虚假信号**:负向对照因无关原因通过(另一个守卫先拒绝、生产路径根本到不了);fixture 替被测方产出本该由它产生的结果;测试名承诺的比输入实际覆盖的多。 - **测试专用生产接缝**:只有测试调用的导出、全局、wrapper、flag,以及只被测试调用的死代码。 - **外观当行为**:尺寸、比例、坐标、computed style、布局 class、`scrollWidth`、挂载行数是外观证据,不是行为。视口只提供场景,断言落在用户任务完成上(移动端能找到并操作某个按钮)。用 role、可访问名、label 定位控件;只有措辞本身是需求时才断言文案。焦点和禁用态只在它就是交互合同时测(聚焦首个无效字段、对话框关闭后焦点归还);归一化矩阵放纯函数测试,组件层留一条代表用例。截图断言只在项目明确采用视觉回归时入套件。 **像实现但必须保留**:公开 API、协议与序列化字节、配置、迁移、存储格式、安全、默认值、跨语言生成物、架构约束——它们本身就是独立合同,满足价值门第 1 条。顺序可被观察时的调用顺序、以最低成本守住用户可见键名或路径的源码检查同理。 ## 写测试 1. 用例先与用户对齐;工单或用户给的用例原样采用。 2. 写成端到端测试:从用户真实入口(页面、CLI、公开 API)完成任务并断言结果;只 mock 付费或不可控的外部服务。 3. **见红**:每条新测试亲眼看到它因预期原因失败一次——功能尚未实现,或临时破坏被测实现(不是改断言)后再精确还原。从没红过的测试只证明了 mock。 4. 一条用例一个用户任务;固定 seed、时钟和网络,用条件等待代替 sleep;不留 skip、僵尸进程或生成物。 完成标准:每条新增测试都有用户认可的来源、过价值门且见过红。 ## 清理与审计 **范围与授权**:范围按用户请求钉死——diff、路径、模块或全仓;全仓只在用户明确要求时做。"审计""看看""找找"是只读,交报告为止;"清理""删掉""精简"授权在范围内直接改。 **分工**:每条判决要读的东西多,范围跨 3 个以上模块时按 [fan-out](../fan-out/SKILL.md) 中档分两波;全仓清理或用户要求仔细时用高档。 - 按生产 owner 模块切片,每片带该模块的测试文件。多个模块共用的支撑代码(fixture、helper、全局 setup)不分给工人,由编排者最后处理,保持每个文件一个写者。 - 第一波只读:与编排者同级的实现角色逐条判决,格式同下文报告,另交**跨片线索**——疑似与别片重复证明的合同(测试名、合同一句话、位置),没有写"无"。 - 收口:同一合同跨片重复时保留最低可靠边界上的那条,其余改判 DELETE 并补证据;抽查每片的 KEEP 举证和 DELETE 证据,不全的退回。高档时 DELETE 另派不同模型的子代理独立复判,两份一致才删,不一致记为未定。审计到此合并报告。 - 第二波(清理):原工人(或附定稿判决的新工人)只改片内文件并跑片内最窄验证;编排者最后删共享支撑代码和跨片的测试专用接缝,跑受影响验证。 **逐条判决**,不按文件。判之前读完测试全文、被测生产 owner、它的调用方、重叠测试、相关 git 历史,以及项目自己的测试规则。 - **KEEP**:价值门六条逐条举证全部成立。 - **REWRITE**:测试里有一个过门的合同,但现写法不过。只保留证明该合同所需的准备、动作和断言,不沿用旧测试的体量、断言数或层级。 - **DELETE**:不过门(agent 写的、只复述实现的单元与集成测试通常落在这里),且写全三项证据——它实际能抓住什么失败;该行为别处更强的证明,或为什么不需要证明;它或它依赖的测试专用接缝当初为何存在。 - **未定**:KEEP 举证不全,DELETE 证据也不全。写进报告,不动。 既有测试在基线上就失败时,当作可能的产品缺陷先定位根因,不删。 **执行**:删测试时一并删掉它独占的测试专用生产接缝与死代码,以及因此失效的 fixture、helper、快照和 setup。为保住测试而改生产行为、降低断言、关闭规则、调低覆盖率阈值都不是解法;覆盖率或数量门槛挡住合理删除时,报告冲突。改完跑最窄受影响验证和仓库要求的门。 **报告**:写明是审计建议还是已完成的清理。逐条列出 DELETE / REWRITE / KEEP / 未定 的位置与理由;KEEP 和 REWRITE 附六条举证,DELETE 附三项证据;列出删掉的生产接缝、跑过的命令与结果,生产代码与测试代码的行数变化分开写。 完成标准:范围内每个候选都有判决,留下的测试全部过门,没有残留的死测试支撑代码,验证结果已知。