TOGA:一种用于测试Oracle生成的神经方法

互联不一般哥 2024-04-27 10:22:08

TOGA: A Neural Method for Test Oracle Generation

Elizabeth Dinella1, Gabriel Ryan2, Todd Mytkowicz3, Shuvendu K. Lahiri4

引用

Elizabeth Dinella, Gabriel Ryan, Todd Mytkowicz, and Shuvendu K. Lahiri. TOGA: a neural method for test oracle generation. In Proceedings of the 44th International Conference on Software Engineering (ICSE '22). Association for Computing Machinery, New York, NY, USA, 2130–2141. 2022.

论文:https://dl.acm.org/doi/10.1145/3510003.3510141

仓库:https://github.com/microsoft/toga

摘要

本文介绍了一种名为TOGA的测试Oracle生成方法,利用基于变压器的神经推理技术,聚焦于异常和断言测试预言机。TOGA能够处理含糊不清或缺少文件的单元,甚至缺乏实现的单元。评估结果显示,TOGA方法在预言机推理准确性方面比现有方法提高了33%,在测试数据集上达到96%的准确率。此外,将TOGA与自动测试生成工具EvoSuite集成后,在大型Java程序中发现了57个现实世界错误,其中有30个是其他自动化测试未发现的。

1 引言

单元测试是软件开发的一个重要方面。有效的组件(方法、类或模块)的单元测试可以提供文档、查找错误并防止回归。在文档方面,单元测试表达了单元的预期功能。记录单元的功能通过测试传达设备的预期用途。测试还作为一种在开发过程中检测功能错误的机制。执行时,测试会检查之间的不匹配预期和实现的功能。这种不匹配会导致测试失败,表明实现中存在错误。此外,当未来的代码更改引入错误时,单元测试可以提醒开发人员。开发过程中有效的(单元)测试可以防止发布有缺陷的软件并降低数十亿美元的成本。

单元测试由两部分组成: 前缀,驱动被测单元处于有趣的状态;以及一个预言机,它指定结果状态应满足的条件。一个足够富有表现力的测试套件应该记录两者下的功能满足先决条件的正常调用和异常调用违反前提条件的行为。图 1 显示了两个堆栈类的单元测试示例。测试记录了正常调用(图 1a)和异常调用(图 1b)。图 1a 显示了该单元的正常调用,其中测试前缀实例化一个堆栈并顺序调用推入和弹出。测试预言以红色突出显示,断言stack 的isEmpty方法应在结果状态返回true。如果该单元包含与测试行为相关的错误,此测试可以帮助检测错误。另一方面,图 1b 显示了该装置的当 pop 的前提条件不满足时的预期行为。在这种情况下,在空堆栈上调用 pop 的预期行为是提出一个例外。因此,测试预言机是预期的例外。 try-catch 结构确保该单元确实引发异常。如果该单元包含错误并且没有引发异常,测试将通过执行 Assert.fail() 失败。

显然,测试有巨大的好处。然而,创作高质量的单元测试非常耗时。平均而言,开发商花费 15% 的时间编写测试。因此,大量的工作一直致力于自动化单元测试生成[10,16,22,36]。然而,测试生成工具并没有明确的知识开发人员预期的程序行为。这带来了挑战用于生成功能测试预言机。相反,这些工具考虑程序崩溃和不良异常(例如空取消引用或越界数组访问)作为测试预言机。这些测试能够发现设备实施中的许多安全错误,但不足以发现违反预期功能的情况因此不能取代手动单元测试的需要。

图1:Stack 类的单元测试

补充自动化测试生成工具,广泛我们致力于根据文档和评论来测试预言机的创建[2,13,23,28,37]。我们参考这些技术作为测试预言机生成的规范挖掘方法。这些方法依赖于有限的文档结构和一组手工制定的规则来推断单元的异常和断言。然而,鉴于用户不遵循规定的格式编写文档,或者完全省略它们,这些方法都会失败在大多数现实世界的软件组件上提取有趣的预言。

我们提出了一种神经方法来推断异常和发现测试预言机的断言错误:TOGA。解决限制在现有的神经生成方法的基础上,我们提出了一种新方法将预言机生成问题重新表述为一个排名问题一小组极有可能的预言。我们的方法基于根据经验观察,开发者编写的单元中的预言机测试通常遵循少量常见模式。我们描述这些模式的分类并定义一个简单的语法表达了这种分类法。我们使用这个语法基于类型的约束来限制候选预言机的空间并生成满足句法和类型的格式良好的测试预言正确性。为了进行排名,我们开发了一个两步神经网络使用经过微调的预训练 Transformer 进行评分的排名程序候选预言机。

总之,有效的测试生成方法必须推断异常和断言预言机可以准确反映开发操作意图,并发现现实世界程序中的错误。此外,这种方法必须优雅地处理含糊不清或缺少文档,甚至缺少实现。

我们在测试预言机推理和错误发现方面评估我们的方法。我们的技术比现有技术提高了 33% 的准确性预言机推理方法,在保留的情况下实现 96% 的准确率测试数据集符合我们的语法和约束,准确度为 69%。在整体断言基准上,相对提高了 11%超过现有方法。此外,我们表明,当集成时使用随机测试生成工具(EvoSuite),我们的方法在 Java 基准 Defects4J中发现了 57 个现实世界的错误。

总的来说,本文的贡献如下:

引入基于方法生成异常预言机和断言预言机而无需依托单元实施的transformer。导出适用于异常和断言预言的数据集包含方法签名和文档字符串的培训。实施 TOGA,一种端到端测试生成技术。它将神经测试预言机生成与自动测试生成工具 EvoSuite 集成在一起。对测试预言机推理进行广泛的评估。证明我们方法改善了预言机推理准确率提高 33%,发现 57 个现实世界错误。

2 相关工作

我们将单元测试生成的相关工作大致分为(i) 自动测试生成方法,(ii) 规范挖掘方法,以及(iii)神经方法。

2.1 自动测试生成工具

考虑图 2a 中的示例,该示例显示了一个有问题的空操作堆栈弹出的实现。图2b显示了生成的单元使用回归预言机进行测试。该测试创建一个堆栈并pop。因此,回归预言是一个不正确的断言:堆栈不应为空序推送和弹出调用。由于pop方法有一个有bug的no-op实现,执行后堆栈将有一个元素流行音乐。因此,回归预言是一个不正确的断言:堆栈不应为空。

同样,将任何异常输出视为错误(安全Oracle)可能会在正确实现的方法上失败,导致错误积极的一面(例如,在空的对象上调用 pop() 的预期行为方法是抛出异常)。图2c显示了生成的单元使用安全预言机进行测试。一种依赖安全预言机的方法还将生成对有缺陷的 pop 实现的通过测试。由于 pop 是作为无操作实现的,因此不会引发异常在空堆栈上调用 pop 时。在这种情况下,测试预言机是隐式并断言不会引发异常。因此,尽管自动测试生成技术发现许多非功能性错误,并且对于检测未来代码更改的回归错误很有用,但它们不能替代手动编写的单元测试记录预期的功能。

图2:有缺陷的 pop 方法的回归和安全预言

2.2 规范挖掘方法

规范挖掘工作旨在生成测试准确反映预期行为的预言机(如图 1 所示)。与随机测试生成方法不同,规范挖掘方法对单元的实现没有任何了解,因此不需要执行。相反,他们依靠文档字符串文档。通常规范采矿方法定义一组自然语言文档字符串模式。这些图案无法捕获所有文档字符串,因为可以编写程序注释灵活,无需任何必要的语法或结构。

@Tcomment定义自然语言模式以及启发式推断无效属性。但是,它不能泛化到其他属性或异常类型。启发式示例@Tcomment 使用的是:如果关键字 @param 包含单词 null 和 not,则生成一个“预期的 NullPointerException”预言机彼此相差3个字之内。 ToraDocu [13] 使用以下组合模式、词汇和语义相似性匹配。与 @TCom ment 不同,ToraDocu 不限于 nullness 属性。然而,ToraDocu 只能为异常行为生成预言机。 JDoc tor [2] 是 ToraDocu 的扩展,也可以生成断言预言。

不变挖掘。为了导出观察到的程序执行行为的程序不变量,需要进行大量的工作。最近,EvoSpex将观察到的执行与突变来生成有效和可能无效程序状态的样本,并应用遗传算法来推断不变量方法后置条件。 GAssert还利用了进化使推断的程序不变量更加准确和袖珍的。这些方法可用于生成规范以及来自推断的不变量的相关测试预言,但是因为它们基于当前的执行/符号行为实施他们将生成回归预言,并且不能检测被测单元中是否已经存在错误。

2.3 神经方法

ATLAS 是一种基于神经网络的断言生成方法神谕。给定测试前缀和被测单元,ATLAS 使用循环神经网络生成断言。ATLAS信赖对单位的实施情况不了解文档字符串文档。 ATLAS 专门针对断言预言机生成,并不试图推断任何异常。

随后的方法对 ATLAS 进行了改进:使用基于 Transformer 的 seq2seq 架构,在自然语言和代码上进行预训练。变压器 seq2seq 模型的性能优于ATLAS 在推理准确性方面。然而,我们表明与测试前缀生成器结合使用时,它会很困难查找 Java 项目中的真实错误。最后,AthenaTest是一种变压器模型方法,用于生成整个单元测试,包括前缀和预言机。雅典娜测试将单元的上下文作为输入(例如,周围的类、方法签名等)和实施。就像之前的神经方法,它对文档字符串文档没有任何了解,并且依赖于实现来推断预期的行为。

3 实验

3.1 预言机结构

我们的方法解决了现有神经方法的局限性通过对一组候选测试采用排名架构预言机,而不是生成模型。在本节中我们开发用于描述这组测试预言的语法。我们首先描述基于以下内容的常见预言机结构的分类对单元测试数据集进行定性调查,然后使用它分类法为我们的预言语法的构建提供信息。

(1) 预期异常预言机验证是否使用某些无效用法执行测试前缀引发异常。它们最常表达为以下结构:

(2) 断言结构。断言预言机验证正确返回行为,尽管如果出现任何异常,它们也会失败抛出。我们观察到几种常见的断言模式:

布尔断言。布尔断言用于检查被测单元的某些属性是真/假。他们通常直接在方法返回值上断言:

空断言。空断言通常会检查处理某些内容的方法调用的返回值输入

相等断言。返回值通常根据常量进行检查或表示期望值的文字。在很多情况下,特别是当被测单元包含一些数据结构,预期值之前已传递作为测试前缀中某些方法的参数。

(3) 不常见的结构。我们注意到发生的其他几种模式更罕见的是,包括对数组的相等断言或对多个方法调用(与方法调用和常量相反)。我们还注意到,有一些我们没有注意到的断言模式在任何单元测试中观察,尽管它们经常被用来表达程序内的不变量。这些包括具有逻辑性的断言具有不等式约束的连接词和断言。

(4) 测试oracle语法。基于普通预言机的分类结构,我们开发了一种表达常用测试预言的受限语法。

3.2 TOGA:神经测试预言机生成

图 3 中描述的 TOGA 包含两个关键组件:异常 Oracle 分类器和断言 Oracle 排名器。

图3: TOGA总体框架

特殊的Oracle分类器,是一个根据二元决策进行微调的预训练 Transformer 模型任务。模型决定是否应该抛出异常通过单元上下文传达开发人员意图。如果分类器推断给定的测试前缀应该引发异常,TOGA 已找到异常的预言机,现在可以生成完成测试。结果测试出现预期异常 Oracle格式如第 3 节所示。否则,分类器预测输入不应引发异常,TOGA 会继续通过调用 Assertion Oracle Ranker 来测试生成过程。Assertion Oracle Ranker,类似地使用预训练的 Transformer 模型主干。为了解决现有神经断言生成方法的局限性,我们的方法将预言机推理视为对一小组数据的排名可能的共同预言机。我们使用它语法以及基于类型的约束来限制空间候选预言并强制语法和类型的正确性。这模型在对候选断言集进行排名时进行了微调给定测试前缀和单元上下文。集合中的每个断言都是排名,并选择排名最高的候选者作为断言Oracle。最后,TOGA 生成一个具有给定测试前缀的测试,并且推断断言预言机。

如前所述,Exceptional Oracle 分类器基于在预训练的 BERT 变压器模型上。特别是,我们使用CodeBERT模型同时接受自然语言和代码训练掩码语言建模。为了训练异常预言机分类器,我们针对异常任务对预训练模型进行了微调Oracle推论。微调是使用监督执行的数据集 D = ( (p, c),l)1, ...(p, c),l)n) 其中 p 是测试前缀,c 是单位上下文,l 是一个二元标签(l∈ 0, 1)。标签 1 表示样本应该引发异常,而标签 0 表示它不应该引发异常。

