AI 代码调试
AI 代码调试是借助编码 Agent 复现、定位和修复缺陷的过程。缺陷既会出现在既有代码中,也会出现在 AI 刚生成的实现中。
本文从失败现象出发,依次讲解复现、假设验证和回归,再说明多次尝试失败后怎样恢复任务。面试中的失败测试修复、并发代码找错和实现审查,都可以沿这条思路展开。
1. 面试核心
先记住这几条,再读正文2. 调试步骤
调试需要把“看见了什么现象”变成“哪段代码为什么出错”。可以通过以下六个环节逐步确认原因:
- 复现:运行失败测试或复现命令,记录环境、输入和错误输出。先确认失败能够稳定出现,偶发问题则继续寻找触发条件。
- 缩小范围:沿测试输入、调用链和关键状态找到相关模块与函数。必要时添加临时日志或断点,观察实际执行路径。
- 提出假设:根据现象列出候选原因,再设计能区分这些原因的实验。实验应说明什么结果支持假设,什么结果会否定假设。
- 修复原因:依据实验结果修改导致缺陷的计算或状态更新逻辑。保留已确认正常的部分,使单次改动的影响容易判断。
- 回归:补充能暴露本次缺陷的测试,再运行受影响的已有测试。按影响范围扩大回归,检查是否破坏其他功能。
- 说明结果:对照 diff,也就是代码修改前后的差异,解释原因与修复。核对是否混入无关修改,并说明已验证和未验证的范围。
比如,分页结果错位时,可以提出假设:页码从 1 开始,offset 却按 page * pageSize 计算。这里的 offset 是需要跳过的记录数。第一页应该跳过 0 条,第二页应该跳过一页,因此可用这两个输入验证偏移。实验支持假设后,再把计算改为 (page - 1) * pageSize,并保留这组回归用例。
2.1 回归测试的判别能力
要证明补丁修好了缺陷,测试必须能区分修复前后的行为。缺陷用例在修复前失败、修复后通过,才能提供这种证据。已有正常用例还需继续通过,用于确认已经覆盖的行为保持正常。
失败后需要区分以下四类原因,再决定修改什么:
- 环境问题:依赖、配置或服务状态与复现要求不一致,应先恢复所需环境。
- 需求理解偏差:实际需求与实现假设不同,需要先澄清预期行为。
- 实现错误:代码违反已确认的行为要求,应修复对应逻辑。
- 测试错误:断言与需求不符,应说明依据后调整测试。
这里的行为契约就是程序对输入输出和边界情况的约定。模型建议改测试时,要用这份约定判断断言是否正确。并发缺陷若单次运行未出现,可以固定线程间的触发顺序,或隔离共享状态后继续验证。
3. AI 参与方式
Agent 可以加快陌生代码阅读和实验执行,开发者则需要判断证据是否支持结论。下表列出了各环节的分工。
| 环节 | Agent 的工作 | 开发者的判断 |
|---|---|---|
| 复现 | 执行命令、整理输出 | 环境是否匹配 |
| 定位 | 搜索引用、读取陌生代码 | 推断是否符合实际状态 |
| 假设 | 提出原因与实验 | 实验能否区分候选原因 |
| 修复 | 编写最小修改和用例 | 修改是否解决根因 |
| 回归 | 执行检查并整理差异 | 验证是否覆盖影响范围 |
复现时要核对输入和环境是否与实际故障一致。多个假设并存时,优先验证影响大、证据强且容易区分的原因。修复后还要审查测试断言是否被修改,以及回归范围是否足够。
让 Agent 在修改前写出假设与证据,有助于及早发现误判。解释错误时可以先纠正,解释与代码一致后再改动,补丁也会更有针对性。
4. 常见陷阱
连续尝试仍然失败时,要检查调试方式是否正在引入更多不确定因素。以下五类问题尤其值得注意:
- 连续整体重写:一次改动涉及多个模块,会同时改变多个假设。后续即使结果变化,也难以判断是哪处修改起作用,因此应保留可用部分。
- 放宽测试:删除断言、放宽比较或跳过用例,会让缺陷失去检测入口。只有测试违背需求时,才有调整断言的依据。
- 只修当前输入:为失败输入添加
if特判后,同类输入仍会走到有缺陷的路径。需要检查触发问题的共同原因。 - 上下文污染:多次失败产生的错误结论继续留在对话中,模型会据此作出后续判断。这时应整理已确认事实,再压缩或重开会话。
- 缺少验证:模型描述“已经修复”后,还需要运行测试。未执行验证时,交付说明应明确修复尚未确认。
恢复会话前,先检查工作区差异,保留用户改动及已验证有效的修复。需要撤销失败尝试时,只撤销已确认属于该尝试的修改。恢复到已知可用状态后,重新检查相关测试。
交给新会话的说明应保留以下任务事实:
- 写清当前目标、验收要求和必须遵守的约束。
- 列出已修改的文件,说明有效改动和当前代码状态。
- 记录已确认的原因、已排除的假设及对应证据。
- 提供复现命令和最近的测试结果,说明下一步要验证的问题。
新会话先核对当前代码,再解释对问题的理解,随后按小步骤验证。反复用到的稳定约定可以记入仓库指令,减少下次重复说明。
5 · 面试题卡片
本页题目与参考回答
5.1 面对陌生代码库和失败测试,如何借助 AI 定位并修复问题?
考察重点
- 说明怎样从失败测试沿调用链定位,并通过实验验证原因。
- 根据需求判断是否应该修改测试,并确定补丁与回归的范围。
参考回答
可以让 AI 协助复现和阅读代码,再用实验确认原因,最后通过缺陷测试与回归验证修复。
先运行失败测试,确认环境与失败位置。让 Agent 搜索测试入口和相关模块,说明调用关系,再核对它的解释是否符合代码。将错误输出、失败输入和预期行为放在一起,提出候选原因,用实验逐个区分。
确认原因后做最小修改,让缺陷用例从失败转为通过,再按影响范围扩大回归。模型建议修改断言时,对照需求检查理由。时间有限时,优先处理影响面大的失败。最后检查 diff,说明已经证实的原因、修复前后的差异和未验证范围。
5.2 配置文件热更新任务中,如何发现并修正 AI 生成实现的问题?
考察重点
- 从配置使用方能观察到的行为定义热更新的正确性。
- 构造错误配置和并发等输入,依据实际输出向 AI 反馈问题。
参考回答
配置热更新应先完成解析与校验,再原子替换完整配置;更新失败时的行为要符合约定。
先明确文件格式、生效时机、连续修改的处理方式,以及失败时是否保留旧配置。要求保留旧值时,应在独立对象上解析和校验,成功后再替换共享引用,让并发读者拿到完整的旧配置或新配置。
用正常更新、格式错误和连续修改复现行为,再检查并发读取。向 AI 反馈具体输入、实际结果与预期结果,才能验证修复是否覆盖原缺陷。
5.3 使用编码 Agent 时,上下文过长或模型反复出错,怎样把任务拉回正确方向?
考察重点
- 识别错误结论怎样干扰后续尝试,并判断何时应停止继续修改。
- 说明怎样保留有效改动、整理事实,并在新会话中继续验证。
参考回答
恢复任务需要先停止无效修改,保留已验证的事实与有效改动,再从可复现的问题继续。
检查工作区差异,只撤销已确认失败的尝试,保留用户改动和有效修复。随后整理目标、约束、相关文件、已确认原因和已排除假设,附上证据与复现命令。
压缩上下文或重开会话后,先重新核对当前代码,让 Agent 解释对问题的理解。确认理解正确,再拆成可单独验证的小步骤,每一步用检查结果决定是否继续。这样可以减少旧错误结论对后续判断的影响。长期有效的约定则保存到仓库指令中。
5.4 怎样证明 AI 修复解决了原缺陷,而非仅让测试变绿?
考察重点:用同一缺陷用例比较修复前后行为,并检查验收标准是否被改动。
相关内容:回归测试的判别能力。
参考回答
同一缺陷用例在修复前失败、修复后通过,并且原有回归用例继续通过,才能支持修复有效的判断。
两次运行要保持输入与环境一致,才能把行为变化归因于补丁。随后审查测试是否删除断言、放宽条件或跳过执行。测试契约确有错误时,说明需求依据后再调整。测试覆盖范围以外的行为,还需要结合代码审查判断。