跳到主要内容

AI 代码调试

AI 代码调试是借助编码 Agent 复现、定位和修复缺陷的过程。缺陷既会出现在既有代码中,也会出现在 AI 刚生成的实现中。

本文从失败现象出发,依次讲解复现、假设验证和回归,再说明多次尝试失败后怎样恢复任务。面试中的失败测试修复、并发代码找错和实现审查,都可以沿这条思路展开。

1. 面试核心​

先记住这几条,再读正文
  • 修复验证。 AI 可以帮助复现失败、阅读代码和提出候选原因。修复是否有效,要由原缺陷用例与回归结果验证。卡 · 调试步骤
  • 复现信息。 失败输入、实际输出和预期行为共同说明缺陷,相关代码位置帮助缩小定位范围。
  • 错误归因。 调试需要区分环境问题、需求理解偏差、实现错误和测试错误。
  • 配置热更新。 配置热更新在解析与校验通过后原子发布完整配置,使读取方看到一致的配置。卡 · 调试步骤
  • 任务恢复。 会话恢复需要保留已验证结论、有效代码改动和复现命令,再据此继续定位。卡 · 常见陷阱

2. 调试步骤​

调试需要把“看见了什么现象”变成“哪段代码为什么出错”。可以通过以下六个环节逐步确认原因:

  1. 复现:运行失败测试或复现命令,记录环境、输入和错误输出。先确认失败能够稳定出现,偶发问题则继续寻找触发条件。
  2. 缩小范围:沿测试输入、调用链和关键状态找到相关模块与函数。必要时添加临时日志或断点,观察实际执行路径。
  3. 提出假设:根据现象列出候选原因,再设计能区分这些原因的实验。实验应说明什么结果支持假设,什么结果会否定假设。
  4. 修复原因:依据实验结果修改导致缺陷的计算或状态更新逻辑。保留已确认正常的部分,使单次改动的影响容易判断。
  5. 回归:补充能暴露本次缺陷的测试,再运行受影响的已有测试。按影响范围扩大回归,检查是否破坏其他功能。
  6. 说明结果:对照 diff,也就是代码修改前后的差异,解释原因与修复。核对是否混入无关修改,并说明已验证和未验证的范围。

比如,分页结果错位时,可以提出假设:页码从 1 开始,offset 却按 page * pageSize 计算。这里的 offset 是需要跳过的记录数。第一页应该跳过 0 条,第二页应该跳过一页,因此可用这两个输入验证偏移。实验支持假设后,再把计算改为 (page - 1) * pageSize,并保留这组回归用例。

2.1 回归测试的判别能力​

要证明补丁修好了缺陷,测试必须能区分修复前后的行为。缺陷用例在修复前失败、修复后通过,才能提供这种证据。已有正常用例还需继续通过,用于确认已经覆盖的行为保持正常。

失败后需要区分以下四类原因,再决定修改什么:

  • 环境问题:依赖、配置或服务状态与复现要求不一致,应先恢复所需环境。
  • 需求理解偏差:实际需求与实现假设不同,需要先澄清预期行为。
  • 实现错误:代码违反已确认的行为要求,应修复对应逻辑。
  • 测试错误:断言与需求不符,应说明依据后调整测试。

这里的行为契约就是程序对输入输出和边界情况的约定。模型建议改测试时,要用这份约定判断断言是否正确。并发缺陷若单次运行未出现,可以固定线程间的触发顺序,或隔离共享状态后继续验证。

3. AI 参与方式​

Agent 可以加快陌生代码阅读和实验执行,开发者则需要判断证据是否支持结论。下表列出了各环节的分工。

环节Agent 的工作开发者的判断
复现执行命令、整理输出环境是否匹配
定位搜索引用、读取陌生代码推断是否符合实际状态
假设提出原因与实验实验能否区分候选原因
修复编写最小修改和用例修改是否解决根因
回归执行检查并整理差异验证是否覆盖影响范围

复现时要核对输入和环境是否与实际故障一致。多个假设并存时,优先验证影响大、证据强且容易区分的原因。修复后还要审查测试断言是否被修改,以及回归范围是否足够。

让 Agent 在修改前写出假设与证据,有助于及早发现误判。解释错误时可以先纠正,解释与代码一致后再改动,补丁也会更有针对性。

4. 常见陷阱​