Assertion Oracle Ranker 也基于预训练的 Code BERT模型。为了训练断言预言机排序器,我们对断言预言机推理任务的预训练模型进行了微调。使用监督数据集进行微调D = ( (p, c, a),l)1, ...(p, c, a),l)n 其中 p 是测试前缀,c是单位上下文中,a 是候选断言,l是二进制标签 (l∈ 0, 1)。标签 1 表示给定的候选断言准确反映了开发者的意图。对于给定的 p和 c 只有一个 l 可以有标签为 1。候选集中的其他断言将具有负面标签。

为了生成候选断言集,我们使用我们的语法以及基于类型的约束来限制候选空间预言机并强制语法和类型的正确性。基于返回被测单元的值,我们迭代地构造一组候选人的主张。我们的断言候选生成算法如算法1所示。

我们描述了一种方法 TOGA 来推断功能测试预言给定测试前缀和单元上下文。然而,为了抓住bug,一个测试 bug 行为的测试前缀是必要的。为了获得高质量的测试前缀,我们使用随机测试生成工具EvoSuite。生成一组由覆盖率指导的测试。我们提取测试前缀通过从每个测试中剥离 EvoSuite 的预言机。如果出现以下情况:test 包含多个断言,我们为每个断言提取 test 前缀单独断言。对于每个生成的测试前缀,我们调用 TOGA 来推断测试预言。与一大套相结合试图覆盖整个单元的前缀,我们的方法能够生成功能测试预言来发现现实世界的错误。

