智测 OpenQA

行业与实践研究与基准测试

评估并缓解含缺陷代码对大语言模型生成单元测试的误导效应(上篇)

智测团队 · OpenQA(openqa.cn)阅读约 31 分钟

尽管大语言模型(Large Language Models, LLMs)在自动化单元测试生成方面展现出巨大潜力,近期研究指出:当提示中给出的是含缺陷代码时,所生成测试的质量会受到负面影响。本文提出一项新指标,用于定量度量

本文目录

评估并缓解含缺陷代码对大语言模型生成单元测试的误导效应(中文全译·上篇)

翻译说明:本文是 arXiv 论文 Evaluating and Mitigating the Misguidance Effect of Buggy Code in LLM-Generated Unit Tests(arXiv:2607.22883)的中文全译,由智测团队翻译。原作者:Junda Zhao(多伦多大学机械与工业工程系,加拿大多伦多;junda.zhao@mail.utoronto.ca)、Shurui Zhou(多伦多大学电气与计算机工程系,加拿大多伦多;shurui.zhou@utoronto.ca)、Eldan Cohen(多伦多大学机械与工业工程系,加拿大多伦多;eldan.cohen@utoronto.ca)。原文以 CC BY 4.0 许可发布。译文保留原文全部章节、数据与结论;参考文献列表从略。

本文超长,分上下两篇。下篇:https://openqa.cn/articles/buggy-code-misguidance-tests-zh-part2

DOI: 10.1145/3832204 期刊: PACMSE,第 3 卷(ISSTA) 收稿日期: 2026-06-25 arXiv: 2607.22883v1 [cs.SE],2026 年 7 月 24 日 CCS 概念: 软件及其工程——软件测试与调试;软件及其工程——自动编程;软件及其工程——经验性软件确认;计算方法论——自然语言生成

关键词: 单元测试生成、大语言模型、基于规约的测试、软件测试、缺陷检测

摘要

尽管大语言模型(Large Language Models, LLMs)在自动化单元测试生成方面展现出巨大潜力,近期研究指出:当提示中给出的是含缺陷代码时,所生成测试的质量会受到负面影响。本文提出一项新指标,用于定量度量「误导效应」(misguidance effect)——即含缺陷代码会把大语言模型引向生成验证其错误行为、而非揭露该错误行为的测试。分析表明,用含缺陷代码提示大语言模型会造成严重的双重影响:它显著增加断言错误行为的「被误导测试」,同时抑制有效的、能够发现缺陷的测试生成。我们进一步从模型内部视角印证这一效应,表明含缺陷代码会使大语言模型更偏好那些断言同一错误行为的测试。为应对该问题,我们提出并验证了一种基于规约的单元测试生成范式:用大语言模型生成的规约文档字符串(docstring)替换提示中的被测代码。结果表明,该范式能有效减少被误导测试,同时大幅增加有效测试;能改进多轮、由反馈驱动的测试生成流水线;并且对含缺陷代码与无缺陷代码均适用。总体而言,这些结果说明,基于规约的提示是缓解含缺陷代码对大语言模型所生成单元测试之误导的一种有前景的策略。

1. 引言

单元测试在软件质量保证中起着关键作用,用于验证各个组件的行为是否符合预期(Sommerville, 2011)。通过在开发生命周期的早期发现缺陷,单元测试有助于降低维护成本、便于重构,并提高软件的整体可靠性(Wang 等, 2024a)。尽管有这些益处,手工编写测试仍然费时且容易出错,因而推动了测试过程自动化的努力(Daka 与 Fraser, 2014)。

大语言模型的近期进展催生了 GPT(OpenAI, 2024)、DeepSeek(DeepSeek-AI, 2025b)和 Claude(Anthropic, 2024a)等强大模型。这些模型在一系列代码相关任务上展现出令人印象深刻的能力,并促使多项近期研究专注于利用并评估它们在自动化单元测试生成中的表现(Chen 等, 2024;Yuan 等, 2024;Dakhel 等, 2024;Yang 等, 2024b;Schäfer 等, 2024)。

现有关于基于大语言模型的单元测试生成研究,大多以无缺陷代码作为主要提示输入,并常常依赖测试正确性与覆盖率等指标(Chen 等, 2024;Yuan 等, 2024;Dakhel 等, 2024;Yang 等, 2024b;Schäfer 等, 2024)。这些指标并不能直接反映所生成测试的缺陷检测有效性(Inozemtseva 与 Holmes, 2014)。然而,这种常见实验设计未能反映真实场景:被测代码往往含有缺陷,这可能对所生成测试套件的有效性产生负面影响。迄今只有少数工作把含缺陷代码作为输入:Abdullin 等(Abdullin 等, 2025)报告了从含缺陷源码生成测试时的缺陷检测有效性;Mathews 等(Mathews 与 Nagappan, 2024)认为,含缺陷代码会妨碍自动测试生成系统发现其自身缺陷;He 等(He 等, 2025)发现,在迭代式代码—测试生成中,由先前迭代生成的含缺陷代码所导出的测试,可能会强化代码中已有的缺陷。尽管这一认识正在出现,这些研究既没有相对于无缺陷代码输入量化性能下降,也没有确立这种性能下降的根本来源。

