软件功能测试的用例设计(基于日志的系统级测试用例切片)

软件功能测试的用例设计(基于日志的系统级测试用例切片)(1)

引用

Messaoudi, S., Shin, D., Panichella, A., Bianculli, D., & Briand, L. (2021). Log-based Slicing for System-level Test Cases. In 2021 ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA).

摘要

回归测试是软件测试中最重要的活动之一。然而,如果复杂系统测试用例设计糟糕,它的成本效益和实用性会大大降低,并且需要大量的时间和资源来运行测试。缓解这个问题的一种方法是将系统测试用例分解成更小的、独立的测试用例——每个测试用例只有一个测试场景和断言——每个测试用例的执行时间就比原始的测试用例低,同时原始测试用例的测试有效性被保留。这种分解可以通过程序切片技术来实现,因为测试用例也是软件程序。然而,当(1)测试用例使用外部资源,(2)代码检测不是一个可行的选择,以及(3)测试执行代价昂贵时,现有的静态和动态切片技术就会有很大的局限性。

本文提出了一种新的分解系统测试用例的方法 DS3(Decomposes System teSt caSe),该方法可以自动将一个复杂的系统测试用例分解为独立的测试用例切片。其思想是使用测试用例执行日志来识别由静态切片生成的切片中“隐藏”的依赖关系。由于日志包含关于被测试系统的运行时信息,我们可以使用它们来提取全局资源的访问和使用,并细化由静态切片生成的片。

我们评估了 DS3 的切片效率,并将其与普通的静态切片工具进行了比较。我们还将 DS3 得到的切片与相应的原始系统测试用例进行了测试效率和有效性的比较。评估结果表明,DS3 能够准确地识别与全局资源使用相关的依赖关系。此外,生成的测试用例切片平均比原始系统测试快 3.56 倍,并且在故障检测有效性方面没有明显损失。

引言

回归测试是对现有代码库进行更改时使用的一种质量保证技术。它保证所执行的更改不会损害代码现有部分和未更改部分的行为。由于被测系统(SUT)的内在复杂性,以及多年软件开发积累的技术债务,系统测试用例通常包含多个测试场景,并将其合并到一个测试用例中。这些测试通常被称为迫切测试,会对回归测试产生负面影响。在我们的工业环境中,迫切测试需要几个小时才能运行完。然而,如果这种复杂的系统测试用例可以分解成更小的测试用例而不失去它们的测试有效性,那么分解的测试用例的执行时间将会减少,测试用例优先级的成本效率将会提高。

在本文中,我们将一个复杂的系统测试用例切片成更简单的用例——提出一种称为 DS3(分解系统测试用例)的新方法,该方法基于日志的分析来补充静态切片。由于日志包含关于 SUT 的运行时信息,我们可以使用它们来提取访问全局资源和执行的动作,在原始系统测试用例中执行每条语句。通过这种方式,我们可以重新构建由使用全局资源定义的语句之间的附加依赖关系。

背景知识

(1)日志。日志是日志条目的序列;日志条目包含时间戳(记录记录的事件发生的时间)和日志消息(记录记录的事件)。日志消息可以进一步分解为消息模板,描述事件类型和事件的参数值,这些参数值是在运行时确定的。

(2)静态切片。静态切片是一种技术,使用 def-use 分析,隔离一个程序的“切片”,它影响程序中特定语句中一个或多个变量的值的计算。

基于日志的测试用例分解

我们的新方法称为 DS3,它将包含多个测试场景的复杂系统测试用例分解为多个单独的系统测试用例,每个测试用例只包含一个测试场景及其相关断言子集,同时保留由于使用全局资源而隐藏的依赖关系。因为测试执行日志包括关于被测试系统的运行时信息,我们可以使用它们来提取被访问的全局资源(例如,文件,数据库)和执行的动作(例如,读,写)在原始(未切片)系统测试用例中执行每条语句。通过这种方式,我们可以重建在运行时由全局资源生成的语句之间的隐藏依赖关系,这些语句没有被静态切片标识。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(2)

图 1

DS3 以系统测试用例、测试用例对应的执行日志、全局资源相关的日志消息模板为输入;它返回一组切片,每个切片执行一个单独的测试场景并包含更少的断言。在我们的运行示例中,DS3 采用系统测试用例 Tsys(图 1 顶部)及其对应的日志 Lsys(图 2),并返回理想切片 I1 和 I2(图 1 中间和底部)。工程师只需在日志中标记与全局资源相关的日志消息模板,例如 output.csv。例如,Lsys 中的日志条目 e1 表示对文件 setup.csv 执行了“读取”操作。因此,通过查看每个消息模板,例如 read file *,工程师可以轻松识别它是否与全局资源的使用有关。然后,DS3 使用基于日志的分析自动识别 s1 和 s2 之间的隐藏依赖关系,并通过细化静态切片生成的中间切片来生成 I1 和 I2。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(3)

图 2

