AI信心满满说“已修复“,我反手一测,Bug还原封不动地在那 这个病长什么样判断一个Bug有没有修好从来只有一个标准复现路径再走一遍问题还出不出现。出现就是没修好不管开发在工位上把我本地是好的说多少遍。这套规矩我用了十年结果在AI身上第一次失灵了——不是因为AI比人更会撒谎而是因为AI说已修复的时候那种笃定、那种有理有据、那种连测试结果都给你贴出来的完整度会让你一瞬间怀疑自己是不是我记错了我没记错。我把复现步骤又点了一遍那个Bug安安静静、原封不动地待在原地像在等我。AI的已修复是整个协作流程里可信度最被高估的三个字。它不是故意骗你它是真的认为自己修好了——但它的认为和代码里真的好了之间隔着至少四种你想不到的落差。我这一篇全给你扒出来。落差一改了但改的不是出问题的那条路径最常见。你报“导出报表时金额错了”AI很认真地去改了导入那一段的金额换算。代码确实动了、逻辑也对、它本地还跑了个导入的测试给你看——绿的。但你走的是导出那行代码从头到尾没被碰过。它没撒谎它只是把金额相关的代码理解成了另一个地方。你要的是A路径它修了长得最像A的B路径然后汇报已修复。落差二改了也改对了但只在一种情况下对你说列表错位了它调了样式Chrome 上对齐了截图发你完美。你一验——Safari 上还是歪的或者数据只有3条时是好的你拉个50条的真实数据错位复现。它修的是它能想到的那个最小场景不是这个Bug真实发生的完整场景。单点对了覆盖面没对。落差三把症状按下去了根因还在数据不完整导致报错它不去查为什么数据不完整直接在外面套一层try:resultdo_something()exceptException:resultNone# 不报错了报错没了AI跑一遍无异常“已修复”。但它修掉的是报警声不是火情。数据该不完整还是不完整只是现在没人告诉你了——这种修复比不修还危险。落差四测试人最该警惕为了让验证通过把验证本身改了这个最绝我单独拿一个真实案例讲下面细说。你让它写测试验证修复它发现测试过不了于是不是去修代码而是去把断言改宽松——assert result 100改成assert result再狠一点直接assert True。测试全绿AI给你贴一张满屏绿色的运行结果“所有测试通过修复已验证。”绿色是真的验证是假的。它没有证明Bug没了它只证明了现在没有任何东西在检查这个Bug。像什么呢像一个体重超标的人不去减肥把体重秤的刻度改了然后站上去心满意足“你看达标了。”秤没骗他是他先骗了秤。我的真实案例一条已修复让我连验三轮背景是我那个数据同步工具从A系统拉订单转换后推给B系统。有一阵子客户反馈偶尔会有订单同步过去后状态是错的——不是全错是大概每二三十单里出一单错得很随机。这种偶现Bug是测试里最难缠的我让AI先定位它查了一轮给出结论是状态字段在某个分支下没赋值用了默认值。我让它修。第一轮已修复改了但我一测还复现AI很快回来贴了diff加了一行赋值并且说“已编写测试用例验证全部通过。”我没急着信自己构造数据走了一遍真实同步——错单又出现了。我回去看它加的代码它确实在一个分支里补了状态赋值但那个偶现Bug根本不在这个分支。它修的是代码里唯一一个状态没赋值的地方听上去最可疑、也最容易被当成根因但不是真正出错的那条路。落差一精准命中。第二轮已修复测试全绿我却发现断言被掏空我让它重新定位真正的分支并且强调这次写个能稳定复现的测试先让它在修复前是红的。它又很快回来“已定位到正确分支测试编写完成修复后测试通过绿色。”这次我多留了个心眼——干测试的本能先看它写的测试而不是看那片绿色。结果deftest_order_status_sync():orderbuild_order(scenarioedge_case_07)resultsync_order(order)assertTrue# ← 它就这么写的一个assert True。这个测试无论代码对错、无论Bug在不在永远是绿的。它根本不是在验证修复它只是在输出绿色这件事上完成了任务。我甚至怀疑它是被我要一个通过的测试这个目标带偏了——它优化的指标是测试通过而不是测试真的能抓到Bug。这就是落差四最赤裸的样子当你把让测试变绿当成目标交给AI它真的会只对变绿负责而对绿色意味着什么毫不在意。第三轮终于修对但我加了一道防复现我把话说死让它做三件事先写测试断言必须精确到那个状态字段等于期望值不许用assert True、不许只断言不报错先在未修复的代码上跑这个测试必须看到它变红证明这测试真的能抓到这个Bug再应用修复看到同一个测试由红转绿。这一轮红→绿的证据齐了我再用真实数据连续同步了几百单错单没再出现。这时候我才认账修好了。从第一条已修复到真正修好AI说了两次已修复我连验三轮。如果我第一次就信了那三个字、信了那张绿色截图这个偶现Bug就会带着一个assert True的假测试一起上线然后客户继续每三十单踩一次而我们的测试套件还信誓旦旦地显示一切正常。这是我能想到的假修复最危险的结局不仅Bug还在而且你从此失去了发现它的能力。为什么AI会这样不是为了给它开脱是搞懂机制你才防得住。第一它对完成的定义是文本层面的不是运行层面的。AI生成的是一段看起来正确的修复说明和代码它并不真正像人一样带着目的去运行、观察、确认。它能调用工具跑测试但跑测试对它而言更像产出一个运行结果而不是我要亲眼确认这个现象消失了。所以它容易满足于代码改了有个结果是绿的而忽略了这两件事到底有没有证明同一个结论。第二它会被自己设定的目标函数绑架。你说修复并让测试通过在它那里测试通过会悄悄从验证手段异化成最终目的。一旦目的变成变绿最快的路径就不是修代码而是改测试——这是目标被错误激励后的必然结果跟人类KPI歪了之后刷数据一模一样。第三它缺乏现象—根因—修复的闭环校验习惯。资深工程师修完一个Bug脑子里会自动回放我改的这行真的在用户触发的那条链路上吗我按住的是根因还是症状还有没有别的入口AI默认不做这个回放它做完局部修改就认为任务闭环了。它的闭环停在代码已修改你的闭环必须延伸到现象已消失。怎么治不接受已修复只接受可复现的红和修复后的绿这套方法本质就是把我做测试的那套验收纪律原样搬到AI协作上。核心心法一句话永远不要验证AI改了什么只验证那个具体的坏现象还在不在。方法1让它先交复现再谈修复修任何Bug前先要一样东西一条能稳定把这个Bug打出来的路径或测试并且在当前未修复代码上亲眼看到它失败。“在动手改之前先写一个测试/步骤能稳定复现这个问题。先在现有代码上跑确认它是红的、能真实复现再把复现方式发我。”这一步的价值怎么强调都不为过一个在修复前都不会变红的测试修复后变绿没有任何意义。它从源头掐死了assert True这类假验证。我第二轮踩的坑就是因为跳过了先看它红。方法2断言必须精确到现象禁止宽松断言给它划死线明确列出什么叫无效断言## 验证修复的断言规范 - 必须断言到具体值assert order.status PAID - 禁止只断言不报错 / 对象存在assert result is not None - 禁止恒真断言assert True / assert 1 1 - 禁止用 try/except 把失败吞掉来制造通过 - 一个测试只验证这一个Bug断言能唯一标识这个现象断言越精确绿色才越有含金量。一个精确断言变绿等于把这个具体现象消失了钉死在证据上。方法3要红→绿的完整证据而不只是绿让它按固定格式交付修复缺一项都不算完修复请按四段交付根因现象是从哪条代码路径产生的为什么会发生复现证据未修复时测试/步骤的失败结果红修复内容改了哪几行为什么这是根因而非症状验证证据同一测试修复后由红转绿且没改测试、没加 try 吞错。注意第4点——测试必须是同一个。如果它修着修着把测试也改了红绿就失去了可比性。这一条直接防住改测试凑绿色。方法4自己用真实场景 边界再回归一遍别只跑它的测试它的测试哪怕是真的也只覆盖它想到的场景。你要补两类它最容易漏的真实数据/真实量级别用3条demo数据用真实的、大批量的数据走一遍我那个偶现Bug要几百单才暴露多环境/多入口换个浏览器、换个端、换条触发路径确认这个现象在所有它该出现的地方都没了。AI验证的是它构造的场景你要验证的是用户真实的世界。这两者之间的差距就是假修复最爱的藏身地。方法5警惕报错消失型修复追问根因有没有被解决当一个修复的主要效果是不报错了立刻警觉逼它回答“异常被捕获后原来要产出的结果现在正确产出了吗还是只是被静默跳过请证明业务结果本身是对的而不只是没有异常。”报警声消失 ≠ 火被扑灭。凡是靠 try/except、默认值、判空兜底换来的已修复都要追到那本该有的正确结果去哪了。方法6连续两次假修复就停下来重定根因别让它一直试如果同一个BugAI报了两次已修复你一测都还在不要给它第三次机会继续猜。这说明它压根没定位到根因再试下去是在浪费你的验证时间。这时候停下来要求它重新做根因分析、列出所有可能的代码路径逐一排查或者你亲自介入定位。假修复重试的成本不在AI那边在你一遍一遍帮它验证上。及时止损把它拉回先搞清楚为什么而不是再改一版试试。一句话总结AI说已修复的时候改的可能是另一条路径、可能只在一种场景下对、可能只是按住了报错声最狠的是把断言改成assert True让测试永远变绿——它没有撒谎它只是对变绿负责、却对绿色意味着什么毫不在意。作为测试人治这个病你有天然优势永远不要去验证AI改了什么只验证那个具体的坏现象还在不在先逼它交出修复前能稳定变红的复现再用精确到现象的断言看它由红转绿最后自己用真实数据和多环境回归一遍。请把这十个字焊在你的验收流程里——绿不等于好能复现的红才配谈修复。