RQ1 Oracle语法

我们在原始 ATLAS 数据集上评估 RQ1,其中包含从 Java 项目中挖掘出总共 188,157 个断言。回答RQ1,我们解析每个断言并检查它是否可以表达为基于断言方法名称和结构的语法AST 的。排除695个解析失败的样本后,我们发现154,523 (82%) 可以用我们的语法来表达。在 32,938 个断言中(18%)无法用我们的语言表达语法中,大多数(23,913,13%)使用我们认为的断言方法不包括(例如,assertThat、assertSame)。在许多情况下(74%基于对 50 个样品的手动检查),不匹配断言似乎在符号上等同于我们语法中可表达的断言(图 4)。

图4:红色突出显示的断言无法表达在语法。绿色符合我语法其他与我们的语法不符的断言 (5%) 包括对表达式而不是变量或文字进行相等断言。尽管我们故意排除像这样的通用断言在我们的语法中,我们注意到,对于在确定性环境中执行的测试,可以通过语法重写。

RQ2 Oracle 推理准确性

为了实现特殊的预言机推理(表 1),我们的实验设置涉及第 4.3 节中描述的Methods2Test* 数据​集。那里没有神经技术可以进行特殊的预言推理,我们都知道。相反,我们包括一个随机基线(加权coin)来说明问题空间的复杂性。硬币根据我们的分布执行随机选择训练集。在我们的训练集中,我们观察到 80% 的样本都不例外。因此,硬币预测负面标签经常(并且通常是正确的),但很少预测积极的结果。该硬币在准确性方面与我们的方法类似,但就 F1 分数而言明显更差,因为它很少预测正面标签正确。对于断言预言机推理(表 2),我们的实验设置涉及第 4.2 节中描述的 Atlas* 数据集。准确度度量是语法的:如果建议是准确的,则认为它是正确的词汇匹配。作为基线,我们与序列到序列进行比较(seq2seq)返回测试预言机模型[33]。 seq2seq 模型是使用光束对自然语言和代码进行预训练的 Transformer搜索解码器。与我们执行排名的方法相反通过一组模板断言,seq2seq 模型生成一个逐个测试预言机令牌。因此,该模型由于以下原因而受到影响:可能的预言机空间很大。我们报告了两项坚持的结果测试集:整体集和词汇内集。词汇内集合是可以用我们的语法表达的整个集合的子集以及基于本地和全球词典的词汇。我们的模型在词汇集上的准确率达到 96%,而之前的准确率仅为 63%通过 seq2seq 模型,总体准确率为 69%,相对准确率为 11%对 seq2seq 模型的改进。

