别再往AI聊天框里粘错误日志了:用失败测试驱动修复

别粘贴错误日志,先写失败测试,把AI从猜谜模式锁进目标模式。
文章指出,把堆栈跟踪直接粘给 AI 是最常见的编程误用:日志缺乏代码库结构、依赖关系和成功标准等运行时上下文,模型只能盲目猜测,往往改动多个无关文件并引入新 bug,还把验证负担留给开发者。DevDeck 提出的替代方案是"复现提示词",分两步:先让 AI 写一个隔离的失败测试并实际运行,确认以退出码 1 失败;再要求它在不修改其他模块的前提下让测试以退出码 0 通过。失败测试由此提供了起点、终点和边界三重约束,把开放问题压缩为封闭问题。文章还比较了两种路径的成本结构,并提醒依赖复杂运行时状态的 bug 可能需要人工先搭测试骨架。
把几十行错误日志直接粘进 AI 聊天框,然后期待它一次性修好 bug——这大概是当下最常见的 AI 编程误用方式。来自 YouTube 频道 DevDeck 的一则短视频指出了问题的核心:原始堆栈跟踪对模型来说缺乏运行时上下文,它只能盲目猜测,结果往往是改动三个不相关的文件,并引入新的 bug。
资深工程师的做法截然不同:他们不粘贴日志,而是先写一个能稳定复现该 bug 的失败测试。这个简单的顺序调换,把 AI 从"猜谜模式"切换到了"目标模式"。
为什么粘贴错误日志会失败

堆栈跟踪记录的是错误发生那一刻的调用链,但它不包含代码库的结构、模块之间的依赖关系,也不包含"什么才算修好"的判定标准。模型拿到一段孤立的日志,唯一能做的就是基于训练数据中的常见模式去推测根因。
DevDeck 的描述很直接:模型会"盲目猜测,修改三个不相关的文件,并引入新的 bug"。这不是模型能力不足,而是输入信息本身缺少约束——没有明确的成功标准,模型就倾向于做"看起来相关"的广泛改动,而这些改动往往越过了真正的问题边界。
更隐蔽的代价是验证成本。当你拿到 AI 的修复建议时,你需要人工判断它改了哪些文件、这些改动是否合理、有没有副作用。日志粘贴法把这个判断负担完整地留给了开发者自己。
复现提示词:两步把 AI 锁进单一目标
DevDeck 给出的替代方案被称为"复现提示词"(reproduction prompt),流程只有两步,但每一步都在收紧 AI 的行动空间。
第一步:写一个隔离的失败测试

要求 AI 编写一个独立的测试脚本,精确复现该 bug,并以退出码 1 失败。写完不是结束——必须实际运行一次,确认它确实以失败状态退出。
这一步的价值在于把模糊的"有个 bug"转化成可执行的判定条件。退出码 1 是一个二进制信号:测试没通过,问题存在,且复现路径是确定的。如果测试跑出来是绿的,说明复现本身就没成功,后续所有修复都建立在流沙上。
退出码(exit code) 是进程结束时返回给操作系统的整数状态码,约定 0 表示成功,非 0 表示某种失败(1 是最通用的"一般错误")。在测试语境中,测试框架正是依据退出码判断结果:pytest、npm test、cargo test 等命令在全部用例通过时返回 0,只要有失败用例就返回非 0。因此"以退出码 1 失败"意味着这条测试命令在 shell 层面就能被脚本、CI 或 AI 自身识别为失败,无需解析人类可读的输出文本。这也让"让测试以退出码 0 通过"成为一个机器可判定的完成条件——AI 可以运行命令、读取退出码、循环修正,直到信号翻转。相比"请把 bug 修好"这类模糊指令,退出码提供了一个无歧义、可自动校验的反馈回路,是复现提示词能够自我收敛的技术基础。
隔离测试(isolated test) 指不依赖完整应用启动、外部网络服务或共享全局状态的测试,通常通过依赖注入、mock/stub 替身或内存数据库把被测代码与外部环境隔开。隔离的意义在于可重复性:如果测试依赖真实数据库或第三方 API,失败可能源于环境抖动而非代码缺陷,"红"的信号就不可信。对 AI 而言,隔离测试还有一层额外价值——它的运行速度快、输出聚焦,模型可以在一次对话内反复执行、观察结果、调整代码,而不会陷入漫长的环境搭建。写隔离测试往往需要先厘清被测函数的输入输出边界,这一动作本身就迫使开发者(或 AI)明确"bug 究竟发生在哪一层",从而缩小后续修复的搜索空间。
第二步:让测试变绿,且不碰其他模块

