搜索—计划—编辑—测试的工作循环
建议用时:25 分钟(含练习)
学习目标
能够把模糊需求拆成可验证步骤,并要求 Agent 先取证、再修改、最后运行相关测试。
本节产出
一份带验证命令的实施计划
核心知识:每一步都应减少一个不确定性
可靠的编码循环不是机械地执行“搜索、计划、编辑、测试”四个词,而是让每一步回答一个问题。
- 搜索:帮助确认问题在哪里。
- 计划:说明准备改变什么和怎样检查。
- 编辑:实现最小必要行为。
- 测试:判断假设是否成立,并发现是否影响原有路径。
若一步没有带来新证据,就需要检查它是否只是重复动作。
开始搜索时,可以从用户看到的文案、路由、函数名或错误信息进入,再沿调用关系找到实现与测试。不必一次读取整个仓库,也不要只看第一个匹配就修改。一个按钮可能在多个页面复用,某个字段也可能经过后端转换;搜索结果需要结合上下文判断。
计划应与任务大小相称。一处错字不需要十页方案;跨模块行为变更则需要列出接口、数据流、兼容影响和验证方法。好的计划包含可观察的结束条件,而不只是“提升性能、增强稳定性”。如果还不能说明预期行为,就应继续理解问题。
图中的反馈路径很重要:失败后先解释失败属于代码、环境还是测试假设,再决定下一次修改。不能把任何红色输出都当成需要删除的障碍,也不能把每次通过都当成整个功能已经正确。
用测试固定行为,而不是复刻实现
对于可复现的 Bug,先写一个能够表现错误行为的测试,再确认它确实因为目标问题失败。若测试失败只是模块路径写错,尚未证明 Bug 被捕获。之后做最小修改使行为符合要求,再检查相关旧测试。
测试应从外部可观察行为出发。例如“空列表显示说明文字”比“代码中包含某个三元表达式”更耐用。实现可能重构,行为合同仍可保持。对于纯文案或其他低影响改动,适当的预览与差异检查可能已经足够,不需要为每个字符新建复杂测试。
案例:过滤器漏掉大小写变体
虚构函数按标签筛选记录。需求明确规定标签比较忽略大小写,现有实现却把 Reading 和 reading 当成不同标签。你先找出筛选函数、输入来源和现有测试,确认标签只在这个函数中比较,而不是在其他地方预先统一格式。
编写两个行为样例:大小写不同仍能匹配,不同单词不能匹配。确认旧实现对第一项失败、第二项通过,再修改比较逻辑。若还存在前后空格,是否去除空格需要另看需求,不能因为顺手就加入未约定的语义。
修复后,除了新样例,还应检查空标签、无匹配结果以及原有调用方式。对于 Unicode 等更复杂情况,应在真实需求涉及它们时明确规则,不用一个简单教学例子宣称覆盖所有语言的大小写问题。
失败记录怎样写
| 失败现象 | 需要区分的原因 | 下一步 |
|---|---|---|
| 新测试不能运行 | 路径或测试配置错误 | 修正测试环境,不动业务断言 |
| 测试运行但行为不符 | 实现错误或需求理解偏差 | 对照合同定位差异 |
| 新测试通过、旧测试失败 | 引入回归或旧合同冲突 | 分析影响,不能直接删除旧测试 |
| 本地通过、构建失败 | 类型、打包或环境差异 | 读取具体构建错误 |
日志只需保存定位问题所需的信息。大量重复输出可能淹没真正错误;更不应把真实用户数据或秘密写进报告。给出准确命令、退出状态和关键失败位置,通常比粘贴全部日志更有用。
动手练习
- 为标签比较例子写出两项正向检查和一项边界检查,说明它们分别保护什么行为。
- 写一份五步以内的实施计划,包含搜索、复现、最小修改、验证与 diff 审阅。
- 模拟一次“新测试通过但旧测试失败”,列出你要核对的问题;不要通过删除旧断言来回避冲突。
参考答案与推演
可以检查 Reading 与 reading 匹配、read 与 reading 不匹配,以及空输入按既有规则处理。若空输入从未定义,先查调用方与合同,或明确提出需要确认的范围;不要在测试里暗中创造新需求。
旧测试失败时,先比较它保护的行为与本次任务是否矛盾,再检查实现是否误改了全局数据。只有确定旧断言已经被新的明确需求取代,才应连同理由更新测试。最终记录要能解释为什么修改正确,而不是只报告绿色数量。
完成检查
- 每个步骤都解决明确问题,计划与任务规模相称。
- 新测试真正复现目标行为,而不是因配置错误失败。
- 检查原有路径,未通过删测试掩盖回归。
- diff 中没有无关重构或偷偷增加的业务规则。
参考与来源
- Claude Code:Best practices:探索、计划与可验证工作流的实践说明。
- Node.js:Test runner:查看可执行测试、断言与运行结果的官方参考。
搜索—计划—编辑—测试的工作循环
3 道题 · 及格分 60 分