变异测试是AI系统测试中较为常见的一种测试方法。通过引入人工制造的缺陷来评估系统的健壮性。在AI系统测试实践中,变异测试解决了对测试套件进行有效性和充分性评估的难题。本文将重点探讨变异测试在AI系统测试中的执行流程,呈现一个完整的测试框架,以及优化变异测试的流程、提高测试效率的方法。
一、变异测试的基本概念
在介绍AI系统变异测试的执行流程前,我们首先需要了解变异测试,明确变异测试的基本概念。
变异测试(Mutation Testing)也称为基于变异的测试,其基本原理是通过对源代码进行变异设计来模拟软件缺陷,并通过对比源程序和变异程序在运行同一测试用例时的差异来评估测试套件的有效性和充分性,揭示其不足并进行针对性地改进。在变异测试中,在原程序中注入人为设计的语法错误的过程称为变异,被测试的程序基于一定的代码转换规则即变异算子,对源程序中的特定代码元素进行变异形成源程序的衍生程序即变异体。利用变异算子进行一次变异得到的衍生程序称为一阶变异体, 进行二次及以上变异得到的衍生程序称为高阶变异体。
变异测试之所以具有可行性,主要基于以下两条假设:
(1)熟练程序员假设
经验丰富的程序员在编写代码时即使出现缺陷,这些缺陷通常也会很简单,往往与正确代码相去不远,只需要进行细微调整即可修复。在变异测试中,这意味着通过在代码中引入小的、可控的变更(即变异),可以模拟程序员可能引入的缺陷。基于这一假设,变异测试通过在原程序上实施微小的改动,能够模拟熟练程序员的实际编程过程,从而有效地揭示代码中的潜在问题。
(2)变异耦合效应假设
这个假设关注的是测试用例对于不同变异体之间的相关性。代码中的不同部分可能会以不可预测的方式相互影响。如果一个测试用例能够检测到一个简单变异体(即小的、单一的代码变更)的缺陷,那么这个测试用例很可能检测到更为复杂的变异体(即多个小的代码变更综合起来的结果)的缺陷。这意味着,不必测试所有可能的变异组合,可以通过测试一些简单的变异体来推断更复杂变异体的测试情况。这大大减少了测试的复杂性和所需的时间和资源。
作为对测试套件的有效性和充分性进行评估的常用技术,变异测试在人工智能测试领域展现出独特的价值。人工智能模型和系统内部往往嵌入了众多复杂的逻辑和算法,往往是传统测试方法难以触及的。传统覆盖测试(如语句覆盖、分支覆盖等)与测试用例的缺陷检测能力没有很强的联系,而变异测试针对AI系统测试中的测试充分性问题,提供了一种有效的评估方法。通过评估和优化测试用例和测试数据集,测试人员可以逐步提高测试的覆盖率和有效性,确保AI系统的稳定性和准确性。
(如有人工智能系统测试服务、人工智能系统测试能力搭建、人工智能测试工具选型、人工智能测试技术交流、人工智能测试实验室建设等需求,可私信我。)
二、AI系统变异测试的基本流程
变异测试在AI系统中的应用价值不言而喻。如何有效地实施这一测试方法,却是一个值得深入探讨的问题。接下来,我们将详细介绍AI系统变异测试的基本流程,从测试准备到结果分析,为大家呈现一个完整的测试框架。
人工智能系统变异测试的目的是提高测试数据的质量和覆盖率,帮助发现和修复人工智能系统中的潜在缺陷,其基本思路与主体框架与传统软件的变异测试相似。具体来说,变异测试的基本流程可以概括为以下几个环节:
1. 生成变异体
从原始程序P出发,利用一系列预设的变异算子生成一组变异程序M,这些变异程序用来模拟可能的程序缺陷或错误。
在变异测试中,变异体的生成技术即变异技术是核心。传统的变异技术大多遵循程序语法规则,使用预先定义的变异算子进行变异。这些变异算子通常是人工设计的,以确保生成的变异体仍然是有效的程序,常见的基于语法规则的变异技术包含Jester、MuJava、Jumble和MAJOR等。随着变异测试的发展, 研究者们提出很多不同的变异技术以支持软件测试的各项研究。
现在的人工智能系统主要基于深度学习网络。差分测试通过学习开源项目历史代码生成变异体,典型的技术有 DeepMutation, µBERT和 LEAM等方法,以应对人工智能模型特有的复杂性和不确定性。由于被测对象由转变为复杂的深度学习模型,AI系统测试中变异算子的设计存在显著差异,变异算子的设计需要考虑更多的维度和因素。
在人工智能系统的变异测试中,常见的变异算子包括但不限于以下几类:
模型结构变异:这类变异算子直接对深度学习模型的结构进行修改,如删除或添加神经元、层,修改神经连接等。这些变异可以模拟模型设计上的潜在缺陷,从而揭示出模型在结构上的脆弱性。
权重与偏置变异:通过对模型的权重和偏置进行微小的修改或重置,可以模拟训练过程中的误差或噪声。这类变异有助于发现模型在权重和偏置调整方面的潜在问题。
激活函数变异:激活函数是深度学习模型中非常关键的一部分,改变激活函数或引入新的激活函数可以模拟模型在非线性转换方面的潜在缺陷。
除了上述针对模型本身的变异算子外,还有一类针对训练数据的变异算子。
训练数据变异:这类变异算子直接对深度学习模型的原始训练集进行操作,如删除某些特定的训练数据、更改训练数据的标签或引入噪声等。通过模拟训练数据中的潜在问题,这类变异可以帮助发现模型在数据泛化能力方面的缺陷。
2. 检测原始程序
使用测试用例集T对原始程序P进行测试。如果测试用例集中有任何一个用例导致P运行失败,说明P中存在错误,需要修复P并重复此测试步骤,直至P能够通过所有测试用例。
3. 执行变异体
成功验证原始程序P后,执行变异程序M中的每个变异体m。针对每个变异体m,运行测试用例集T,并观察结果。
4.结果分析
如果测试用例集T中存在至少一个测试用例t,使得在变异体m和原始程序P上的执行结果不同,则称测试用例t能“杀死”变异体m。这表明该测试用例能有效区分原始程序与变异体之间的行为差异。
若没有任何测试用例能杀死某个变异体m,则称该变异体为“存活变异体”。存活的变异体可能是等价变异体(即尽管在形式上与原程序有所不同,但在功能上等同于原程序)或者是当前测试用例设计不足以检测出的非等价变异体。
需要注意的是,变异测试通常使用变异得分(Mutation Score,MS)来评价现有测试套件的有效性的关键指标。变异得分是被杀死变异体与全部变异体的比值,按照以下公式进行计算。其中,|kill(M,T)|表示被杀死的变异体的数目,|M.all|表示所有变异程序的数目,|M.equiv|表示等价变异程序的数目,且满足|kill(M,T)|≤|M.all|-|M.equiv|。
变异得分MR的数值介于0与1之间,数值越高,表明测试用例集杀死的变异程序越多,其缺陷检测能力越强,反之则越低。当MR的值为0时,表明测试用例集没有杀死任何一个变异程序;当MR的值为1时,表明测试用例集杀死了所有的非等价变异程序。
5.优化迭代
当发现存活变异体时,要进一步分析以识别出其中的等价变异体,并将其从变异体集合M中移除。对于非等价的存活变异体,需要开发新的测试用例来增强测试集T的检错能力,以便在未来的测试中能够杀死这些变异体。
变异测试是一个动态的测试过程,需要通过不断地生成变异程序、执行测试用例、分析结果并改进测试用例集,确保测试的充分性和有效性。不断重复上述步骤,增加或改进测试用例,减少存活变异体的数量,直到达到目标——测试用例集变异得分为1,表明测试用例集具有良好的错误检测能力。
三、优化AI系统变异测试的方法
AI系统变异测试的基本流程已经相对清晰,但在实际操作中,我们仍需要不断寻找优化的方法,以提高测试的效率和质量。在本部分,我们将分享一些优化AI系统变异测试的策略和方法,帮助大家更好应对AI系统变异测试过程中的挑战。
变异测试在AI系统等大型程序中的应用面临一个显著挑战,即产生数量庞大的变异体会导致测试成本剧增。为了克服这一难题,测试人员通常关注变异体选择优化和执行优化两个方面,致力于降低变异测试在实际测试实践中的代价。
1.变异体选择优化
主要关注如何减少变异体的数量,从而降低成本。这一领域的研究包括随机选择法、聚类选择法、变异算子选择法以及高阶变异等多种方法。随机选择法通过随机抽取部分变异体进行测试,降低测试规模;聚类选择法则基于变异体的相似性进行分组,选择代表性变异体进行测试;变异算子选择法关注于选择对程序行为影响较大的变异算子,以减少无效变异体的生成;而高阶变异则通过组合多个低阶变异来生成更高效的变异体。
变异体选择优化的具体方法,整理如下:
2.变异体执行优化
主要关注如何缩短变异测试的时间。这包括变异体检测优化、变异体编译优化以及并行执行变异体等策略。变异体检测优化通过改进检测算法,提高检测效率;变异体编译优化则针对变异体的编译过程进行优化,减少编译时间;并行执行变异体则利用并行计算资源,同时执行多个变异体的测试,从而显著缩短测试时间。
变异体执行优化的具体方法,整理如下:
通过变异体选择优化和执行优化两类方法,我们可以从不同角度提高变异测试的效率,降低测试成本,使其在AI系统等大型程序的测试实践更为广泛和实用。
以上就是AI系统变异测试的基本概念、基本流程和优化方法的全部内容了。如有人工智能系统测试服务、人工智能系统测试能力搭建、人工智能测试工具选型、人工智能测试技术交流、人工智能测试实验室建设等需求,可私信我。
参考文献
[1] 田甜,邵阳阳,王苗苗,等.基于程序依赖关系的变异体生成策略.计算机应用.2024.
[2] 党向盈,李金凤.融合变异测试的路径覆盖测试数据进化生成方法.软件工程,2023.
[3] 巫浩然.面向Solidity语言的变异测试系统设计与实现.2020.
[4] 张功杰,巩敦卫,姚香娟.基于统计占优分析的变异测试.2015.
(本文引用部分内容版权属于原作者,仅作交流探讨,如有侵权请联系删除。谢绝转载)