第二步的指令是:在不修改任何其他模块的前提下,让这个测试以退出码 0 通过。
这里的关键约束是"不碰其他模块"。AI 此时只有一个二元目标——测试从红变绿。它没有空间去做"顺手重构"或"顺便优化",因为任何越界改动都违反指令。DevDeck 的总结是:模型"无法产生幻觉或破坏其他文件,因为它只在测试变绿时才停止"。
为什么测试驱动对AI特别有效

人类工程师接到"修这个 bug"的任务时,通常自带对代码库的隐性理解:知道哪些文件不该动、哪些接口是稳定的、改动的影响半径大概多大。AI 没有这层理解,它需要外部机制来补上这个约束。
失败测试恰好提供了三重约束。第一,它定义了起点:bug 必须能被稳定复现。第二,它定义了终点:退出码从 1 变成 0。第三,它定义了边界:除测试覆盖的路径外不得改动其他模块。三者叠加,把开放式问题压缩成了封闭式问题。
这种方法的另一个好处是修复过程可审计。测试脚本本身就是一份文档,记录了 bug 的触发条件和预期行为。后续如果有人质疑修复是否完整,跑一遍测试就能回答。相比之下,粘贴日志的对话记录几乎不具备这种可复用性。
测试驱动开发(TDD) 的经典循环是"红—绿—重构":先写一个失败的测试(红),再写最少的代码让它通过(绿),最后在测试保护下重构。DevDeck 的复现提示词本质上是把这个循环搬到了人机协作场景,但做了一处关键改造:红与绿两个阶段都交给 AI 执行,人类只负责设定循环的边界条件。传统 TDD 中,开发者对代码库的隐性理解让"最少代码"成为自觉;AI 缺乏这层理解,于是"不碰其他模块"必须被显式写成指令,才能替代人类的直觉约束。换句话说,TDD 对 AI 有效的真正原因不是测试本身,而是测试把原本存在于工程师头脑中的验收标准外化成了可执行的断言——模型无法读取你的心智模型,但能读取断言失败的红灯。
两种调试路径的对比
DevDeck 在视频末尾抛出了一个二选一:失败测试优先,还是粘贴错误日志然后祈祷。
前者的成本前置——你需要先花时间把 bug 固化成测试;后者的成本后置——你需要花时间审查 AI 的广泛改动,并承担引入回归的风险。对于一次性、影响面清晰的小问题,直接问 AI 可能更快;但对于涉及多模块、有回归风险的 bug,测试先行几乎总是更省总时间。
这个判断标准本身就值得记住:问题的爆炸半径越大,越应该先用测试把边界画出来。
实践中的注意事项
复现提示词并非万能。如果 bug 依赖特定的运行时状态(比如并发时序、外部服务响应),写一个隔离的失败测试本身就需要相当的工作量,这部分工作 AI 未必能独立完成。此时更现实的做法是人先把测试骨架搭好,再让 AI 在骨架内修复。
另外,"不碰其他模块"是一条需要明确写进提示词的约束。如果不写,模型仍可能顺手改动周边代码。指令的精确程度直接决定了约束的有效程度。
DevDeck 将这套流程定位为"资深工程师的日常工作流",并以此作为频道内容的持续主题。对于日常与 AI 结对编程的开发者来说,把失败测试放在提示词的第一步,可能是投入产出比最高的一个习惯改变。
相关推荐

Anthropic Fable 5.2实测:一句话生成3A游戏与Excel克隆
Anthropic Fable 5.2实测:三行提示词生成可玩《战争机器》克隆、完整Excel和DaVinci Resolve克隆,解析基准测试、Ultra Code模式、token成本与定价策略,评估它是否值得替代Opus 5.5。

赛博寻书:BT社区如何「劫走」塞林格遗作
塞林格未发表的《The Ocean Full of Bowling Balls》仅存于大学图书馆且禁止复制。一个私密BT tracker悬赏六TB上传积分,社区从背诵接力到eBay买书扫描,最终成功让文本流出,却因传播过快被管理员删种。本文复盘这场赛博寻书行动及其讽刺结局。

弹劾防长赫格塞斯?五角大楼战争与中期选举风暴
五角大楼气氛紧张,伊朗战事持续八个月仍无退出方案。评论分析赫格塞斯弹劾动议的真实动机:不是罢免,而是留下政治记录,并剖析战争如何通过油价与生活成本影响中期选举选情。