← 返回 2026-02-12

重新审视 LLM 软件工程智能体中自动生成测试的价值 Rethinking the Value of Agent-Generated Tests for LLM-Based Software Engineering Agents

Zhi Chen, Zhensu Sun, Yuling Shi, Chao Peng, Xiaodong Gu, David Lo, Lingxiao Jiang 📅 2026-02-08 👍 4 2026-07-13 08:35
LLM SWE-bench 代码智能体 自动化测试 软件工程

智能体自发编写的测试主要是观察性调试工具,而非驱动任务成功的关键因素

前置知识

Code Agent(代码智能体)

由大型语言模型(LLM)与外部工具组合而成的自动化软件开发系统。它通过迭代的'动作-观察'循环与代码仓库交互:模型生成推理和操作指令,通过 bash 等工具执行代码编辑、文件操作、测试运行等动作,然后观察执行结果并据此决定下一步操作。这种架构使得智能体能够像人类开发者一样逐步探索和修改代码库,解决仓库级别的 GitHub issue。在本文中,智能体使用 mini-SWE-agent 这一轻量级脚手架,仅通过 bash 工具与仓库交互,测试编写完全可选。

理解代码智能体的交互模式是本文分析的基础——论文研究的正是这类智能体在解决 issue 过程中自发编写测试的行为及其价值。

SWE-bench Verified

一个基于真实 GitHub issue 的代码智能体评估基准。它从 12 个开源 Python 仓库中抽取 500 个已解决的 GitHub issue,每个实例提供一个 issue 描述、一个固定的仓库快照和官方评估工具。智能体需要根据 issue 描述自动生成代码补丁(patch),然后由官方评估工具判断补丁是否能成功解决问题。该基准经过 OpenAI 与 SWE-bench 作者合作的人工筛查,是当前衡量代码智能体解决真实软件问题能力的标准测试集。

本文的所有实验都在 SWE-bench Verified 上进行,理解这个基准的任务结构(issue → 补丁 → 评估)对于解读论文中的成功率数据至关重要。

Agent-Written Tests(智能体编写测试)

智能体在解决 issue 过程中自发创建的测试文件,这些测试在原始代码库中并不存在。与仓库中已有的、由人类开发者编写的测试不同,智能体编写的测试是临时性的,反映了模型对问题规范、领域知识和目标代码库语义的理解。它们可以通过断言(assertion)验证具体行为,也可以通过 print 语句暴露运行时值。测试的可靠性取决于模型的判断能力——好的测试能暴露边界情况和提供有价值的反馈,差的测试可能嵌入错误假设,误导调试方向。

这是本文的核心研究对象。论文的核心问题就是:这些智能体自发编写的测试到底有没有用?是真正在帮助解决问题,还是只是一种习得的软件开发惯例在消耗交互预算?

Value-Revealing Prints(值揭示型 print 语句)

智能体在测试代码中使用的 print 语句,用于在运行时暴露程序的计算值、中间结果或执行状态。与断言(assertion)不同,print 语句不会自动判定'通过/失败',而是将运行时信息呈现给智能体作为观察性反馈。例如 print(add(1, 2)) 用于检查函数输出,print(len(items)) 用于查看数据规模,except Exception as exc: print(exc) 用于捕获异常信息。本文发现这些 print 语句在智能体编写的测试中数量远超断言,是测试反馈的主要来源。

论文的一个核心发现是智能体测试的价值主要体现在观察性反馈(print 语句)而非验证性检查(断言),这一概念直接支撑了论文的核心论点。

Prompt Intervention(提示词干预)

通过修改智能体的系统提示词来改变其行为模式的实验方法。在本文中,研究者对原始 mini-SWE-agent 提示词进行小幅定向编辑,创建'鼓励编写测试'和'阻止编写测试'两个变体,然后在同一脚手架下比较行为变化和结果差异。这种方法的优势在于保持智能体架构不变,仅通过提示词变化来隔离测试编写行为的影响,从而观察测试编写量的增减是否与任务成功率变化相关。

RQ3 的核心实验设计,用于回答'更多测试是否意味着更多成功'这一因果问题,是论文最具实践意义的发现来源。

研究动机

当前 LLM 代码智能体在解决仓库级别的 GitHub issue 时,一个普遍做法是在问题解决过程中自发编写测试——但这些测试的真实价值一直不明确。一个引人注目的矛盾现象是:GPT-5.2 几乎不写任何新测试(仅在 0.6% 的任务中编写),却达到了 71.8% 的解决率;而 Claude Opus 4.5 在约 83% 的任务中编写至少一个测试文件,解决率仅高出 2.6 个百分点(74.4%)。这一观察直接挑战了'测试越多越好'的直觉。先前的研究大多在固定的测试目标和预定义的质量指标下评估 LLM 生成的测试,例如针对固定目标程序的单元测试覆盖率、变异分数或断言质量。但在真实的 GitHub issue 解决场景中,代码库和候选补丁是动态演化的,测试编写和使用是智能体的自发行为而非预设的评估目标。这种动态、自组织的测试行为在之前的研究中几乎未被系统性地研究过。