Huang 等(Huang 等, 2025)的一项近期研究试图定量度量含缺陷代码在生成单元测试时误导大语言模型的程度——即导致模型把含缺陷代码的错误行为当作预期功能,并生成验证该行为的测试。然而,他们用于量化这一误导效应的指标存在关键局限:它把所有在含缺陷版本上通过的测试都标为「被误导」。实践中,含缺陷代码在许多输入上的行为往往与正确代码相似,只在触发缺陷的特定输入上才有差异。事实上,正如我们在第 2 节中的经验结果所示,为含缺陷代码生成、且在含缺陷版本上成功通过的测试中,大多数也会在其修复后的对应版本上通过。这表明 Huang 等提出的指标未能准确刻画误导现象的存在与程度。

无缺陷方法

public static boolean equals(
 CharSequence cs1, CharSequence cs2){
 if (cs1 == cs2) return true;
 if (cs1 == null
 || cs2 == null) return false;
 if (cs1 instanceof String
 && cs2 instanceof String)
 return cs1.equals(cs2);
 return CharSequenceUtils
 .regionMatches(cs1, false, 0, cs2, 0,
 Math.max(cs1.length(), cs2.length()));
}

含缺陷方法

public static boolean equals(
 CharSequence cs1, CharSequence cs2){
 if (cs1 == cs2) return true;
 if (cs1 == null
 || cs2 == null) return false;
 return cs1.equals(cs2);
}

由含缺陷方法生成的文档字符串

/**
 * Compares two CharSequence instances for
 * equality, handling null inputs safely.
 *
 * This method provides a null-safe, case-
 * sensitive comparison. Two CharSequence
 * objects are considered equal if they re-
 * present the same sequence of characters.
 * The method is designed to work with any
 * CharSequence implementation, such as
 * String, StringBuilder, or StringBuffer.
 */

由无缺陷方法生成的测试

@Test
public void testEquals_sb() {
 assertTrue(StringUtils.equals("abc",
 new StringBuilder("abc")));
} // 测试断言的是正确行为 ✓

被误导的测试

@Test
public void testEquals_sb() {
 assertFalse(StringUtils.equals("abc",
 new StringBuilder("abc")));
} // 测试断言的是含缺陷行为 ✗

仅由文档字符串生成的测试

@Test
public void testEquals_sb() {
 assertTrue(StringUtils.equals("abc",
 new StringBuilder("abc")));
} // 测试断言的是正确行为 ✓

图 1. 由含缺陷代码生成、断言其缺陷行为的「被误导测试」示例,以及由含缺陷代码生成的文档字符串如何纠正这一行为并产出能够发现该缺陷的测试。上排为给大语言模型的主要输入,下排为相应生成的测试。高亮文本标出代码输入与所生成测试之间的关键差异。图中并排比较了 StringUtils.equals 的无缺陷实现与含缺陷实现、由含缺陷代码生成的文档字符串,以及由各输入生成的测试:由含缺陷代码生成的测试断言的是缺陷行为,而基于文档字符串的测试发现了该缺陷。

为弥补这些不足并准确量化误导效应,我们开展了一项大规模经验研究,采用一项新指标,显式度量「被误导测试」——定义为在含缺陷版本上通过、但在其无缺陷对应版本上失败的测试。图 1 以 Defects4J 中缺陷 Lang-14 的 StringUtils.equals 为例,给出被误导测试的动机示例。该方法旨在比较两个 CharSequence 对象的内容;CharSequence 是由 String、StringBuilder 和 StringBuffer 实现的 Java 接口,因此 "abc" 与 new StringBuilder("abc") 尽管具体类型不同,仍应被视为相等。无缺陷实现使用 regionMatches 处理这一情形,而含缺陷实现直接调用 cs1.equals(cs2)。由于 String.equals 仅当其参数同样是内容相同的 String 时才返回 true,在比较 String 与 StringBuilder 时它会错误地返回 false。当以这一含缺陷实现作为提示时,大语言模型把错误行为当作预期行为,并生成断言该错误行为的测试。

为计算这一新指标,我们利用由真实世界含缺陷代码片段及其修复版本构成的平行数据集,从而度量在预期功能相同的情况下,测试结果在含缺陷代码与无缺陷代码上有何不同。通过生成测试并在两个版本上执行,我们揭示了一种关键的双重影响:相对于修复后的对应版本,用含缺陷代码提示大语言模型会显著增加「被误导测试」,同时抑制「有效测试」——即成功识别该缺陷的测试。此外,相关分析表明,被误导测试的减少与有效测试的增加之间存在强正相关,提示缓解误导效应可能带来更有效的测试套件。为从模型内部视角验证误导效应,我们还分析了序列得分(sequence score)——一种度量大语言模型对候选文本偏好的常用指标(Brown 等, 2020;Mitchell 等, 2023;Holtzman 等, 2020),并表明含缺陷的输入代码会使这一偏好偏向于断言其错误行为的测试。我们进一步表明,这种有害效应会延伸到更先进的技术,削弱近期测试生成工作中常见的多轮、由反馈驱动的提示流水线(Yuan 等, 2024;Jain 与 Le Goues, 2025;Chen 等, 2024)。

