生成突变体(实际问题)

生成突变体(实际问题)参数的值 我们可以有选择地激活或停用变异 从而允许我们比较原始代码和变异代码在不同条件下的行为

大家好,欢迎来到IT知识分享网。

生成突变体

变异算子
我们通常使用突变算子来生成突变体
操作员可能是,例如:
用 * 替换 +
用另一个变量 y 替换表达式中的变量 x
用另一个变量替换赋值的 LHS 上的变量 x变量 y
删除一个声明





在计算机编程中,术语“LHS”代表“左侧”。 它是指出现在赋值运算符 (=) 左侧的赋值语句部分。 LHS 是您指定要为其分配新值的变量或内存位置的位置。

例如,考虑以下赋值语句:

x = 10 

在这种情况下,LHS 是变量“x”。 它是将存储值 10 的目标位置。

如果您想用另一个变量“y”替换 LHS 上的变量“x”,您可以将赋值语句修改为:

y = 10 

现在,变量“y”成为赋值的 LHS,值 10 将存储在与“y”关联的内存位置。

一阶突变体First Order Mutants
(1) 一个突变体是一个一阶突变体,如果它可以通过一次应用一个突变算子产生。
(2) 通常只使用一阶突变体:这限制了产生的突变体数量。
(3) 如果一个突变体不是一阶突变体那么它就是一个高阶突变体。
(4) 一阶突变体的使用通常通过以下方式证明是合理的:
耦合效应:如果我们杀死一阶突变体,那么我们就杀死了(大多数)高阶突变体
有能力的程序员假设:真实代码接近于正确(因此类似于正确的一阶突变体在程序里面)
(5) 这些假设的一些证据——但证据有限






Example

We might mutate this x=x+1; if (x>0) y=y+1; else y=y+2; I To form this x=x+1; if (x>0) y=y-1; else y=y+2; I Or this x=x+1; if (x>0) y=x+1; else y=y+2; I Or x=x+1; if (x>=0) y=y+1; else y=y+2; 

杀死一个变种体
假设突变体 p0 是通过突变 p 的程序语句 s 形成的。
然后杀死 p0 我们需要找到输入:
(1) 执行:驱动程序执行到s。
(2)感染:导致s后不同的状态(即不同的一些变量的值,可能是程序指针)。
(3) Propagation:传播这种状态上的差异,形成不同的输出。
PIE框架





PIE 框架,在突变测试的背景下,代表“潜在感染效应”。 它是一种系统方法,用于确定代码中的特定突变是否被相应的测试用例“杀死”。

  1. 潜力:第一步是确定代码中发生突变的可能性。 突变通常是通过对原始代码进行小的更改来引入的,例如更改运算符、删除语句或修改常量。
  2. 感染:引入变异后,下一步就是将变异代码应用到现有的测试套件中。 变异的代码与测试用例一起执行,以确定它们中的任何一个是否能够“感染”变异。 换句话说,测试用例应该能够触发由突变引起的改变的行为。
  3. 效果:最后,通过比较变异代码的行为与原始代码的行为来分析变异的效果。 如果原始代码和变异代码的测试用例结果不同,则表明变异已被测试用例“杀死”,因为它检测到更改并产生了不同的输出或行为。
    PIE 框架有助于系统地评估测试用例在检测突变方面的有效性。 目标是确保测试套件有效捕获突变,从而提高软件的整体质量和可靠性。
Recall the following example, and assume that values for x and y are output. x=x+1; if (x>0) y=y+1; else y=y+2; The following mutant x=x+1; if (x>0) y=y-1; else y=y+2; 
Recall the following example, and assume that values for x and y are output. x=x+1; if (x>0) y=y+1; else y=y+2; The following mutant x=x+1; if (x>=0) y=y+1; else y=y+2; 

为了确定这个突变体是否被测试用例杀死,我们可以考虑两种情况:

  1. 当 x = -1 且 y = 11 时:
    • 原代码中,由于x小于0,执行else分支,y变为11 + 2 = 13。
    • 在突变代码中,x 仍然小于 0,但条件 (x >= 0) 为真。 因此,执行 if 分支,y 变为 11 + 1 = 12。
    • 原始代码和突变体代码的输出不同,表明突变体已被该测试用例杀死。
  2. 当 x = 1 且 y = 11 时:
    • 在原始代码和变异代码中,x 都大于 0,因此执行 if 分支。 在这两种情况下,y 都变为 11 + 1 = 12。
    • 原始代码和突变体代码的输出相同,表明突变体没有被这个测试用例杀死。

覆盖面和充分性标准Coverage and Adequacy Criterion
(1)假设我们形成一个程序 p 的突变体集合 M。
(2) 我们有一个相关的覆盖率度量:M 中被测试套件杀死的突变体的百分比。
(3) 有一个相关的充分性标准:我们需要杀死所有突变体。


等效突变体
(1) 如果没有可能的输入杀死 p0,则 p 的突变体 p0 是等价突变体。
(2) 则 p0 在句法上不同于 p 但在语义上相等的。

在突变测试中,等效突变体是原始代码的突变版本,其行为方式与所有可能输入的原始代码相同。 换句话说,等效突变体是不会改变程序的可观察行为的突变体。

为了进一步解释这个概念,让我们考虑一个例子:

原始代码:

def calculate_square(x): 返回 x * x 

突变代码(p0):

def calculate_square(x): 返回 x 2 

(3) 等价性可能更复杂——它可能取决于突变发生的上下文