我们的方法不需要访问源代码。因此,它可以应用于由第三方组件组成的软件系统。然而,我们需要满足两个条件才能应用 DS3:(1)在测试用例中的语句和日志中的消息之间存在可追溯性信息,(2)日志包含一些关于全局资源使用的信息。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(4)

算法 1

算法 1 提供了 DS3 的伪代码。它以系统测试用例 T=<s1,…,sn>作为输入,其对应的执行日志 L=<e1,…,ek>,以及日志消息模板集 MTG={mt1,…,mtn}标记为与 L 中全局资源的使用相关;它返回一组分解的测试用例(即切片)D={D1,…,Dj}。

算法 1 包括四个主要阶段:(1)基于断言的反向切片,(2)使用日志对全局资源的 def-use 分析,(3)切片细化,以及(4)切片最小化。反向切片阶段从 T 生成静态切片 D。全局资源定义使用分析阶段识别 T 中的语句、L 中与全局资源相关的日志条目以及对后者执行的操作之间的关系,使用 L 和 MTG.然后在切片细化阶段使用所得的三元组 Gdu 来细化每个静态切片 D∈D。最后,切片最小化阶段删除 D 中的任何冗余切片。算法以返回最小化的 D 结束。

实验评估

我们将 DS3 作为一个 Python 程序实现,使用 Python Program-Analysis 工具包执行静态切片。我们评估的候选基准满足以下需求:(1)它包含系统或集成级测试用例,(2)测试用例应该在执行时生成日志,以及(3)测试用例应该访问/使用全局资源(例如,外部文件,数据库,远程资源)。这些要求由一个专有的基准来满足,以下称为 Prop,由我们的一个活跃在卫星行业的工业合作伙伴提供。

(1) 切片效果

为了评估切片的有效性,我们在两个基准上运行 DS3 和基线静态切片工具,获得两组切片测试用例(每个工具生成一个)。我们使用了以下度量:

软件功能测试的用例设计(基于日志的系统级测试用例切片)(5)

其中 D 是由给定方法(DS3 或基线)产生的一组切片。在公式中,分子表示不会导致编译或运行时错误的测试片的数量;分母表示生成的切片的总数。Eff 的取值范围为 0~1,Eff(D)值越大,意味着所分析的技术在生成不遗漏任何依赖关系的正确切片时更有效。

表 1 报告了我们的方法和基线产生的切片的数量。“System”列表示基准的名称;列“#Test Cases”指示要切片的原始测试用例的数量;“Total”、“Pass”、“Fail”列分别表示获得的切片总数、执行时成功通过的测试用例切片数、执行时失败的测试用例切片数;“Eff(D)”列表示方法的切片有效性。结果表明,静态切片机的切片效率低于 DS3。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(6)

表 1

(2)切片测试用例的效率

我们将生成的测试片的执行时间与原始(非切片)测试用例的执行时间进行了比较。由于测试用例的执行可以改变环境(例如,通过创建或修改一个文件),我们在运行每个测试用例之前重新设置环境,以避免任何不正确的结果。我们将每个测试运行 10 次,以考虑测试执行时间中的不确定性。我们还评估了 DS3 的开销,DS3 内部阶段所花费的平均时间和切片一个给定测试用例的总执行时间,通过测量超过 10 次执行。

表 2 显示了运行 DS3 生成测试切片的时间,以及执行生成的切片和原始测试用例的时间。更具体地说,列“Others”、“Static”和“Refine”表示执行 DS3 不同阶段的平均时间:查找全局资源定义和使用以及最小化步骤(“Others”)、静态切片(“Static”),切片细化(“Refine”);“Total”一栏表示 DS3 的平均总执行时间;“Slices”列表示 DS3 产生的切片数;“Org”列表示原始(非切片)测试用例的执行时间;列“Sl.Avh”和“Sl.Tot”分别表示切片测试用例的平均执行时间和累积执行时间,其中后者表示为每个单独的系统测试用例获得的所有切片的执行时间之和;“Speedup”列表示未切片测试用例的执行时间与切片测试用例的累积执行时间之间的加速比。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(7)

表 2

结果表明,对于 30 个测试用例中的 24 个,DS3 生成的测试用例片的累计执行时间比原始测试用例短,平均加速速度为 3.56 倍。

测试用例 PTC30 可以观察到最大的加速(23.14 倍)。本例中,5 个片的累计执行时间平均为 1004s(≈17 分钟);相反,执行原始测试用例需要 23231 秒(≈387 分钟,即超过 6 个小时)。这个很大的差异是由于规避了无关语句的执行:在原始的测试用例中,一个昂贵的过程实际上与测试用例中的其他语句没有任何依赖关系;实际上,DS3 成功地在它生成的测试用例切片中确定并排除了这个过程。

在剩下的 6 个测试用例中,测试片的总执行时间高于原始测试用例的执行时间。我们观察到 PTC5 的加速比的最低值(即最高的减速,0.53):原始测试用例的执行时间为 465s,而 DS3 产生的两个切片的累计执行时间为 874s。为了进一步理解执行时间大幅增加的根本原因,我们手动分析了 PTC5 及其相应的切片。我们发现,对于这种情况,DS3 创建了两个独立的测试片段,每个片段都有测试设置代码的相同副本;执行此设置代码会占用文本大小写片段的大部分执行时间。