基于上述发现,我们认为,用被测代码提示大语言模型这一主流范式存在根本局限:当代码含有缺陷时,其误导效应会把模型引向生成断言那些本应被揭露之行为的测试。为缓解这一效应,我们借鉴基于规约的测试(Gao 等, 2003)(黑盒测试)原则。该原则在测试驱动开发(Test-Driven Development, TDD)(Beck, 2002)中被广泛采用,即从预期行为而非实现导出测试。我们提出两步工作流:(1)使用大语言模型导出一份文档字符串,捕捉预期功能并省略实现细节;(2)用该文档字符串替换提示中的源代码,从而去除作为误导来源的含缺陷实现。这一设计选择至关重要:对于含缺陷输入,我们发现必须把代码完全移除,而不是仅仅加以补充,才能有意义地缓解误导。这有别于先前仅把大语言模型生成的文档作为代码旁的额外上下文的研究(Yuan 等, 2024)。图 1 也在同一 StringUtils.equals 示例上说明了这一做法:当大语言模型生成的文档字符串替换测试生成提示中的含缺陷代码时,所生成的测试正确地断言 "abc" 与 new StringBuilder("abc") 应被视为相等,从而暴露该缺陷。值得注意的是,即便简单的规约构造提示也能产出明显更有效的测试套件;我们进一步用一个由分析驱动的意图推导步骤加强这一基线,以产生更准确的规约,从而进一步减少被误导测试、增加有效测试,且不会大幅增加那些断言既不存在于含缺陷代码、也不存在于修复后代码中的幻觉行为的测试。我们基于规约的方法也能提升近期工作所采用的交互式、多轮测试生成流水线的性能(Chen 等, 2024;Yuan 等, 2024;Jain 与 Le Goues, 2025)。我们还人工检查所生成文档字符串的质量,并量化其对所得测试的影响,表明我们的方法能有效阻止缺陷传播到所生成的文档字符串中,并为一大部分含缺陷焦点方法恢复正确行为。前者使被误导测试套件显著减少,后者则贡献了大幅更多的被发现缺陷,支持了我们的设计直觉,并凸显出需要能够从含缺陷代码重构出更准确规约的方法。总体而言,这些结果确认:我们基于规约的方法在缓解误导效应方面是有效的。

最后,由于往往并不知道被测代码是否确实含有缺陷,我们表明该方法可同时应用于含缺陷代码与无缺陷代码。在无缺陷代码上,相对于以源代码为输入的基线,它产生的编译失败、误报测试(在正确代码上失败的测试)和测试覆盖率水平相当,不会给开发者增加额外负担,同时使所生成测试仍可用于回归测试等更广泛用途。

综上所述,本文做出如下贡献:

  • 我们开展大规模定量研究,利用一项新指标从经验上验证含缺陷代码的误导效应,并从模型内部视角确认该效应。相关分析进一步表明,缓解误导效应与提高所生成单元测试的有效性之间存在强正相关。
  • 我们提出并评估一种基于规约的测试生成范式,以大语言模型生成的行为规约而非含缺陷代码作为提示核心。我们表明,该范式显著减少被误导测试,同时提高缺陷检测率。此外,我们表明它能提升交互式、多轮提示流水线的效力,并分析所生成规约的质量如何影响最终测试套件。
  • 我们证明该方法对含缺陷代码与无缺陷代码均具稳健性。应用于无缺陷代码时,其编译失败、误报测试和测试覆盖率与基线水平相当。这确保该方法在增强缺陷检测的同时,不会给开发者增加额外负担,也不会损害其在回归测试等更广泛用途上的效用。

2. 研究设计

2.1. 研究问题

在本研究中,我们考察以下研究问题(RQ),以识别、分析并缓解误导效应及其对缺陷检测的负面影响。

  • RQ1: 含缺陷代码的误导效应如何影响大语言模型所生成单元测试的行为?
  • RQ2: 我们提出的基于规约的单元测试生成流水线如何帮助缓解误导效应?
  • RQ3: 我们提出的基于规约的单元测试生成流水线是否会影响由无缺陷代码生成的单元测试?

RQ1 考察误导效应的存在与严重程度。我们进行大规模评估,为这一现象提供经验证据,验证其对所生成测试之缺陷检测能力的有害影响,并从模型内部视角确认该效应。此外,我们分析缓解该效应与提高缺陷检测有效性之间的相关性。

RQ2 考察我们基于规约的流水线在含缺陷代码上的效力。我们首先评估其缓解误导并改善缺陷检测的能力,然后考察其收益是否随规约质量而扩展,以及是否在多轮、由反馈驱动的提示流水线中仍然成立。最后,我们人工检查缺陷是否被大语言模型生成的规约所继承,以及这如何影响所得测试套件。

RQ3 评估我们基于规约的流水线对无缺陷代码的影响,以确认其对含缺陷代码与无缺陷代码均适用,确保它不会给开发者施加不必要的负担,也不会损害其在回归测试等更广泛应用中的效用。

2.2. 基准

本研究采用 Defects4J(Just 等, 2014),这是一个被广泛使用的数据集,包含开源 Java 项目(例如 JFreeChart、Commons Lang)中的真实缺陷。该数据集 3.0 版包含 17 个项目中的 854 个缺陷(bugs)。每个缺陷都附带代码的含缺陷版本与修复版本,并可能包含一个或多个含缺陷方法,我们称之为焦点方法(focal methods)。数据集还提供人工编写的测试,其中包括能够检测含缺陷焦点方法的测试。

