测试全绿,评审翻车:为什么「功能过了」不等于「代码能合入」
编者按:掘金作者 lucas_AI 结合论文 SWE-Gate,讨论代码评审约束为何无法被功能测试替代。下文保留原作论述结构,已做精简;不涉及未公开公司与个人隐私。
你有没有经历过这种事:辛辛苦苦把 bug 修好了,单测全绿,提 PR 想发版,结果维护者一句「方案不错,但你这样改会破坏旧接口」——打回。
这就是代码 agent 每天面对的世界的缩小版。
过去两年,衡量代码 agent 好不好用,几乎只看一个指标:能不能让测试变绿。SWE-bench 就是从真实 GitHub issue 出发,让 agent 修 bug,修完跑功能测试,过了就算赢。但真实世界里的「修好一个 bug」,从来不是「测试过了」就行——代码评审那关才是决定补丁能不能合入的裁判。评审会说什么?
「这样改会把旧 API 弄坏,保持向后兼容」
「这个函数原来抛布尔值代表两种情况,你别把语义改了」
「咱仓库的约定是异常集中处理,别在业务层 try-catch」
这些要求,功能测试根本测不出来。今天这篇论文,就是来补这个洞的。
TL;DR
SWE-Gate 从 75 个开源 Python 仓库的真实代码评审意见里,提炼出「验收约束」(比如向后兼容、保留异常语义、遵守仓库约定),做成 303 个修复任务。它把评测拆成两个独立维度——功能正确和约束服从——每个实例都配了两套测试。
结论很扎心:644 个通过功能测试的补丁里,有 221 个(34.3%)违反了评审约束。也就是说,光看功能测试,代码 agent 的真实水平会被系统性高估约三分之一。
问题出在哪:SWE-bench 只测了「半个答对」
SWE-bench 够真实、够客观,但有个天生盲区:一个补丁能合入,除了修好 bug,还要过代码评审。评审里提的向后兼容、异常语义、项目惯例,在它的评分体系里完全不存在。
论文举了 Pydantic 的例子:有人给额外字段序列化加开关,初版功能完全对,但评审认为改公共接口属于破坏性变更;最后加了参数才合进去。「功能修好了」和「功能修好且过了评审」是两码事。论文管前者叫 functional success,管后者叫 joint success——中间隔着的,就是那些「隐藏失败」。
SWE-Gate 怎么做:把评审意见变成可执行测试
从真实评审里抽「约束种子」,过滤掉风格、格式等难验证意见,只留能构造反例补丁的约束。
把约束移植到兼容仓库再造题,并跑通校验。
同一问题出两套测试:功能测试测 issue 修没修好,约束测试测评审约束满不满足;再配「能过功能但违反约束」的非合规补丁,以及两套都过的黄金补丁。
结果:34.3% 的「修好了」其实是「没通过」
投入多个模型、同一 agent 框架跑 303 题后,合计 644 个功能成功里,423 个真正过评审,221 个隐藏失败,隐藏失败率 34.3%。最强模型功能成功率接近 75%,照样有一大批补丁过不了约束关。
最容易翻车的约束类型包括:范围泛化、资源生命周期清理、编码转义——这些要求覆盖面超出眼前这个 bug,或要把资源和异常管到收尾。相对容易的是哨兵区分、参数顺序保留等更接近语法层面的约束。
对照组还发现:把评审约束用自然语言写进提示,联合成功率会涨,但功能成功率可能微降——多一条验收标准,补丁更复杂,agent 会把精力分到「满足约束」上。
这事对你有啥用
用代码 agent 提效时:SWE-bench 高分不等于能直接合入。给 agent 的提示里写清兼容性、异常语义、仓库约定,有助于提高「能过评审」的概率,但也要自己盯核心改动。
跟 agent 协作时:下次它说「测试都过了」,可以多问一句——「评审会怎么看你这个补丁?」
说明:文中实验数据与案例均转述自原文对 SWE-Gate 论文的介绍,不代表对特定公司内部流程的披露。
来源
原作者:lucas_AI
原文:测试全绿,评审翻车:为什么「功能过了」不等于「代码能合入」,掘金,2026年9月10日。
#CodeReview #代码评审 #SWE-Gate #合入 #经验分享
成为第一条评论!
Nobody's responded to this post yet. Add your thoughts and get the conversation going.