本文的目标是本文的目标是系统性地回答三个互补的研究问题:第一,当测试编写是可选的(而非强制的)时,智能体的测试行为模式是什么——它们是否编写测试、何时编写、执行强度如何?第二,当智能体确实编写测试时,这些测试提供了什么样的反馈信号——是验证性的断言还是观察性的输出?第三,通过提示词干预来增加或减少测试编写,能否改变最终的任务解决结果和效率成本?更具体地说,论文希望通过量化分析来判断智能体编写的测试究竟是一种有价值的技术手段,还是一种消耗交互预算的'习惯性软件开发惯例'。

与已有工作不同的是,本文的独特切入点在于将智能体编写的测试视为一种'过程行为'而非'产品质量指标'来研究。先前的工作主要关注 LLM 生成测试的静态质量(覆盖率、变异分数等),但本文关注的是测试在智能体问题解决过程中的动态角色。更关键的是,论文引入了一个控制变量实验:通过提示词干预来操控测试编写行为,观察同一脚手架下行为变化与结果变化之间的关系。这种实验设计使得论文能够超越相关性描述,接近因果推断。此外,论文将测试中的反馈信号区分为验证性断言(assertion)和观察性打印(value-revealing print),并对二者进行了细粒度分类,这在之前的工作中从未被系统性地分析过。

核心方法

论文的研究方法可以用一个类比来理解:想象一个程序员在解决 bug 时,有时会写测试用例来验证自己的修复,有时则直接检查代码就提交。问题是:这个程序员写测试的习惯到底有没有帮助他更好地解决问题?本文的研究设计就像是给六位风格各异的高级程序员(六个 LLM)分配相同的 500 个 bug 修复任务,然后仔细观察他们的工作过程。研究者使用轻量级的 mini-SWE-agent 脚手架,让测试编写完全可选,从而观察每个模型的'自然'测试行为。然后通过 AST 解析提取测试文件中的断言和 print 语句,进行分类统计。最后通过提示词干预实验,人为地让某些模型多写测试或少写测试,观察结果变化。整个研究分为三个层次递进的研究问题:行为描述(RQ1)→ 信号分析(RQ2)→ 干预实验(RQ3)。

本文最核心的发现是:智能体编写的测试最好被理解为一种'模型依赖的过程风格'(model-dependent process style),而非任务成功的可靠驱动因素。这一判断建立在三组证据之上:第一,同一模型在已解决和未解决的任务中,测试编写频率高度相似(差异不超过 6 个百分点),说明测试编写与成功之间没有强关联;第二,当测试被编写时,值揭示型 print 语句在数量上一致地超过断言(每个任务中 print 平均是断言的 3-7 倍),表明测试主要充当观察性调试工具而非验证性检查;第三,通过提示词干预大幅改变测试编写行为后,任务成功率几乎不变(所有模型的 McNemar 检验 p 值均 > 0.05),但效率指标(API 调用次数、token 使用量)可以发生显著变化。这三个层面的证据共同指向一个结论:更多测试不等于更多成功,测试主要改变的是过程脚印而非结果。

方法步骤详情

研究方法分为三个递进阶段。第一阶段(RQ1:测试行为描述)使用 mini-SWE-agent 脚手架在 SWE-bench Verified 上运行六个 LLM(Claude Opus 4.5、Gemini 3 Pro、GPT-5.2、Kimi K2 Thinking、MiniMax M2、DeepSeek v3.2 Reasoner),记录每个任务的交互轨迹。通过扫描 bash 操作日志,提取符合 Python 测试命名模式的文件(以 test_ 开头或以 _test.py、tests.py 结尾),统计每个任务是否编写测试、编写了多少测试文件、何时开始和结束编写、执行了多少次测试。第二阶段(RQ2:反馈信号分析)对提取的测试文件进行 Python AST 解析,将断言分为四类(C1 健全性检查:检查存在性或类型;C2 属性检查:检查值的属性;C3 关系检查:检查范围或约束;C4 精确检查:检查精确值),将值揭示型 print 语句分为三类(P1 值/内容检查;P2 结构摘要检查;P3 异常/状态信号)。第三阶段(RQ3:干预实验)创建提示词变体,对低测试编写模型(GPT-5.2 和 Gemini 3 Pro)鼓励编写测试,对高测试编写模型(Kimi K2 Thinking 和 DeepSeek v3.2 Reasoner)阻止编写测试,比较基线与干预条件下的任务成功率和效率指标。