遵循先前关于评估基于大语言模型的单元测试生成的工作(Yang 等, 2024b;Yuan 等, 2024;Schäfer 等, 2024),我们将测试生成与评估聚焦于焦点方法。在选择焦点方法时,我们遵循先前研究的一般做法(Yang 等, 2024b;Alagarsamy 等, 2024;Tufano 等, 2021),并进一步按以下标准细化选择:

  1. 我们纳入分析中的全部非私有方法(public、protected 与默认访问级别),因为它们可从测试包访问,因而可被直接测试。
  2. 焦点方法必须同时存在于含缺陷版本与修复版本中,以便进行有意义的性能比较。被补丁删除或新引入的焦点方法予以排除。
  3. 我们只保留那些以其含缺陷版本至少触发 Defects4J 中一项已有人工编写测试的焦点方法,以确保相应补丁是为了修复缺陷,而非风格或性能优化。总计,我们整理的基准包含 318 个焦点方法,覆盖全部 17 个项目中的 233 个缺陷。

2.3. 测试生成工作流

为支持现实且可推广的评估,我们采用的测试生成工作流紧密遵循 Yang 等(Yang 等, 2024b)提出的、用于评估大语言模型所生成单元测试的端到端流水线,涵盖提示构造与单元测试抽取。遵循他们关于有效提示上下文的发现,我们用额外的、易于获得的周边代码特征来扩充焦点方法,包括方法签名与参数、外层类构造函数、已声明字段,以及同一类中的其他方法。此外,我们纳入作为参数类型或返回类型出现的用户定义类的构造函数,使大语言模型具备实例化这些对象依赖并生成更可靠测试所需的信息。视实验设定而定,焦点方法体和/或由焦点方法生成的文档字符串被用作提示的核心行为输入。我们用一条系统指令包裹该上下文,将大语言模型定位为专业 Java 开发者,并附加一条显式请求,要求为所提供代码生成单元测试。测试生成提示的概要见图 2。

You are a professional who writes Java test methods. Please help me write some unit tests in Java language, details are listed below:

‘‘‘

<被测代码和/或大语言模型生成的文档字符串,以及其他与焦点方法相关的上下文>

‘‘‘

Please write some unit tests in Java 11 and Junit 4 with maximizing both branch and line coverage. Please ensure that the output format is Markdown, and no explanations needed.

图 2. 用于生成单元测试的提示模板。该模板由系统指令、被测代码或文档字符串及其相关上下文,以及一条显式生成请求组成。

我们采用 Yang 等的提示配置,原因有三。第一,他们评估了广泛的开源与闭源模型,支持该提示设计的通用性。第二,他们的消融研究系统分析了额外代码上下文的影响,并促使我们纳入这些具体的上下文特征。第三,所需上下文可以仅从被测代码中抽取,无需人工检查,从而能够实现完全自动化的提示构造与测试生成流水线,这与减轻开发者负担的实用目标一致。

为从大语言模型输出中抽取单元测试,我们使用抽象语法树(AST)解析器(Tree-sitter(Brunsfeld, 2018))识别所生成的测试用例及相关产物,如 import 与辅助函数。然后,我们将抽取的内容与项目特定依赖,以及为 JDK(例如 java.util)和 JUnit(例如 org.junit.Assert)整理的一组常用依赖相结合,组成最终测试文件,以防止因缺少 import 而导致编译失败。

2.4. 模型

为确保分析全面,我们从六家领先开发者中选取了 11 个多样的前沿(SOTA)大语言模型,在可得的情况下同时包括「基础」模型与「推理」模型。推理模型针对多步推理进行了优化(通常借助显式的思维链),以提高在需要复杂逻辑演绎的任务上的表现;基础模型则直接生成输出。对于能够以任一模式运行的混合模型,例如 Claude 4 Sonnet(Anthropic, 2025),我们分别评估了启用与未启用推理时的表现。所评估模型的完整列表见表 1。

表 1. 本研究中用于单元测试生成的大语言模型。

开发者模型名称类型是否开源
GoogleGemini 2.5 Pro(Google, 2025b)推理否
GoogleGemini 2.5 Flash(Google, 2025a)混合否
AnthropicClaude 4 Sonnet(Anthropic, 2025)混合否
xAIGrok-4(xAI, 2025b)推理否
xAIGrok-3(xAI, 2025a)基础否
OpenAIGPT-4.1(OpenAI, 2025a)基础否
OpenAIGPT-O4-mini(OpenAI, 2025c)推理否
DeepSeekDeepSeek-V3(DeepSeek-AI, 2025b)基础是
DeepSeekDeepSeek-R1(DeepSeek-AI, 2025a)推理是
AlibabaQwen3-Coder-Plus(Qwen Team, 2025a)基础是
AlibabaQwen3-Plus(Qwen Team, 2025b)推理是

图 3. 由被测代码生成规约文档字符串的合并提示模板。每一行是一个可复用的提示组件;最后一行说明三种提示变体如何组装。

