基于Bug报告的自动生成测试用例:大型语言模型的可行性研究

互联不一般哥 2024-03-13 06:34:02

Automatic Generation of Test Cases based on Bug Reports: a Feasibility Study with Large Language Models

论文链接:[2310.06320] Automatic Generation of Test Cases based on Bug Reports: a Feasibility Study with Large Language Models (arxiv.org)

摘要

这篇文章主要讨论了利用大型语言模型(LLMs)自动生成基于缺陷报告的可执行测试用例的可行性研究。作者通过实验使用了ChatGPT和codeGPT模型,并在Defects4J数据集上进行了综合实证研究。实验结果表明,生成的测试用例具有可执行性、有效性和相关性,并且能够在自动程序修复(APR)流程中发挥重要作用,支持准确的错误定位和修补程序的验证。此外,作者还提供了相关的数据集和模型,以促进未来的研究。

引言

测试套件在软件自动化任务中扮演着关键角色,尤其是在自动程序修复(APR)领域。APR旨在自动生成修复补丁以减少调试和修复时间,而测试套件的质量直接影响到补丁的正确性。然而,软件项目中的测试套件往往不足,尤其是针对新发现的bug。APR的一个新趋势是利用错误报告来生成和验证补丁,但这也要求有足够的测试用例来评估补丁。

由于现有的自动测试生成方法要么只针对单元测试,要么需要正式定义的输入,而bug报告则提供了丰富的信息,因此研究如何从bug报告中生成测试用例显得尤为重要。这项研究的目标是解决从业者在采用程序修复方面的挑战,确保补丁可以自动生成并验证用户报告的bug。

在这篇论文中,研究者建议利用大型语言模型(LLM)来生成基于非正式错误报告的可执行测试用例。实验建立在ChatGPT和codeGPT的基础上,前者是一个在大量自然语言文本和软件程序源代码上训练的模型,后者是针对软件工程的预训练模型,可以针对各种任务进行微调。通过分析缺陷报告来自动化缺陷复制,这项研究有望为软件工程开辟新的可能性。

研究问题

RQ1: ChatGPT是否能够将非正式编写的bug报告转换为可执行的测试用例?为了回答这个问题,我们将ChatGPT应用于将缺陷4j的bug报告转换为测试用例。

RQ2: 与ChatGPT获得的基线结果相比,微调模型的表现如何?我们研究了微调模型在生成测试用例方面的能力,并将生成的测试用例与ChatGPT生成的测试用例进行比较,以评估其可执行性、有效性和相关性。

RQ3: LLM是否能够为新的bug生成可执行的测试用例?由于缺陷4j基准可能在训练过的LLM中泄露,我们评估了为新报告的bug生成测试用例的可行性,以验证翻译模型的泛化能力。

RQ4: Bug报告质量对测试用例生成性能的影响是什么?我们研究了缺陷4j中不同项目和不同类型的用户编写的bug报告,以了解bug报告的大小和内容是否对LLM生成可执行和相关的测试用例的能力产生影响。

RQ5: 生成测试用例与软件工程任务的相关性如何?我们研究了生成的测试用例对故障定位和补丁验证的影响,以了解它们与软件工程任务的相关性。

研究结果

[RQ1]:使用ChatGPT生成测试用例的LLM基准性能

实验目标:

本实验的目标是评估人类开发人员生成的测试用例是否可以通过现成的LLM(大型语言模型)来生成,特别是使用自然语言编写的bug报告来非正式地描述bug。为了回答第一个研究问题,实验以ChatGPT(版本3.5)为基准模型,并探索了两个子研究问题。

实验设计(RQ1.1 - 单代):

实验依赖于ChatGPT API(3.5版本)并使用默认参数。为了使用ChatGPT生成测试用例,向API提供的提示符由两部分组成,如之前章节所介绍的。然后,使用ChatGPT API为研究中的所有错误生成测试用例。在实际操作中,在运行生成的测试用例之前,会解析ChatGPT的输出,以从可能导致编译失败的自然语言文本(例如,描述性细节)中清除它们。之后,测试用例被系统地包含在测试套件中,由缺陷4j测试管道完全执行。最后,记录执行结果,以便计算可执行性、有效性和相关性的指标。

实验结果(RQ1.1 - 单代):

实验结果显示,ChatGPT能够从一个bug报告中生成一个可执行的测试用例,这个bug报告可以用来重现它。在缺陷4j数据集上,计算了ChatGPT能够成功生成测试用例的bug报告的比例。评估了生成的测试用例的数量,这些测试用例可以直接执行,不需要进一步的开发人员更改。然后评估了有效和相关的测试用例的百分比。