连续尝试仍然失败时,要检查调试方式是否正在引入更多不确定因素。以下五类问题尤其值得注意:

  • 连续整体重写:一次改动涉及多个模块,会同时改变多个假设。后续即使结果变化,也难以判断是哪处修改起作用,因此应保留可用部分。
  • 放宽测试:删除断言、放宽比较或跳过用例,会让缺陷失去检测入口。只有测试违背需求时,才有调整断言的依据。
  • 只修当前输入:为失败输入添加 if 特判后,同类输入仍会走到有缺陷的路径。需要检查触发问题的共同原因。
  • 上下文污染:多次失败产生的错误结论继续留在对话中,模型会据此作出后续判断。这时应整理已确认事实,再压缩或重开会话。
  • 缺少验证:模型描述“已经修复”后,还需要运行测试。未执行验证时,交付说明应明确修复尚未确认。

恢复会话前,先检查工作区差异,保留用户改动及已验证有效的修复。需要撤销失败尝试时,只撤销已确认属于该尝试的修改。恢复到已知可用状态后,重新检查相关测试。

交给新会话的说明应保留以下任务事实:

  • 写清当前目标、验收要求和必须遵守的约束。
  • 列出已修改的文件,说明有效改动和当前代码状态。
  • 记录已确认的原因、已排除的假设及对应证据。
  • 提供复现命令和最近的测试结果,说明下一步要验证的问题。

新会话先核对当前代码,再解释对问题的理解,随后按小步骤验证。反复用到的稳定约定可以记入仓库指令,减少下次重复说明。

5 · 面试题卡片​

本页题目与参考回答

5.1 面对陌生代码库和失败测试,如何借助 AI 定位并修复问题?​

考察重点

  • 说明怎样从失败测试沿调用链定位,并通过实验验证原因。
  • 根据需求判断是否应该修改测试,并确定补丁与回归的范围。

相关内容:调试步骤、AI 参与方式。

参考回答

可以让 AI 协助复现和阅读代码,再用实验确认原因,最后通过缺陷测试与回归验证修复。

先运行失败测试,确认环境与失败位置。让 Agent 搜索测试入口和相关模块,说明调用关系,再核对它的解释是否符合代码。将错误输出、失败输入和预期行为放在一起,提出候选原因,用实验逐个区分。

确认原因后做最小修改,让缺陷用例从失败转为通过,再按影响范围扩大回归。模型建议修改断言时,对照需求检查理由。时间有限时,优先处理影响面大的失败。最后检查 diff,说明已经证实的原因、修复前后的差异和未验证范围。

5.2 配置文件热更新任务中,如何发现并修正 AI 生成实现的问题?​

考察重点

  • 从配置使用方能观察到的行为定义热更新的正确性。
  • 构造错误配置和并发等输入,依据实际输出向 AI 反馈问题。

相关内容:调试步骤、常见陷阱。

参考回答

配置热更新应先完成解析与校验,再原子替换完整配置;更新失败时的行为要符合约定。

先明确文件格式、生效时机、连续修改的处理方式,以及失败时是否保留旧配置。要求保留旧值时,应在独立对象上解析和校验,成功后再替换共享引用,让并发读者拿到完整的旧配置或新配置。

用正常更新、格式错误和连续修改复现行为,再检查并发读取。向 AI 反馈具体输入、实际结果与预期结果,才能验证修复是否覆盖原缺陷。

5.3 使用编码 Agent 时,上下文过长或模型反复出错,怎样把任务拉回正确方向?​

考察重点

  • 识别错误结论怎样干扰后续尝试,并判断何时应停止继续修改。
  • 说明怎样保留有效改动、整理事实,并在新会话中继续验证。

相关内容:常见陷阱、上下文压缩。

参考回答

恢复任务需要先停止无效修改,保留已验证的事实与有效改动,再从可复现的问题继续。

检查工作区差异,只撤销已确认失败的尝试,保留用户改动和有效修复。随后整理目标、约束、相关文件、已确认原因和已排除假设,附上证据与复现命令。

压缩上下文或重开会话后,先重新核对当前代码,让 Agent 解释对问题的理解。确认理解正确,再拆成可单独验证的小步骤,每一步用检查结果决定是否继续。这样可以减少旧错误结论对后续判断的影响。长期有效的约定则保存到仓库指令中。

5.4 怎样证明 AI 修复解决了原缺陷,而非仅让测试变绿?​

考察重点:用同一缺陷用例比较修复前后行为,并检查验收标准是否被改动。

相关内容:回归测试的判别能力。

参考回答

同一缺陷用例在修复前失败、修复后通过,并且原有回归用例继续通过,才能支持修复有效的判断。

两次运行要保持输入与环境一致,才能把行为变化归因于补丁。随后审查测试是否删除断言、放宽条件或跳过执行。测试契约确有错误时,说明需求依据后再调整。测试覆盖范围以外的行为,还需要结合代码审查判断。

6. 参考资料​