提示组件提示文本
共享提示主体(S.P.M.B.)你是一名专业 Java 开发者。请帮助识别下述方法的意图与功能:<被测代码及相关信息>
基础文档字符串提示后缀(B.D.P.P.)请提供一份正式文档字符串,识别给定方法的功能与意图。请避免直接引用焦点方法代码,因为它可能含有缺陷,并且只输出文档字符串。
高级分析提示(A.A.P.)请提供一份正式文档字符串,识别给定方法的功能与预期规约。为此,请首先从一名审计质量与正确性的专家软件工程师视角进行批判性分析。你的分析必须识别两类潜在问题:1. 逻辑错误:审视算法逻辑。根据方法名与上下文,其实现是否正确地达成了其表面目标,还是存在即使在「正常路径」上也会产生错误结果的逻辑缺陷?2. 稳健性疏漏:检查生产级代码本应包含、但却缺失的必要步骤。这包括但不限于输入校验(例如空值检查与边界条件)、恰当的错误处理,以及必要的数据清洗或转义。
面向推理模型的输出要求(O.R.R.M.)务必清楚地写出你的分析。基于这一分为两部分的分析,文档字符串应描述该方法的一个正确且稳健版本的规约,捕捉开发者的可能意图。请避免直接引用焦点方法代码,因为它可能含有缺陷。将文档字符串输出在由 \\\java 与 \\\ 围起的 Java Markdown 代码块中,文档字符串本身用 /** 与 */ 包裹。
面向基础模型的输出要求(O.R.B.M.)你的输出应分为三部分。第 1 部分:批判性分析。清楚陈述所发现的逻辑错误与稳健性疏漏。若未发现问题,明确写出:「未发现问题。」第 2 部分:所需修复。列出纠正已识别逻辑错误与稳健性疏漏所需的全部修复。若无需修复,写出:「无需修复。」第 3 部分:最终规约文档字符串。基于第 2 部分,撰写一份正式文档字符串,描述在应用全部提议修复之后该方法的纠正后行为。请避免直接引用焦点方法代码,因为它可能含有缺陷。将文档字符串输出在由 \\\java 与 \\\ 围起的 Java Markdown 代码块中,文档字符串本身用 /** 与 */ 包裹。
提示组装基础文档字符串提示 = S.P.M.B. + B.D.P.P.;面向推理模型的高级提示 = S.P.M.B. + A.A.P. + O.R.R.M.;面向基础模型的高级提示 = S.P.M.B. + A.A.P. + O.R.B.M.

2.5. 缓解方法与基线

为抵消含缺陷代码造成的误导效应,我们提出一种基于规约的测试方法。先前研究(Huang 等, 2025;Schäfer 等, 2024;Liu 等, 2025)探索过使用高质量、人工撰写的文档来改进大语言模型所生成的测试,但此类文档在实践中往往不可得。相反,我们使用大语言模型恢复被测代码的预期行为,并使测试生成聚焦于该预期行为,而非可能错误的实现细节。

我们的方法由两步组成。第一步,提示大语言模型以文档字符串的形式构造代码的行为规约。第二步,将该规约文档字符串作为测试生成模型的唯一行为输入,丢弃原始的含缺陷实现。通过迫使模型在规约而非含缺陷代码上运作,我们旨在降低其对实现缺陷的偏向,从而减少被误导测试的数量,同时增加有效的、能够发现缺陷的测试数量。与直接基于代码的测试生成相比,本方法的主要额外开销是一次用于生成文档字符串的额外大语言模型调用,以及相应的输入/输出词元成本。这标志着与先前工作的关键分歧:先前工作要么把含缺陷代码作为大语言模型的唯一输入(Schäfer 等, 2024;Chen 等, 2024;Lemieux 等, 2023),要么仅把大语言模型生成的文档作为含缺陷代码旁的补充上下文(Yuan 等, 2024)。我们以这些设定作为基线进行比较,另设一个同时移除被测代码与所生成文档字符串的基线,以评估我们设计的两个组成部分是否都必要:(1)完全移除被测代码;(2)用大语言模型生成的规约替换它。我们在图 3 中给出本方法基础版本的提示,标注为基础文档字符串提示(Base Docstring Prompt)。

为进一步加强本方法,我们引入一种高级提示策略(高级文档字符串提示,Advanced Docstring Prompt),利用现代大语言模型的代码理解能力,要求模型在生成文档字符串之前进行分为两部分的分析:(1)识别实现与从方法名及上下文推断出的意图相矛盾的逻辑错误;(2)检测稳健性缺口,例如缺失的空值检查、不充分的清洗,或未处理的边界情况。强制进行这一分析的提示见图 3 中的高级分析提示一行。该策略对推理模型与基础模型的实现方式不同,以最大化其有效性。对于推理模型,要求模型分析这些问题就足以引出必要的推理过程。对于基础模型,同样的指令并不能可靠地引出所需推理步骤。因此,我们要求模型显式报告已识别的缺陷以及解决它们所需的修复,并且只有在此之后,才在假定这些修复已被应用的前提下撰写文档字符串。我们对照两个基线评估这一高级提示:(1)基础文档字符串提示,以度量高级分析相对于本方法基础版本的收益;(2)带有相同高级分析指令的直接基于代码的测试生成。第二个基线在单步中生成测试,既不移除含缺陷实现,也不用大语言模型生成的文档字符串替换它。这一比较检验的是:当被测的含缺陷代码仍然可见时,仅靠高级分析能否缓解误导效应;抑或它必须与我们基于规约的方法相结合,由被测代码生成文档字符串,并在测试生成时用该文档字符串替换代码。

最后,我们对在应用本方法后、被误导测试套件降幅最大与最小的两个模型,用高级文档字符串提示所生成的全部 636 份文档字符串进行人工检查。我们用这一检查分析文档字符串质量如何影响下游测试生成。所检查的文档字符串属性详见下一节。

2.6. 指标与统计

表 2. 基于两个代码版本上执行结果的测试类别。「阳性」表示标记了缺陷,「阴性」表示未标记缺陷。

