运用生成式人工智能进行单元测试生成:自动生成对象的比较分析_类别_代码
Shreya Bhatia, Tarushi Gandhi, Dhruv Kumar, Pankaj Jalote
Delhi, India
引用
Bhatia S, Gandhi T, Kumar D, et al. Unit test generation using generative ai: A comparative performance analysis of autogeneration tools[J]. arXiv preprint arXiv:2312.10622, 2023.
论文:https://arxiv.org/abs/2312.10622
择要
这项研究旨在实验性地调查LLMs(特殊是ChatGPT)对Python程序天生单元测试脚本的有效性,以及天生的测试用例与现有单元测试天生器(Pynguin)天生的用例之间的比较。在实验中,我们考虑三种类型的代码单位:1)过程化脚本、2)基于函数模块化代码和3)基于种别代码。根据覆盖率、精确性和可读性等标准评估所天生的测试用例。
1 弁言
单元测试是软件开拓的一个主要部分,由于它有助于在开拓过程中尽早捕获缺点。手动创建和掩护有效的单元测试是一项明显费时费力的任务。为理解决手动测试创建中固有的困难,研究职员提出了各种自动化单元测试天生过程的方法论。这个领域常见的方法包括基于搜索、基于约束或基于随机技能,所有这些方法都旨在天生一套紧张目标是增强目标软件覆盖率的单元测试套件。然而,与手动创建的测试比较,通过这些技能产生的自动化测试可能不太易读和理解。这个缺陷使得履历较少的测试职员很难学习,并且阻碍了这些策略特殊是对初学者采取。因此,开拓职员可能会犹豫是否将这些自动天生 的 测试直收受接管入他们 的 事情流程中。为理解决这些担忧,最近的努力探索利用高等深度学习 (DL) 技能,特殊是大型措辞模型 (LLMs),进行单元测试天生。
大型措辞模型(LLMs)的进步,以OpenAI的ChatGPT(GPT-3.5)为例,展示了在诸如问答、翻译和文本/代码天生等日常任务中增强的能力,与人类一样理解。与其他LLMs不同,ChatGPT结合了来自人类反馈的强化学习(RLHF)和更大规模的模型,提高了泛化能力并与人类意图对齐。ChatGPT广泛运用于日常活动中,在文本天生、措辞翻译和自动客户支持等任务中至关主要。除了日常利用外,大型措辞模型越来越多地运用于软件工程任务,包括代码天生和择要。这些模型还可以促进单元测试用例的天生,并简化软件验证过程。
本文旨在磋商由大型措辞模型天生的测试套件的上风和缺陷。我们特殊关注ChatGPT作为LLM的代表。此外,我们希望探索将现有单元测试天生器(如Pynguin)与基于大型措辞模型(LLM)的方法集成以提高整体性能的潜力。
我们评估ChatGPT天生的单元测试质量与Pynguin比较。根据代码构造,我们将样本Python代码分类为3类:1)过程脚本,个中代码高度不构造化,缺少类和方法的适当定义。2)基于函数的模块化代码是指具有清晰函数定义的独立操作且像独立代码单元一样运行的功能。3)基于类的模块化代码环绕类和工具组织而成,作为紧张组织单位。
我们精心整理了一个数据集,包括60个Python项目,将它们分类为每个种别20个项目,并且每个项目都有完全的可实行环境。在我们的研究中,我们专注于从每个项目中选择一个指定的核心模块,代码行数在100-300行之间,根据诸如圈繁芜度、函数计数和文件相互依赖等成分进行选择。然后我们通过将它们作为输入提示给ChatGPT来为所选模块天生单元测试,并与Pynguin天生的单元测试进行比较。我们旨在办理以下研究问题:
RQ1(比较性能):ChatGPT 在天生单元测试方面与 Pynguin 比较如何?RQ2(性能饱和和迭代改进):ChatGPT天生的测试用例的有效性如何随着多次提示迭代而改进/变革?RQ3(质量评估):ChatGPT 天生的断言有多精确,有多少百分比的断言与代码的预期功能符合?RQ4(结合工具以提高性能):ChatGPT和Pynguin的组合是否可以提升单元测试天生的整体性能,包括覆盖率和有效性?2 技能先容
图1:实证剖析事情流程
2.1 基于代码构造的分类
三个划分的种别用于捕捉不同级别的代码组织:
第一类(过程脚本):包括以无构造、过程化脚本为特色的代码示例。它们具有线性实行流,涉及包含一系列步骤的程序,并且掌握流依赖于块和浸染域(if、while、for),供应有限封装。
种别2(基于功能的模块化代码):包含了具有构造化方法的代码示例,没有显式的类定义。它们具有清晰定义的独立函数,作为代码的独立单元。这种代码组织供应了有限封装性,并可能依赖全局变量,在函数内部没有数据隐蔽或保护机制。
种别3(基于类的模块化代码):包含的代码示例具有良好组织构造,定义了类和方法作为紧张单元。这种代码组织是从面向工具编程中采取的,供应了强大的封装性;数据被隐蔽在类中,并通过方法访问。适用于具有繁芜构造的较大项目或运用程序。网络到的大多数较大代码示例属于此种别。
2.2 数据网络
为了对单元测试天生工具进行全面评估,我们首先网络了一组Python代码样本的数据集,涵盖了各种项目。Pynguin存在一个限定,即它无法很好地处理利用原生代码(如Numpy)的Python程序。在我们的比较剖析中,我们不得不该用没有依赖于这些库的Python项目。最初,针对每个种别,我们从开源Github存储库中选择了20个Python项目(即统共60个项目),确保多样性和平衡代表,并把稳到Pynguin的限定。
每个项目包含多个文件,这些文件彼此之间存在依赖关系。为了进行测试天生,我们必须确定一个核心模块,将其作为 ChatGPT 的提示输入通报,以便该核心模块包含密集的代码逻辑并覆盖项目的紧张功能。最初,我们将核心模块的选择限定在 0-100 行代码(LOC)的大小范围内(为了方便往后参考,我们将这些称为“小型代码示例”)。对这些数据进行剖析显示,在从 ChatGPT 和 Pynguin 天生的测试中得到了类似性能表现,因此我们决定将剖析扩展到更大规模的代码库,并且核心模块的大小范围从 100 到 300 LOC 不等。为了方便往后参考,我们将其称为“大型代码示例”。
基于 Lukasczyk 等人利用过的基准数据选取额外一组40个Python项目,并附带完全可实行项目环境,确保实验有稳固根本。值得把稳的是,根据它们的代码构造和繁芜程度对项目进行分类身分歧种别:每个种别2和3各20个。我们没有找到足足数目符合种别1: 过程脚本 (只找到六个)100-300 行 大型项目, 由于大多数项目采取模块化编程方法来简化掩护事情。
此外,通过我们的初步剖析,我们创造 Pynguin 无法为种别1天生单元测试用例,由于它在过程脚本中难以识别单位。因此,我们将进一步比较 Pynguin 和 ChatGPT 在种别2和3之间的剖析。然而,在接下来谈论由 ChatGPT 天生的测试时,我们也会考虑对种别1样本进行实验。统共有100个Python项目按代码行数分类:每个种别1(0-100行)、种别2(0-100 行)和种别3(0-100行)各20个,并且其余40个项目分布在种别2(100-300 行)和种别3(100-300行)。
利用ChatGPT启动单元测试用例天生过程的关键第一步涉及将单个代码模块作为提示的输入呈现。随后,我们动手确定每个项目中值得进行测试的关键核心模块,基于以下成分:
代码行数(LOC):为了简化我们的关注重点,我们将剖析限定在0-300行代码的模块上,并根据每个项目内部的后续成分确定核心模块。繁芜度指标:我们采取McCabe繁芜度来评估文件中的繁芜性和逻辑深度,通过优先选择具有最大圈繁芜度函数的模块来完善我们的选择。功能计数:在剩余的竞争者中,我们考虑了每个文件中的函数计数作为一个额外标准,旨在识别具有较高数量函数且具有较高圈繁芜度的文件,这表明个中包含繁芜逻辑。依赖剖析:我们选择过程的一个主要方面涉及审查文件之间的相互依赖关系。常常被其他文件导入或引用的文件涌现为潜在候选项,对项目整体逻辑至关主要。2.3 单元测试天生工具
我们探索了最近的工具Ticoder和Codamosa的潜力;然而,由于它们无法直接实验,我们选择了精通Python单元测试天生工具Pynguin来进一步与ChatGPT进行全面比较。我们聘请ChatGPT和Pynguin为每个已识别的核心模块天生单元测试用例。
2.4 ChatGPT的提示设计
我们的提示包括两个组成部分:i)Python程序,和ii)自然措辞中描述任务目标的文本,如图2所示。在第i部分中,我们供应所选核心模块(100-300行代码)的全部代码。我们不会将单独的单元供应给ChatGPT,由于我们旨在评估ChatGPT在供应完全Python程序时识别单元的能力。在第ii部分中,我们向ChatGPT查询如下:“利用Pytest编写单元测试来覆盖所有边缘情形。”ChatGPT天生的测试用例随后会针对Pynguin天生的测试用例进行语句和分支覆盖率评估,通过这一过程我们还会创造ChatGPT和Pynguin错过的语句,即天生的测试用例无法覆盖,并查看它们是否重叠。接下来,我们为ChatGPT设计了一个新提示,该提示将获取这些被忽略语句的索引,并哀求其再次天生单元测试以提高覆盖率。
接着,我们也被迭代提示ChatGPT不断改进覆盖范围的可能性所吸引。然后,我们在每次迭代时重复提示ChatGPT,并更新提示以包含新一组未命中语句的索引,直到不雅观察到覆盖率没有进一步提高为止,如图3所示。
图2 根本提示词
图3 进阶提示词
3 实验评估
3.1 实验设置
研究问题。通过我们的研究,我们将按以下顺序办理研究问题:
RQ1(比较性能):我们丈量了由ChatGPT和Pynguin天生的单元测试之间在不同代码构造和繁芜性下的语句覆盖率和分支覆盖率差异。然后,我们调查了圈繁芜度、代码构造以及ChatGPT实现的覆盖率之间是否存在任何干系性。
RQ2(性能饱和和迭代改进): 然后,我们迭代地提示Chatgpt改进样本的覆盖范围,给出错过语句的索引。
RQ3(质量评估):我们检讨天生的单元测试用例是否存在编译缺点。在正在编译的测试用例中,我们检讨它们的断言是否精确地测试了代码的预期功能。
RQ4(结合Pynguin和ChatGPT提高性能):在遗漏语句的情形下,我们查看 ChatGPT 和 Pynguin 天生的单元测试中遗漏语句之间的重叠程度。我们利用这一点来得出结论,即两种工具结合利用的技能组合可能是改进性能的潜在办理方案。
评估指标。通过多方面的方法评估天生的单元测试的有效性,采取以下指标:
语句覆盖率:量化天生测试覆盖个别代码语句的程度。分支覆盖率:评估各种代码分支的覆盖范围,并衡量测试套件在探索不同实行路径方面的效果。精确性:检讨天生断言是否有助于评估代码预期功能,同时也是精确的。3.2 实验结果
3.2.1 小型代码示例(0-100行)
对付种别1(程序脚本),Pynguin未能天生任何单元测试用例。这可以归因于种别1样本的构造,个中缺少构造,Pynguin无法识别出供测试的不同单元,由于它依赖于模块化代码的属性。把稳到ChatGPT供应了将种别1程序重构为模块化单元的建议。它首先为所供应的代码示例天生了重构后的代码,然后根据修正后的代码天生了测试用例。对付种别2,在语句和分支覆盖率方面,Pynguin和ChatGPT达到的造诣没有显著差异。这也可以从实行独立t考验后得到的p值(阈值=0.05)中看出来。语句覆盖率的p值为0.631,而分支覆盖率则是0.807。两个p值都高于阈值。对付种别3也是一样,在两种工具实现的语句和分支覆盖率之间没有显著差异,鉴定各自p值大于阈值:0.218 和 0.193 。在表格1中显示 ChatGPT和Pynguin 对 0-100行代码示例给出相似覆盖范围。
表1 ChatGPT&Pynguin为小代码样本得到的均匀语句和分支覆盖率。
这两种工具都为种别2和种别3供应了相称的性能。
3.2.2 小型代码示例(0-100行)
A.种别覆盖剖析
由于对付种别1,由于缺少定义明确的单元,单元测试天生是不可行的,并且代码重构是一个广泛的领域,我们将覆盖率剖析限定在具有100-300 LOC的大型代码样本的种别2和种别3。对付种别2,我们不雅观察到ChatGPT和Pynguin实现的语句和分支覆盖率之间没有显著差异,各自的p值大于0.05(阈值);0.169和0.195。对付种别3,ChatGPT和Pynguin给出了类似的覆盖率,分别表示为语句和分支覆盖率的p值0.677和0.580。这些不雅观察结果在表2和图4中详细显示。
回答RQ1:ChatGPT和Pynguin给出了所有3个类别的可比语句和分支覆盖率。此外,Mccabe繁芜度是评估代码单元繁芜性的指标。对付代码样本,我们为其分配最大Mccabe繁芜度,这是代码中存在的所有单元的最大值。然而,根据这个繁芜性度量绘制均匀语句覆盖率彷佛并没有突出显示每个工具实现的覆盖率与代码样本的最大Mccabe繁芜度之间的任何趋势或干系性,如图5所示。
表2 ChatGPT&Pynguin对大型代码样本得到的均匀语句和分支覆盖率。
图 4 代码样本(100-300 行)的语句覆盖率(左)和分支覆盖率(右)由ChatGPT(蓝色)和Pynguin(赤色)得到。
B. 覆盖范围的迭代改进
到目前为止,覆盖率剖析是基于从提示ChatGPT的第一次迭代中得到的结果进行的。作为对ChatGPT提示的一部分,我们供应了第一次迭代中遗漏的语句,并哀求它进一步改进给定代码样本的覆盖范围。我们持续这个过程,直到连续迭代之间没有覆盖率改进为止。由于大多数样本在第4次迭代时收敛(如图6所示),我们最多须要反复提示ChatGPT 5次。回答RQ2:不雅观察到种别2和种别3中语句覆盖率均匀增加了27.95和15.25。对付种别1,在表3中可以看到只管经由多次迭代,但在任何步骤上都没有改进覆盖范围。
表3 迭代改进。此表显示了在迭代1和5中实现的所有3个类别的均匀声明覆盖率。还描述了5次迭代后状态覆盖率的均匀改进以及达到覆盖率改进饱和点所需的迭代次数中位数。最佳覆盖率:所有迭代的最佳整体覆盖率均匀值。
C. 精确率
为了评估ChatGPT天生的断言的精确性,我们以以下办法检讨各种缺点种别:i)测试用例是否编译通过,ii)在编译通过的测试用例中通过断言的百分比,iii)对付失落败的断言碰着的缺点性子。强调利用用于天生这些断言的源代码片段来自公开可供一样平常利用的经由充分测试以实行其预期功能的Python项目。这意味着ChatGPT天生的测试用例应有效捕获代码预期功能,并且如果它们精确地测试代码逻辑,则相应断言该当通过。然而,如果有任何断言失落败,则表明这些断言未能测试代码预期功能,因此是禁绝确的。
回答RQ3:如表4所示,对付第2种别,均匀约39%的天生断言是禁绝确的,而对付第3种别,均匀28%的断言是禁绝确的。其余,我们还检讨了ChatGPT为第1种别样本供应重构代码时断言的精确性,并创造58%天生的断言是禁绝确的。从第1种别到第3种别逐渐减少缺点断言百分比可能意味着ChatGPT在具有明确定义构造程序中天生精确断言的能力更高,可能是由于代码中存在更连贯和故意义单元。
表4 禁绝确断言的百分比。此表给出了ChatGPT3类代码示例天生的断言精确的均匀百分比。还指定了断言失落败的3个缘故原由的分布:i)断言-缺点:当断言条件未得到知足时发生ii)try/除外块中的缺点:当估量会引发非常但未引发时发生iii)运行时缺点:在程序成功编译后运行时发生。
D. 重叠遗漏语句
我们研究了ChatGPT和Pynguin常常遗漏的重叠语句的数量。我们不雅观察到,均匀而言,在统共50个遗漏语句中,大约17个是两者共有的,这意味着重叠明显低于遗漏语句的总数。回答RQuar:如果我们把ChatGPT和Pynguin结合起来,一个可能的逻辑推论是,唯一遗漏的语句将是重叠的语句,别的的语句,以前被Chat-GPT和Pynguin单独遗漏的语句,现在将被覆盖。例如,根据我们的评估,这两个工具的组合将导致31个以上的语句被覆盖。这如表5和图7所示。这也符合CODAMOSA的创造,该创造提出SBST和LLM的组合可以带来更好的覆盖率。
表5 遗漏重叠语句的汇总统计
图7 每个代码示例的ChatGPT、Pynguin及其交集的遗漏语句
转述:顾思琦
本文系作者个人观点,不代表本站立场,转载请注明出处!