用AI改bug时,我强制自己先写一句复现命令,命中率翻倍

发布于 2026年09月12日 ❤ 0 👁 28 阅读 💬 2 评论

用AI改bug时,我强制自己先写一句“复现命令”,命中率翻倍

先说背景。上周我维护的一个采集脚本,跑一批任务时总在第37条左右崩,报错是KeyError: 'url'。以前的我拿到这种错,第一反应是把报错贴给模型,让它猜哪里可能有问题。

这么做的问题不是模型不行,是我给的信息太穷。模型看不到数据长什么样,只能按“最常见情况”猜,于是它给了一串“加try/except”“用get兜底”的补丁。我照着改了,当天不崩了,第三天换个数据源又崩。

这次我换了个做法,给整个过程加了一道约束:在让AI动手之前,我必须先产出一条能稳定复现的命令。

什么叫“能稳定复现”:不是"我这里会崩",而是一行可以复制到终端、跑十次崩十次的命令。为了写出这行命令,我被迫做了三件事:

第一,把触发条件缩小。我从“跑整批任务”缩到“只跑第37条”,这就逼我去看第37条的原始数据,而不是整批日志。

第二,把输入固定下来。我把那条数据dump成文件,命令里写死这个文件路径。这一步很关键,因为它把“环境问题”和“数据问题”分开了。我很快发现不是网络、不是超时,是那一条记录的字段结构跟别的不一样。

第三,把预期和实际写清楚。命令跑完应该输出什么,现在实际输出什么,两行对照。

做完这三步我再看错误,其实已经很清楚了:那个数据源在缺字段时返回的是null而不是空字符串,脚本里判空用的是if not item.get('url')没拦住null进入了后续拼接。

真正让我改观的是接下来发生的事。我把这条复现命令连同两段原始数据一起发给模型,它一次就给了根因判断,还指出了同一个文件里另外两处有相同的判空逻辑没被我注意到。我grep了一下,属实。

对比一下两轮对话的成本:第一次我描述了半小时的“现象”,来回改了四轮;第二次我只发了一条命令加两个数据片段,一轮结束。差别不在模型,在于我给的信息能不能被验证。

现在我给自己定了条死规矩,写进我的日常流程:

  1. 遇到偶发bug,先把“偶发”这个词消灭掉,用固定输入把它变成必现。

  2. 复现命令必须能独立跑,不依赖我本地的隐式状态。

  3. 拿不出复现命令就不问AI,先自己花时间造一个。造不出来的,说明我还没理解问题。

这条规矩还有一个附带好处:复现命令本身变成了回归测试的种子。修完之后我把它存进项目里,下次同一个地方再出问题,一条命令直接判定。

踩过的坑也记一下:一开始我图省事,用“跑整批然后看日志”当复现方式,结果一条命令跑三分钟,来回试五次就是十五分钟,效率反而更低。复现要的是“最小”,不是“最真实”。最小且稳定,才有迭代价值。

结论很简单:AI不会因为你的报错截图变聪明,但会因为你的复现命令变得准确。把“描述现象”换成“给出可执行的最小复现”,是我今年在AI辅助改bug上性价比最高的一个改动。

评论 (2)

Meicheng · 站长
Meicheng · 站长 2026年09月12日
这个「先写复现命令」的做法我特别认同。补一个自己的经验:复现命令一定要写成「一条能直接复制粘贴跑」的形式,而不是口头描述。很多时候 bug 的根因,恰恰藏在你「觉得不用写」的那一步里——写成命令一跑,边界条件自己就浮出来了。
Meicheng · 站长
Meicheng · 站长 2026年09月13日
这条我特别认同,尤其是「把偶发变成必现」这一步,很多人栽在跳过它直接问 AI。我补一个反向的坑:复现命令也别造得太「全」——我一开始习惯把整个环境的依赖都带上,结果一条命令跑三分钟,来回迭代五轮就废了半小时。后来才悟到,复现要的是「最小且稳定」,不是「最真实」。再补一个我的用法:修完 bug 后把这条复现命令直接存进项目里当回归测试种子,下次同一处再出问题,一条命令就判定,不用重新猜。

登录 后参与评论