词汇量消融。我们对 K(我们的全球词典的词汇量)进行了研究,以检验之间的权衡生成大量的候选断言并对它们进行排名准确断言候选人。图5 整体模型准确性、词汇表支持的样本百分比以及词汇表支持的样本的准确性ATLAS* 测试集。对于 K=0,全局字典未使用,仅变量和本地字典中的常量被视为断言生成。仅使用本地字典仍然可以生成正确的大约 50% 的样本的断言候选者测试集。增加K会导致模型精度略有下降,但会导致整体准确性提高,因为使用全局字典生成了更正确的断言候选。一旦词汇量变得太大,模型精度开始下降,并且设置较高的 Ks 会降低整体精度。在 RQ2 中,我们根据 ATLAS* 验证的调整设置 K=8放。此设置实现了高模型之间的最佳权衡候选集的准确性,并支持大量可能的断言。

表1:RQ2:卓越 Oracle 推理的评估

表 2:RQ2:断言预言机推理的评估

表 3:RQ3:总体错误查找。

图 5:全局字典大小 K 对整体准确性的评估

表 4:RQ3:按预言机类型发现的错误数量。

RQ3 Oracle 推理准确性

TOGA异常Oracle错误分析:对于单焦点方法,EvoSuite 通常会生成多个测试用例。对于某些聚焦方法(~10%),EvoSuite 生成异常和非异常输入状态。然而,TOGA 很少预测 (4%) 不同的异常无论输入状态如何,预言机都使用相同的聚焦方法。这观察表明 TOGA 主要调节焦点方法签名而不是特定的输入状态。

TOGA 断言预言机错误分析:我们对地面真实预言机进行了手动分析,发现总共229个预言机断言Oracle,有31人预测正确。剩余198预测可细分如下: 106真实情况断言无法用给定的词汇来表达,13无法用语法表达,9没有被预测因为TOGA错误地预测了一个特殊的神谕。在里面剩下的 70 个样本,可以表达真实的预言词汇和语法,但模型做出了错误的预测,导致 bug 到达的词汇准确率为 31%EvoSuite 测试。这明显低于 TOGA 96% 的词汇量ATLAS* 的准确性。性能差异表明ATLAS* 中的测试分布与 EvoSuite 的非常不同生成的测试。专门在 EvoSuite 上训练的模型生成(测试,预言机)对而不是 ATLAS* 对可能会产生更好的结果表现。

转述:冯晟

0 阅读:0

互联不一般哥

简介:感谢大家的关注