(3)覆盖范围和故障检测能力

为了度量代码覆盖率,我们使用了 Bullseye coverage——一种高级 C 代码覆盖率工具,用于提高关键系统领域的软件质量,如工业控制、医疗、汽车、通信、航空航天和国防。接下来,我们使用突变测试来评估原始测试用例和切片之间的故障检测能力的差异。

对于突变分析,我们使用了 mutate ,这是一个开源的突变测试工具。Mutate 提供了 15 个突变操作符,包括算术、条件、布尔、数字和行删除操作符。我们在计算中考虑了以下变异运算符:(1)逻辑运算符,(2)条件运算符,(3)递增小数运算符,(4)算术运算符,(5)布尔文字运算符,(6)十进制数运算符。

为了评估 DS3 的切片过程与原始测试用例(组 2)相比,是否没有影响测试切片(组 1)的故障检测能力,我们比较了每组杀死的突变体数量。我们用 KO 表示被原始测试用例杀死的突变体集合,用 KS 表示被 DS3 生成的测试切片杀死的突变体集合。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(8)

表 3

表 3 报告了原始测试用例和生成的测试片段的代码覆盖率。“FunctionCov”和“BranchCov”列分别表示功能覆盖和分支覆盖得分;子栏“Total”表示系统源代码中功能/分支的总数;子列“Org”和“Slices”分别指示了原始测试用例和切片所覆盖的功能/分支的数量。

在功能覆盖率方面,原始的测试用例和生成的切片都达到了 61%(1831/2980)。我们观察到分支覆盖率的一个非常小的差异:原始的测试用例覆盖了代码分支的 42.36%(5736/13541),而生成的切片覆盖了代码分支的 42.08%(5698/13541)。

软件功能测试的用例设计(基于日志的系统级测试用例切片)(9)

表 4

表 4 为突变检测结果。对于最初的系统测试用例,有 289 个突变体被杀死。生成的测试片能够杀死 288 个突变体,正如预期的,这些突变体都被原始的测试用例杀死了。

实际意义

我们认为 DS3 有助于解决两种问题:assertion roulette 和 eager tests。assertion roulette 是一个带有多个断言语句的测试,这使得测试失败时的根本原因分析更加困难。eager tests 会同时检查多个不同的功能,这会对测试代码的可读性和可理解性产生负面影响。在给定的系统测试用例上执行 DS3 将产生多个片,每个片有更少的断言语句和一个单独的测试场景。由于 DS3,原始测试用例的断言将分布在生成的片上,从而减少了每个片的断言数量(assertion roulette)。此外,将测试用例分割成独立的片段有助于解决 eager tests。

尽管 DS3 有不可忽略的开销,但它只需要运行一次,因此它对测试成本的影响是有限的。使用 DS3 的优点是生成的片开销较小。减少测试执行时间是测试用例选择和优先级确定的目标之一。此外,可以根据设置配置、输入值或目标功能对测试片进行分组。可以为每个组进一步选择片,以只运行最具代表性的测试片,并进一步降低总体测试执行成本。

在测试用例选择和优先级划分中使用的两个常见目标是覆盖率(最大化)和测试执行(最小化)。开发人员可以使用 DS3 选择与原始测试用例达到相同覆盖率和变异分数的测试片段,但执行时间显著减少。

结论

在本文中,我们提出了一种新的方法 DS3,将具有多个测试场景的复杂系统测试用例分解为独立的切片测试用例,每个测试用例运行一个测试场景。DS3 利用了在过去的回归测试会话中收集的静态切片和执行日志。其主要思想是使用包含关于 SUT 的运行时信息的日志来识别由于访问和使用全局资源而导致的测试语句之间的依赖关系;这些依赖关系用于细化由静态切片生成的切片测试用例,而静态切片往往会忽略这些依赖关系。在一个专有系统和一个开源系统上进行的评估结果表明,基于日志的切片细化确实有效地避免了生成的切片测试用例中由于缺少依赖而导致的编译或运行时错误。此外,生成的测试用例切片平均比原始系统测试用例快 3.56 倍,在故障检测能力方面没有显著损失。

作为未来工作的一部分,我们计划评估使用 DS3 对回归测试活动的成本效益的影响,比如测试用例的优先级。我们还计划扩展 DS3 以支持不同的编程语言,并在其他基准上对其进行评估。由于基于日志的切片的思想不仅适用于测试用例,而且也适用于一般的程序源代码,我们将进一步研究回归测试之外可能的应用程序。

致谢

该工作已获得卢森堡国家研究基金(FNR) No C-PPP17/IS/11602677 和加拿大 NSERC Discovery 和 CRC 项目的资助。

本文由南京大学软件学院 2021 级硕士曹智豪转述翻译。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页