技术新颖性

本文的技术新颖性体现在多个层面。首先,在研究视角上,不同于以往将 LLM 生成测试视为独立产品质量问题的工作,本文首次将测试编写视为智能体问题解决过程中的'涌现行为'来系统性研究,关注的是测试在实际工作流中的动态角色。其次,在信号分析上,论文创新性地区分了验证性断言和观察性 print 语句,并设计了基于 AST 的规则化分类器,将断言映射为四级分类(从健全性检查到精确值检查),将 print 语句映射为三类(值检查、结构摘要、异常信号),这种细粒度的信号分析在之前的工作中从未出现。第三,在实验设计上,通过仅修改提示词来操控测试编写行为,保持脚手架和模型不变,使得研究能够在控制混杂变量的前提下观察测试编写与结果之间的关系,这比简单的相关性分析更接近因果推断。

研究设计概览
Figure 1: 研究设计概览

实验结果

实验结果呈现出一个清晰的模式:智能体编写的测试是一种过程风格,而非成功驱动因素。在 RQ1(测试行为)方面,六个模型的测试编写率差异巨大:MiniMax M2 在 98.6% 的任务中编写测试,Kimi K2 Thinking 为 97.4%,Claude Opus 4.5 为 83.0%,DeepSeek v3.2 Reasoner 为 89.2%,Gemini 3 Pro 为 61.6%,而 GPT-5.2 仅为 0.6%(仅 3 个任务)。但同一模型在已解决和未解决任务中的测试编写率高度相似,差异不超过 6 个百分点。当测试被编写时,未解决任务往往编写更多测试文件(平均 4.12 vs 3.33 个,以 Claude 为例),这可能反映了更困难的任务触发了更多试错。在测试执行方面,未解决任务执行测试更频繁(平均执行次数 6.52 vs 4.89),且执行失败率因模型而异(7% 到 30%)。在 RQ2(反馈信号)方面,值揭示型 print 语句一致地超过断言:Claude Opus 4.5 每个任务平均 25.00 个 print vs 5.16 个断言,MiniMax M2 为 37.6 vs 6.3。断言以属性检查(C2,33%-41%)和精确值检查(C4,34%-43%)为主,关系检查(C3)极少(3%-8%)。print 语句以值/内容检查(P1)为主导(70%-78%),异常/状态信号(P3)为第二(19%-25%)。在 RQ3(干预实验)方面,鼓励测试编写使 GPT-5.2 在 64.4% 的任务中从'无测试'变为'有测试',但成功率未变(均为 71.8%),API 调用增加 5.5%,输出 token 增加 19.8%。阻止测试编写使 Kimi K2 Thinking 在 68.4% 的任务中从'有测试'变为'无测试',成功率仅下降 2.6%,但输入 token 减少 49.0%,API 调用减少 35.4%。四个模型的 McNemar 检验均不显著(p > 0.05),表明提示词诱导的测试编写量变化对最终结果没有统计学上显著的影响。

各模型按执行结果的测试编写率
Table 1: 各模型按执行结果的测试编写率
智能体编写测试中的任务级反馈信号量
Table 4: 智能体编写测试中的任务级反馈信号量
测试状态翻转与结果转换矩阵
Table 7: 测试状态翻转与结果转换矩阵
基线 vs 干预条件下的 API 调用和 token 使用量
Table 8: 基线 vs 干预条件下的 API 调用和 token 使用量
测试状态改变后的结果转换分布
Figure 3: 测试状态改变后的结果转换分布
查看结构化数据
任务指标本文基线提升
SWE-bench Verified(基准解题率) Resolution Rate Claude Opus 4.5: 74.4%, Gemini 3 Pro: 74.2%, GPT-5.2: 71.8% Kimi K2-T: 63.4%, MiniMax M2: 61.0%, DeepSeek v3.2-R: 60.0% 前三名模型解决率均超过 71%,GPT-5.2 在几乎不写测试的情况下仅低 2.6pp
GPT-5.2 鼓励测试干预 Resolution Rate 71.8%(干预后) 71.8%(基线) +0.0pp(无提升),API 调用 +5.5%,输出 token +19.8%
Gemini 3 Pro 鼓励测试干预 Resolution Rate 73.2%(干预后) 74.2%(基线) -1.0pp(轻微下降),差异不显著
Kimi K2 Thinking 阻止测试干预 Resolution Rate 60.8%(干预后) 63.4%(基线) -2.6pp(轻微下降),但输入 token 减少 49.0%,API 调用减少 35.4%
DeepSeek v3.2 Reasoner 阻止测试干预 Resolution Rate 58.2%(干预后) 60.0%(基线) -1.8pp(轻微下降),但输入 token 减少 32.9%,输出 token 减少 14.0%