实验设计(RQ1.2 - 多代):

为了克服ChatGPT随机性的问题,进行了另一个实验,研究生成的5个测试用例中是否至少有1个是可执行且相关的。对于每个提示,查询ChatGPT API五次,并评估不同生成的测试用例。

实验结果(RQ1.2 - 多代):

结果显示,平均而言,所有项目中50%的bug报告都获得了可执行的测试用例,而为30%的bug报告获得了至少一个有效的测试用例。在可执行的测试用例中,观察到59%是有效的。这些结果表明,一旦通过了初始的可执行性挑战,ChatGPT生成的测试实际上是有效的,能够捕获错误报告的语义,并将其转化为触发错误的测试用例。

回答RQ1:

实验结果表明,ChatGPT可以用错误报告提示,为50%的输入样本生成可执行的测试用例。除了可执行性之外,大约30%的bug可以通过有效的测试用例进行重现,这个比例约为9%所有生成的测试用例中实际上是相关的。注意到超过一半(59%)的可执行测试用例是有效的测试用例。这些结果基于一个现成的LLM即服务,显示了自动化测试用例生成的潜力,利用用户报告的bug的复杂信息。

[RQ2]:CodeGPT的性能,这是一个针对测试用例生成任务进行微调的特定于代码的LLM

实验目标:

本实验的目标是为了评估微调模型性能与ChatGPT获得的基线结果的比较程度,采用了微调的CodeGPT模型。

实验设计(RQ2.1 - 单代):

实验考虑了codeGPT-small-java-adaptedGPT2模型,并按照默认参数对缺陷4j Java测试用例进行了微调。为了训练一个能够最佳泛化的模型,实验随机打乱了缺陷4j数据集,因为每个项目的错误报告的格式、大小和质量都不同。数据集最终被分为70%的训练集、15%的测试集和15%的验证集。

实验结果(RQ2.1 - 单代):

表3总结了RQ2的实验结果。在一次生成尝试中,CodeGPT优于ChatGPT,微调后的CodeGPT生成了24%的可执行测试用例。结果表明,针对将自然语言bug报告转换为测试用例的特定任务进行微调的生成预训练模型,比简单地在单个生成尝试中利用ChatGPT获得更好的性能。由于经过微调的CodeGPT模型是基于GPT 2.0版本的,因此预计一旦GPT 4.0模型可用于微调,结果将会有很大改善。

实验设计(RQ2.2 - 多代):

对于本实验,使用了先前微调的CodeGPT模型(第3.2节),并在测试数据集上执行了五次迭代,同时将随机种子从一个迭代更改到下一个迭代,以获得不同的结果。生成的测试用例再次在可执行性、有效性和相关性上进行评估。

实验结果(RQ2.2 - 多代):

如表3所示,使用微调模型执行多代只会略微增加可执行测试用例的数量。与利用像ChatGPT这样的预训练模型相比,微调模型在它们的世代中具有更少的随机性。此外,训练数据集非常小,这可能会导致过拟合。这解释了当使用CodeGPT为每个bug报告生成多个测试用例时,与使用ChatGPT执行多个代时,可执行测试用例的增加(+35%)相比,只有轻微的增加(+10%)。

对RQ2的回答:

微调CodeGPT产生了一个LLM,它通过一次生成尝试为24%的bug报告生成可执行的测试用例。这个比率比ChatGPT单代基线(15%)所达到的比率要大得多。然而,当执行几次生成尝试时,ChatGPT的成功率要高得多。这些结果表明,经过微调的LLM在自动化流水线中可能是有益的,其中单次射击就足够了,而ChatGPT在推荐场景中更有用。该结果进一步表明,在未来的工作中,应该研究更强大的模型。

[RQ3]:对新bug的性能泛化

实验目标:

本实验的目标是评估ChatGPT和CodeGPT这两个已知已经在公共数据上训练过的LLM(截至2021年10月)在新生成bug上的表现。由于实验依赖于缺陷4j数据集,这是一个在测试和程序修复中广泛使用的基准,因此可能存在数据泄漏的问题。为了解决这个问题,实验在新报告的bug(2021年10月之后)上评估了提议的生成管道,以确保重现bug的测试用例不是模型原始训练数据的一部分。

实验设计:

实验的重点是ChatGPT(多代),并自动评估可执行性。由于目前还没有一个针对所有新bug的固定版本,因此需要对生成的测试用例的相关性进行人工调查。实验收集了2021年10月1日之后创建的所有可用的缺陷4j错误报告,以确保它们没有包含在ChatGPT 3.5的训练数据中。只有Cli、Lang和Math项目报告了新的bug,因此考虑了额外的项目,这些项目仍在维护中。