类别修复版本含缺陷版本
真阴性通过通过
真阳性(有效)通过失败
假阴性(被误导)失败通过
假阳性失败失败

表 3. 在含缺陷版本上通过的测试,以及其中真阴性(两个版本都通过)与假阴性(被误导)测试的数量(#)和比例(%)。

模型在含缺陷版本上通过真阴性测试 #真阴性测试 %假阴性测试 #假阴性测试 %
Gemini 2.5 Pro2183201092.08%1737.92%
Gemini 2.5 Flash1782166893.60%1146.40%
Gemini 2.5 Flash(推理)2066191192.50%1557.50%
Claude 4 Sonnet3034288595.09%1494.91%
Claude 4 Sonnet(推理)2932274593.62%1876.38%
Grok-42482230392.79%1797.21%
Grok-31468139795.16%714.84%
GPT-4.11806171494.91%925.09%
GPT-O4-mini1672154292.22%1307.78%
DeepSeek-V31750167495.66%764.34%
DeepSeek-R12206206193.43%1456.57%
Qwen3-Coder-Plus2053197396.10%803.90%
Qwen3-Plus2914267591.80%2398.20%
平均2181204393.77%1386.23%

为回答研究问题,我们采用若干关键指标,它们来自将每条生成的测试分别在含缺陷程序及其对应修复版本上执行。测试根据这一双重执行的结果分为四类,详见表 2。

在整个评估中,我们把 Defects4J 的修复版本视为预期程序行为的金标准,并据此定义全部测试标签。在这一定义下,任何对相同输入产生与修复版本不同的外部可观察输出的实现,在我们的评估中都不被视为无缺陷。这一特定于基准的预言机使我们能够在全部焦点方法上一致地标注被误导测试、有效测试和误报测试。

对于 RQ1,为度量误导效应及其对缺陷检测有效性的影响,我们比较由含缺陷代码与修复后代码生成的两类测试的数量与比例:

  • 被误导测试(假阴性): 在含缺陷代码上通过、在其对应修复版本上失败的测试,用于验证并量化误导效应。
  • 有效测试(真阳性): 在含缺陷代码上失败、在其对应修复版本上通过的测试,直接度量对缺陷检测能力的影响。

我们用于量化误导效应的指标与 Huang 等(Huang 等, 2025)有实质差异。我们只把假阴性计为「被误导」——即在含缺陷版本上通过但在修复版本上失败的测试——因为只有这些测试显式断言了缺陷行为。相比之下,Huang 等把所有在含缺陷版本上通过的测试(真阴性 + 假阴性)都当作误导的证据;然而,这一聚合计数可能主要由真阴性驱动——即在两个版本上都通过的有效测试。为说明这一局限,我们在表 3 中计算并报告真阴性(两个版本都通过)与假阴性(仅在含缺陷版本上通过)的数量和比例。我们发现,在含缺陷代码上通过的测试中,绝大多数——平均超过 90%——实际上是真阴性。因此,Huang 等基于聚合计数的指标并不能准确刻画含缺陷代码之误导效应的存在与程度。

为从模型内部视角进一步验证大语言模型所生成测试的这些行为发现,我们分析大语言模型在以含缺陷或修复后源代码为条件时,赋予给定测试(被误导或有效)的序列得分(Brown 等, 2020;Mitchell 等, 2023;Holtzman 等, 2020)。该得分形式化定义为:

$$S(T,C)=\frac{1}{|T|}\sum_{i=1}^{|T|}\log P(t_{i}\mid C,t_{1},\ldots,t_{i-1})$$

在该式中,$S(T,C)$ 表示在给定输入代码上下文 $C$ 时,所生成测试序列 $T$ 的归一化得分。该得分计算为每个词元的平均对数概率,反映模型生成该特定序列的置信度。按序列长度 $|T|$ 归一化,确保不同词元序列长度的测试之间可以公平比较(Brown 等, 2020)。

对于 RQ2,我们度量被误导测试与有效测试的变化,以确认本方法缓解了误导并改善了缺陷检测。为确保收益不集中于少数焦点方法,我们也在方法层面分析结果,报告大语言模型被误导的唯一方法数量(至少有一条被误导测试),以及被检测到的唯一含缺陷焦点方法数量(至少有一条有效测试)。这在焦点方法粒度上验证了跨数据集的有效性。对于高级分析方法,由于模型可能幻觉出并不存在的「虚假意图」或不正确的修复,我们还报告那些断言既不存在于含缺陷版本、也不存在于修复版本中的幻觉行为的测试,即假阳性测试。我们进一步进行人工检查,标注每份大语言模型生成的文档字符串是否:(1)保留了含缺陷焦点方法中的原始缺陷;(2)描述了修复该缺陷所需的纠正后行为。

对于 RQ3,我们度量测试正确性指标(Yang 等, 2024b;Yuan 等, 2024;Schäfer 等, 2024),包括编译失败率与误报测试率。图 4 给出误报测试的一个例子,即通过断言代码中并不存在的幻觉行为而在无缺陷代码上失败的测试。我们还度量测试覆盖率指标(Wang 等, 2024b;Inozemtseva 与 Holmes, 2014;Rao 等, 2023),包括无缺陷代码的行覆盖率与分支覆盖率。

无缺陷焦点方法

public String generateToolTipFragment(String toolTipText) {
 return " title=\"" + ImageMapUtilities.htmlEscape(toolTipText)
 + "\" alt=\"\"";
}

断言幻觉行为的测试

@Test
public void testGenerateToolTipFragment_Null() {
 String result = gen.generateToolTipFragment(null);
 Assert.assertEquals("", result);
}

带有幻觉行为的生成文档字符串

/**
 * Generates a sanitized HTML attribute fragment...
 * <ul>
 * <li>Gracefully handle null... treating null as an empty
 * string rather than producing a literal "null" string
 * or throwing an exception.</li>
 * <li>Safely escape all special characters...</li>
 * </ul>
 *
 * @return a valid HTML attribute fragment containing the
 * escaped title, or an empty string if input is null
 */

图 4. 由带有幻觉的文档字符串生成的误报测试示例。高亮行标出生成文档字符串中的幻觉行为,以及测试中相应的错误断言。该示例展示了一份描述两个代码版本中都不存在之行为的幻觉文档字符串,以及由此产生的、在两个版本上都失败的误报测试。

3. RQ1:含缺陷代码的误导效应

在本节中,我们从测试表现与模型内部两个视角,评估含缺陷代码的误导效应及其对所生成测试之缺陷检测有效性的影响。评估工作流见图 5。

图 5. 评估含缺陷代码之误导效应的工作流。工作流示意:分别为每个焦点方法的含缺陷版本与修复版本生成测试,在两个版本上执行,并分类以度量误导效应。

3.1. 误导效应对测试生成的影响

表 4 比较了由含缺陷代码与修复后代码生成的测试。当以含缺陷代码作为提示时,模型产生的被误导测试大幅更多;这些测试在含缺陷代码上通过、在修复版本上失败,从而错误地验证了缺陷行为。平均而言,模型生成 137.69 条被误导测试(3.84%)。相比之下,当给出对应的修复后代码时,平均值降至 16.46(0.46%)。这一差距为误导效应的存在与幅度提供了定量证据,表明现代大语言模型可能把错误逻辑误解为预期功能。

表 4. 每个模型生成的测试总数,以及含缺陷代码输入与修复后代码输入下被误导测试与有效测试的数量(#)和百分比(%),按基础模型与推理模型分组。

模型含缺陷输入 总数含缺陷 被误导 #含缺陷 被误导 %含缺陷 有效 #含缺陷 有效 %修复后输入 总数修复后 被误导 #修复后 被误导 %修复后 有效 #修复后 有效 %
Gemini 2.5 Flash35391143.221403.963616110.302797.72
Claude 4 Sonnet42021493.55882.094250150.353618.49
Grok-32543712.79933.662581170.661997.71
GPT-4.12841923.24863.032905110.382368.12
DeepSeek-V33002762.531133.763008190.632418.01
Qwen3-Coder-Plus3455802.321574.543353100.302597.72
基础模型平均3263.6797.002.94112.833.513285.5013.830.44262.507.96
Gemini 2.5 Pro32841735.27982.983286170.5235410.77
Gemini 2.5 Flash(推理)39571553.92992.50395670.182937.41
Claude 4 Sonnet(推理)45151874.14881.954553270.593728.17
Grok-439231794.561453.703985190.483989.99
GPT-O4-mini25001305.20361.44260670.272489.52
DeepSeek-R134131454.25972.843622210.583248.95
Qwen3-Plus48572394.921142.354808330.693898.09
推理模型平均3778.43172.574.6196.712.543830.8618.710.47339.718.99
总平均3540.85137.693.84104.152.983579.1516.460.46304.088.51

除增加被误导测试外,误导效应也直接削弱缺陷检测。对于在含缺陷代码上失败、在修复版本上通过的有效测试,当以含缺陷代码为提示时,模型平均只产生 104.15 条(2.98%)。当给出对应的修复后代码时,这一数字升至 304.08(8.51%),近乎三倍。这些结果表明,含缺陷的输入代码不仅导致更多不正确的测试,还会抑制有用的、能够发现缺陷的测试生成。

表 5. 不同输入条件下所生成测试的平均序列得分。行表示生成测试的模型,列表示评估模型。为防止自我评估偏差,生成者与评估者来自同一开发者时的得分已被排除。M/E:被误导测试/有效测试。「—」表示因同一开发者而被排除。

模型DS-V3 含缺陷 MDS-V3 含缺陷 EDS-V3 修复 MDS-V3 修复 EQwen 含缺陷 MQwen 含缺陷 EQwen 修复 MQwen 修复 EGPT-OSS 含缺陷 MGPT-OSS 含缺陷 EGPT-OSS 修复 MGPT-OSS 修复 E
Gemini 2.5 Pro-1.28-1.36-1.35-1.29-1.64-1.77-1.76-1.68-2.21-2.42-2.30-2.35
Gemini 2.5 Flash-1.12-1.23-1.23-1.17-1.39-1.61-1.55-1.52-2.00-2.27-2.14-2.19
Gemini 2.5 Flash(推理)-1.24-1.38-1.31-1.32-1.61-1.79-1.73-1.71-2.14-2.38-2.23-2.31
Claude 4 Sonnet-1.07-1.22-1.20-1.14-1.39-1.65-1.56-1.51-2.16-2.44-2.33-2.36
Claude 4 Sonnet(推理)-1.10-1.26-1.21-1.19-1.44-1.69-1.62-1.58-2.17-2.46-2.34-2.39
Grok-4-1.38-1.37-1.45-1.29-1.85-1.85-1.99-1.71-2.68-2.58-2.80-2.50
Grok-3-1.23-1.29-1.35-1.23-1.58-1.73-1.75-1.61-2.44-2.51-2.59-2.43
GPT-4.1-1.16-1.31-1.28-1.23-1.57-1.73-1.78-1.62————
GPT-O4-mini-1.40-1.39-1.48-1.32-1.85-1.84-1.99-1.73————
DeepSeek-V3————-1.49-1.70-1.72-1.57-2.28-2.61-2.46-2.53
DeepSeek-R1————-1.70-1.87-1.84-1.75-2.49-2.70-2.60-2.61
Qwen3-Coder-Plus-1.12-1.23-1.27-1.17————-2.27-2.52-2.45-2.44
Qwen3-Plus-1.21-1.29-1.28-1.22————-2.40-2.56-2.52-2.47
平均-1.21-1.30-1.31-1.23-1.59-1.75-1.75-1.64-2.29-2.50-2.43-2.42

表中评估模型列依次为 DeepSeek-V3、Qwen3-Coder-Plus、GPT-OSS-120B;每个评估模型下再分含缺陷输入与修复后输入,各含 M(被误导)与 E(有效)。

我们也观察到,推理模型倾向于从含缺陷输入生成更多被误导测试,并从修复后输入生成更多有效测试。这一发现得到相关分析的支持。我们发现,由含缺陷输入产生的被误导测试数量与由修复后输入产生的有效测试数量之间存在强正相关($r=0.90$,$p<0.01$),二者各自比例之间也存在强相关($r=0.72$,$p<0.01$)。这些相关表明,最有能力生成正确测试的模型,也是最容易被含缺陷代码误导的模型。此外,我们观察到,从含缺陷输入切换到修复后输入时,被误导测试的减少与有效测试的增加之间存在强正相关(数量上 $r=0.90$,$p<0.01$;比例上 $r=0.88$,$p<0.01$)。这一紧密联系提示,缓解误导效应可能是提高大语言模型所生成测试套件之缺陷发现效力的一个有前景方向。

在真实场景中,含缺陷程序的修复版本并不能用于测试生成。因此,由修复后代码生成的测试所表现出的更优性能,并不是一个可实践的基线,而是一个预言机,用以展示含缺陷代码本身所造成的性能下降。我们的分析表明,含缺陷代码是有效测试生成的主要障碍,这一因素必须在现实评估中加以考虑。这些发现的一个关键含义是:先前仅使用无缺陷代码评估基于大语言模型的测试生成的工作(Yang 等, 2024b;Tang 等, 2024;Dakhel 等, 2024),很可能高估了这些模型真实的缺陷检测能力。

3.2. 序列得分

为给误导效应提供模型内部证据,我们分析大语言模型赋予每条所生成测试的序列得分。该得分揭示模型对给定输出的概率偏好(Brown 等, 2020;Mitchell 等, 2023;Holtzman 等, 2020):如果输入中的缺陷扭曲了模型的生成偏好,那么被误导测试在以含缺陷代码为条件时应获得更高的序列得分,而有效测试在以修复后代码为条件时应得分更高。

为进行这一实验,我们使用三个前沿开源模型作为评估者:DeepSeek-V3(DeepSeek-AI, 2025b)、Qwen3-Coder-Plus(Qwen Team, 2025a)和 GPT-OSS-120B(OpenAI, 2025b),因为专有模型的 API 无法获得序列得分。为确保评估无偏,我们采用交叉打分方法:每个模型只为来自不同开发者的模型所生成的测试打分。这防止模型偏爱自身的生成风格,而该风格可能受共享训练数据或相似训练过程的影响。

表 5 的结果确认,含缺陷源代码会使模型的生成偏好偏向于断言缺陷行为的被误导测试,这由两条一致趋势所证明。第一,被误导测试在以含缺陷代码为条件时的平均序列得分高于以修复后代码为条件时;例如,以 DeepSeek-V3 为评估者时,从含缺陷输入切换到修复后输入,平均值从 $-1.21$ 降至 $-1.31$,Qwen3-Coder-Plus(从 $-1.59$ 到 $-1.75$)和 GPT-OSS-120B(从 $-2.29$ 到 $-2.43$)也有类似下降。相反,有效测试在以修复后代码为条件时得分更高;以 DeepSeek-V3 为例,平均值从 $-1.30$ 升至 $-1.23$,Qwen3-Coder-Plus(从 $-1.75$ 到 $-1.64$)和 GPT-OSS-120B(从 $-2.50$ 到 $-2.42$)也呈现同一模式。综合来看,这些趋势表明,先前观察到的行为差异源于模型在内部被含缺陷实现所误导。

RQ1 回答

含缺陷代码对大语言模型所生成的测试具有严重的双重负面影响。它误导模型产出验证该缺陷的被误导测试,同时抑制本可检测该缺陷的有效测试。我们进一步用序列得分从模型内部加以印证,表明模型的偏好被扭曲为偏向于断言提示中缺陷行为的测试。此外,第 3.1 节的相关分析提示,代码理解能力更强的模型可能更容易受到误导,而被误导测试的减少与有效测试的增加相关。

下篇继续:评估并缓解含缺陷代码对大语言模型生成单元测试的误导效应(下)。

觉得有用,转给同事

微信扫码

用微信扫一扫,在手机上打开后即可转发。

用 RSS 订阅

提交勘误