i f ( x>y ) y=y+1; e l s e x=x+1; a=x ; w h i l e ( x>y ) y=y+x ; b=y+1; 

问题
这些会导致问题,因为:
(1) 我们无法杀死它们:理想情况下我们将覆盖更新到被杀死的非等价突变体的百分比。
(2) 然而,除非我们检测到等效的突变体,否则我们无法测量这种覆盖率。
(3) 等价性不可判定。
通常,求助于人工测试人员——但这很昂贵




经典的覆盖标准是用于通过测量代码在测试期间被执行的程度来评估测试用例的充分性的指标。 这些标准旨在确保代码的不同部分已被执行或被测试用例覆盖。 一些常见的经典覆盖标准包括:

  1. 语句覆盖率:该标准确保代码中的每条语句在测试期间至少被执行一次。 它测量测试套件覆盖的语句的百分比。
  2. 分支覆盖:分支覆盖旨在确保代码中所有可能的分支或决策点都已被执行。 它测量在测试期间采用或不采用的分支的百分比。

3.路径覆盖:路径覆盖旨在覆盖代码中所有可能的执行路径。 它确保分支和循环的每个可能组合都经过测试。

  1. 条件覆盖:条件覆盖检查布尔条件(真和假)的所有可能结果是否已在测试期间得到评估。 它确保已执行代码中的每个条件。
  2. 函数/方法覆盖率:函数或方法覆盖率测量在测试期间被调用或调用的函数或方法的百分比。

这些经典的覆盖标准提供了测试套件执行代码的程度的定量度量。 它们有助于识别未经过充分测试的代码区域,可能表明测试覆盖率存在差距。

实际问题
(1) 我们已经看到突变测试可以包含经典的覆盖标准。
(2)杀死突变体和找茬之间有更清晰的联系。
(3)可以直接测试生成:我们生成杀死突变体的测试用例。
(4)然而:
突变测试没有被广泛使用(但它被使用)。
主要用于评估测试生成技术的有效性
(5) 即使是小程序也可能有很多变异体。
我们需要生成并编译所有这些。
我们对它们运行测试用例。
(6) 等价突变体会使报道产生误导和浪费精力。
理想情况下,我们希望消除这些。
一个困难的过程——通常是手动的,如此昂贵且容易出错(特别是如果我们有很多突变体!)。
(7) 我们可能会使用一个子集,而不是使用整套建议的变异算子。
(8) 人们对运营商的子集感兴趣,例如:
它们导致突变体数量显着减少,实现线性。
如果我们杀死使用选定集生成的所有突变体,我们也会杀死几乎所有使用完整集生成的突变体。
(9)这种方法称为选择性突变。
(10)注意:从一组突变体中随机抽样也有帮助。
(11) 基本思路:我们用一个程序来捕获所有的突变体。
(12) 可以通过使用“切换”开/关突变的参数来实现。
(13)这减少了编译时间和占用的空间
突变体。
例子:






















Recall the following example. x=x+1; if (x>0) y=y+1; else y=y+2; The following mutant x=x+1; if (x>0) y=y-1; else y=y+2; We can introduce parameter mut to control whether the mutation occurs. x=x+1; if (x>0) { 
   if (mut) y=y-1; else y=y+1;} else y=y+2; 

变异代码中引入了 mut 参数, 允许在代码中进行受控突变。 使用 mut 参数的目的是有选择地启用或禁用突变,从而便于比较原始代码和突变代码之间的行为。

通过引入 mut 参数,我们可以创建两种不同的场景:

  1. mut 设置为 True 时:
    • 如果条件 (x>0) 为真,变异代码 y=y-1; 将被执行。
    • 此更改改变了原始行为,因为它从“y”中减去 1 而不是加 1。
    • 此场景有助于评估测试套件检测引入突变的能力。
  2. mut 设置为 False 时:
    • 如果条件 (x>0) 为假,变异代码 y=y+1; 将被执行。
    • 此更改保留了原始行为,因为它将 1 添加到“y”。
    • 此场景用作控制案例,以确保测试套件不会错误地将不存在突变标记为检测。

通过切换 mut 参数的值,我们可以有选择地激活或停用变异,从而允许我们比较原始代码和变异代码在不同条件下的行为。 这种受控方法提供了一种方法来评估测试套件在检测引入的特定突变方面的有效性。

依赖分析是一种静态程序分析技术,用于识别和分析不同程序元素(例如变量、语句或指令)之间的依赖关系。 它旨在确定这些程序元素之间的关系和数据流。

依赖性分析的主要目标是了解一个程序元素的变化如何影响代码中的其他元素。 通过识别依赖关系,可以进行优化、检测潜在问题并避免在突变测试期间生成某些类型的等效突变体。

主题变奏Variations on a Theme——语言
(1) 可以改变模型或规范——而不仅仅是代码。
(2) 模拟不同类型故障的潜力。
(3) 如果模型是可执行的(或可以映射到代码),则有帮助。
(4) 或者,如果存在不可执行的语义就足够了(因此我们可以推断是否可能有共同的输出)。



主题变奏——杀戮的其他概念Other notions of killing
弱杀死突变体的概念已被定义:
如果突变语句被执行,这导致不同的状态。
所以:需要执行和感染但不需要传播。
传统定义则称之为强杀strong killing。



免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132430.html

(0)
上一篇 2025-07-31 17:10
下一篇 2025-07-31 17:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信