实验结果:

表4显示了评估的新bug数量以及ChatGPT在可执行性方面的性能。在之前研究的3个项目和2个额外的项目中,收集了38个新的bug报告:对于这些bug报告中的55%,生成的测试用例是可执行的。此性能与缺陷4j的旧错误报告(参见RQ2)所达到的性能相当,这表明以前获得的性能可能是无偏的。此外,注意到大部分可执行生成的测试用例是有效的(Lang为50%,JacksonDatabind为100%)。实验手动分析了相关性,并确认生成相关测试用例的可行性。在缺乏oracle(评估测试用例相关性的固定版本)的情况下,实验将数据集提供给社区以供构建。

清单3提供了一个新报告的bug的示例,使用它来提示ChatGPT生成bug触发测试用例(即,用于重现相关的bug)。请注意,这个bug报告仍然没有得到解决,用户也没有其他用户提供相关的测试用例(当它再次在stackoverflow上提交时)。使用ChatGPT,实验生成了一个可执行的测试用例,如清单4所示。手工评估进一步确认了由ChatGPT提取的用于构建测试用例的输入是相关的,并且有助于重现报告的错误。

对RQ3的回答:

ChatGPT,一个LLM即服务,被证明能够为新报告的错误生成可执行的测试用例。总的来说,在超过55%的情况下,新的bug报告可以有效地作为提示来生成可执行的测试用例。通过人工分析,确认生成的测试用例反映了所描述的行为。

[RQ4]: Bug报告质量的影响

【实验目标】:

本实验的目标是根据错误报告的大小以及代码制品的存在来估计错误报告的质量。这种估计基于文献中的发现,即非常短的bug报告往往质量较低,而包含代码摘录的bug报告往往是由提供足够细节的开发人员编写的。实验调查了缺陷报告的大小和内容对测试用例生成的性能的影响。

【实验设计】(RQ4.1 - bug报告大小):

实验考虑bug报告的类别是基于它们是否导致使用ChatGPT生成可执行的、有效的和相关的测试用例与否。然后计算每个类别所有bug报告的大小(bug报告的字符数)。

【实验结果】(RQ4.1 - bug报告大小):

图4显示了每个类别的bug报告大小分布的中值,表明bug报告大小对生成的测试用例的可执行性和有效性影响很小。相比之下,相关的测试用例与规模较大的bug报告相关联。统计显著性差异是基于Mann Whitney U得分进行评估的。在p值大致为> 0.5(0.99)的情况下,可以得出结论:bug报告大小在可执行性方面对测试生成的性能没有影响。

这个观察结果可能与ChatGPT已经在公开可用的Java源代码上进行了广泛的训练有关,这使得它能够以最小的语法错误生成测试用例。因此,生成的测试用例的可执行性和有效性在很大程度上保持独立于bug报告的大小。

bug报告大小在相关性方面对性能的影响似乎是需要评估的更重要的方面,因为生成的测试用例的语法正确性是不够的。MWW测试确实证实了bug报告大小有轻微的影响:p值<0.5(0.2)。

【实验设计】(RQ4.2 - bug报告内容):

实验还考虑bug报告中代码片段的存在,并评估其对测试用例生成性能的影响。如果至少有一个可解析代码,则认为代码存在是被确认的。

【实验结果】(RQ4.2 - bug报告内容):

实验的初步观察显示,当使用ChatGPT生成带有bug报告的测试用例时,bug报告的质量很重要。

图5代表了bug报告在代码存在方面的情况,以及对涉及Cli、Closure、Lang、Math和Time项目样本的数据集生成的测试用例的评估。在数据集中,平均63%的bug报告包含代码。因此,如图5所示,包含代码的bug报告的数量总是高于不包含代码的bug报告的数量。

尽管如此,数据清楚地揭示,测试用例越好(即,可执行,然后有效,最后相关),相关的输入缺陷报告包含代码的概率就越高。如果我们比较导致生成不可执行的bug报告和导致生成可执行测试用例的bug报告的百分比,已经观察到在代码存在方面增加了6%的点。从可执行的测试用例到有效的测试用例,代码存在度只有轻微的增加(2%点)。然而,对于相关性,导致相关测试用例的90%的bug报告都包含代码。这清楚地突出了bug报告中的代码片段对LLMs的生成任务的影响。

对RQ4的回答:

实验结果表明,bug报告大小对生成的测试用例的可执行性和有效性影响很小。但是,它对测试用例相关性概率有轻微的影响。在内容(以及缺陷报告中是否存在代码)方面,实验显示66%导致生成可执行测试用例的缺陷报告中包含代码,而90%的相关测试用例与包含代码的缺陷报告相关。

这些观察结果证实了自然语言bug报告中存在的代码对于LLM生成可执行且相关的测试用例具有重要指导作用。

[RQ5]:软件工程中的用法

【实验目标】:

本实验的目标是研究生成的测试用例与软件工程任务的相关性,特别是在自动程序修复(APR)中的错误定位和补丁验证。实验旨在展示如何使用从用户编写的bug报告中生成的测试用例,以便在生产环境中运行完整的生成-验证修复管道。

【实验设计】(RQ5.1 - 故障定位):

在第一个实验中,评估生成的测试用例能否确保故障定位的性能。实验采用基于频谱的故障定位(SBFL)方法,并与GZoltar2工具结合使用。GZoltar提供所有可疑源代码行的列表,并按照落合可疑评分排序。如果至少有一个实际有bug的源代码行在列表的最高排名中,则认为bug被成功定位。实验首先在原始测试套件上运行GZoltar作为参考性能,然后在测试套件上运行GZoltar,其中原始的bug触发测试用例被生成的测试用例替换。

【实验结果】(RQ5.1 - 故障定位):

表5总结了基于频谱的故障定位的结果。在最初的测试套件中,SBFL能够完美地为22个错误本地化源代码行(排名前1)。在考虑SBFL的前5个输出时,在参考设置中正确地定位了42个错误。

然而,当使用生成的测试用例而不是真实测试用例时,SBFL的本地化性能略有提高:在三个研究项目中,top-1和top-5的本地化性能得到了改善。总体上,基于bug报告生成的测试用例帮助精确定位了4个即使使用ground truth测试用例也无法定位的bug。

【实验设计】(RQ5.2 - 补丁验证):

在第二个实验中,评估生成的测试用例在多大程度上可以帮助验证自动生成的补丁。实验考虑了基于TBar模板的APR基线工具生成的补丁。TBar工具通过迭代应用修复模式并使用项目测试套件验证修补后的程序来修复每个bug。实验调查了有多少TBar生成的补丁被标记为正确的(可信的)被生成的测试用例验证。

【实验结果】(RQ5.2 - 补丁验证):

表6总结了实验结果。例如,它显示在9个已知是合理的闭包补丁(即通过项目测试套件,但实际上不正确的)中,没有一个被生成的测试用例发现有效。总的来说,29个合理的补丁中只有8个被生成的测试用例验证。这意味着生成的测试用例可能比现有的开发人员编写的测试套件更有用,可以丢弃21个可信的补丁。

然而,也注意到在TBar数据集中被人工标记为正确的几个补丁没有被生成的测试用例验证。这可能是由于人工标记错误,或者实际的开发人员测试用例在报告的bug范围内不完整,或者生成的测试用例过度拟合了bug报告。

对RQ5的回答:

基于频谱的故障低定位实验表明,运行由LLM生成的测试用例,使用错误报告作为输入,可以比使用真实测试用例获得更好的定位性能。此外,实验结果也表明,生成的测试用例确实可以用来验证补丁的正确性。这显示了一个有前途的研究方向,即使用从用户错误报告生成的测试用例来验证生成的补丁,从而能够在真实的软件开发周期中采用生成和验证APR工具。

结论

在这项研究中,我们证明了使用大型语言模型(LLM)基于bug报告自动生成测试用例的可行性。ChatGPT的基本实验结果表明,尽管这个LLM即服务没有针对生成测试用例的特定任务进行微调,它也能够成功地使用bug报告(用自然语言编写)作为提示来生成可执行的和相关的bug触发测试用例。

进一步的实验显示,虽然ChatGPT通过多代尝试实现了高可执行性,但经过微调的LLM(例如:CodeGPT)通过单代尝试实现了比ChatGPT更高数量的可执行测试用例。这些发现表明,尽管存在希望,但使用LLM生成测试用例的研究仍存在性能差距需要缩小。

对新报告的bug进行的额外实验表明,所实现的基线性能是真实的:它不会因训练数据泄露而产生偏差。此外,对软件工程中LLM生成的测试用例的相关性的调查已经证明了它们在错误定位和补丁验证方面的潜力,这是自动程序修复的两个关键步骤。

转述:朱云峰

0 阅读:0

互联不一般哥

简介:感谢大家的关注