局限与改进

论文承认了多项局限性。在内部有效性方面,智能体运行受到随机解码和工具/环境不确定性的影响,测试行为和解决结果都可能因此变化。此外,成功与失败的比较可能反映任务难度或交互长度的差异,而非测试本身的效果。作者通过将观察结果视为描述性的、使用仅修改提示词的干预方法、以及报告任务级别的结果转换矩阵来缓解这些担忧。在外部有效性方面,发现基于 SWE-bench 和特定模型集合,绝对数值可能在其他基准、编程语言或工具链下有所不同。从我的观察来看,论文的提示词干预相对简单(仅添加或移除测试相关的自然语言指令),更复杂的测试策略提示(如'先写测试再写代码'或'用测试驱动开发')可能产生不同结果。此外,论文仅分析了 Python 项目,智能体编写的测试在其他语言中的行为模式可能不同。论文未评估测试质量(如覆盖率、变异分数),仅关注测试的存在与否和反馈信号类型,这意味着即使是'高质量'的测试也可能因其他原因未被有效利用。

独立分析的弱点

论文的第一个弱点是测试质量的评估缺失。论文仅分析了测试是否被编写以及反馈信号的类型,但未评估这些测试的实际质量——例如测试覆盖率、是否真正检查了与 issue 相关的行为、是否引入了错误的断言。一个低质量的测试可能比没有测试更糟糕,因为它可能误导智能体。改进方向是引入测试质量评估指标,例如测试是否成功复现了 issue 描述的问题、测试的变异杀伤力(mutation score)等。第二个弱点是提示词干预的设计较为粗糙。'鼓励编写测试'和'阻止编写测试'是极端的二元干预,未探索更精细的策略,例如'编写一个最小的回归测试'或'只对修改的函数编写测试'。这种更精细的干预可能揭示测试在特定条件下的价值。第三个弱点是论文仅关注了 SWE-bench Verified 中的 Python 项目,且所有项目都是成熟的开源项目。在更小的代码库、不同的编程语言、或企业内部项目中,智能体测试行为的模式和价值可能不同。改进方向是扩展到多语言基准和不同规模的项目。

未来方向

论文提出了两个有前景的未来研究方向。第一,开发适合非稳态代码状态的测试质量评估指标。传统测试指标(覆盖率、变异分数等)假设系统快照是固定的,但在智能体开发中,测试是针对中间版本编写的,后续可能被覆盖。未来需要开发在执行时间点对瞬态工件仍有意义的指标。第二,自演化测试生成策略——智能体从环境反馈和失败模式中修正自己的测试策略,而非遵循静态的手写提示词。这可以被形式化为成本和安全约束下的闭环优化问题。基于论文的发现,我还可以延伸出以下方向:研究测试编写在多智能体协作场景中的价值——当一个智能体编写测试而另一个智能体使用测试结果时,测试的信号传递效率可能不同;研究'测试预算'的最优分配——在固定的交互预算下,多少比例应该分配给测试编写和执行,才能最大化解决率;以及研究不同类型 issue(错误修复 vs 功能添加 vs 性能优化)对测试敏感性的差异,论文的探索性分析已识别出 8 个可能对测试敏感的候选 issue。

复现评估

论文提供了良好的复现条件。作者在论文中明确提到提供了一个匿名的 Zenodo 复制包(DOI: 10.5281/zenodo.19251470),包含数据集、原始轨迹、提示词文件和分析脚本。所有实验使用官方 mini-SWE-agent 代码库,评估使用官方 SWE-bench sb-cli 工具。硬件要求是 Linux 服务器(Ubuntu 22.04.5)配合 AMD Ryzen Threadripper PRO 7975WX CPU(32 核 / 64 线程)和 251 GiB RAM。模型推理通过官方 API 和 OpenRouter API 访问,全部实验的 LLM API 成本约为 1,600 美元。复现的主要挑战在于 API 成本较高(需要运行 500 个任务 x 6 个模型 x 多个提示词变体),以及模型版本的时效性(GPT-5.2、Claude Opus 4.5 等模型可能更新)。提示词干预的具体文本保存在 experiment_prompts 文件夹中,便于精确复现。总体而言,复现难度中等偏高,主要瓶颈在于 API 成本而非技术复杂性。