什么是变异测试?

一、变异测试的目的

变异测试是一种软件测试技术,用于评估测试用例的有效性。其核心思想是通过在源代码中引入人为的缺陷(称为“变异”),然后运行测试用例,检查这些变异是否被检测到。如果测试用例能够发现这些变异,说明它们有效;否则,测试用例可能需要改进。

二、变异测试的步骤

  • 生成原始程序:首先需要一个正确的程序版本。
  • 创建变异体:通过修改源代码生成多个变异体,每个变异体包含一个小的人为错误。
  • 运行测试用例:对原始程序和所有变异体执行相同的测试用例。
  • 比较结果:如果某个变异体在测试中失败(即被“杀死”),说明测试用例有效;如果通过(即“存活”),则测试用例可能不够充分。
  • 分析结果:根据变异体的存活率评估测试用例的质量。

三、变异测试的举例

假设有一个简单的Python函数,用于计算两个数的和:

def add(a, b):
    return a + b

生成变异体
我们可以通过修改代码生成多个变异体,例如:
变异体1:将+改为-

def add(a, b):
    return a - b

变异体2:将+改为*

def add(a, b):
    return a * b

变异体3:将+改为/

def add(a, b):
    return a / b

运行测试用例
假设我们有以下测试用例:

def test_add():
    assert add(2, 3) == 5
    assert add(-1, 1) == 0
    assert add(0, 0) == 0

比较结果
原始程序:所有测试用例通过。
变异体1:add(2, 3)返回-1,测试失败,变异体被“杀死”。
变异体2:add(2, 3)返回6,测试失败,变异体被“杀死”。
变异体3:add(2, 3)返回0.666...,测试失败,变异体被“杀死”。
在这个例子中,所有变异体都被测试用例发现,说明测试用例有效
因为测试失败,所以说明之前的用例有效,被测代码有改动(有变异)。在未修改源代码之前,测试用例理论上是可以通过;现在修改代码(有变异)后,按照逻辑,原本的测试用例就通不过了;若还能通过,则说明有极大可能性的测试用例无效,须补充完善。

 

四、常见的变异类型

基于变异测试,我们对测试用例有效性的定义是: 有效性=发现的变异数量÷注入的变异总数
从原理上讲,代码变异主要分为以下三类:

  • 第一类可以称为等效变异。例如,把a+b变成a-(-b)。这种变异我们不做,因为它不是一个bug。
  • 第二类可以称为实际等效变异。例如,把int类型变成short类型,理论上会有溢出的问题。一般情况下,大家很少用short类型,只要是整数就直接用int类型,但值的范围无论如何都不会超过几十或者几百。比如,变量numberOfDays的值是天数(number of days),这种变异我们也不做。
  • 第三类变异为运算符类的变异。几乎都是bug,很清楚,没有争议。我们主要做的就是这类变异。
变异类型 例子
算数运算符 +改成-,++改成--
关系运算符 !=改成==,>改成<
逻辑运算符 &&改成||
赋值运算符 +=改成-=
布尔值 true改成false
循环结构 break改成continue
函数调用 把setWhitelist(values)改成setBlacklist(values)
删减代码 把try...catch...finally里的catch或者finally删掉

 

五、变异测试的优点和缺点

优点

  • 评估测试用例质量:通过变异体的存活率,可以判断测试用例的充分性。
  • 发现潜在缺陷:帮助识别测试用例未覆盖的代码路径。
  • 改进测试用例:指导开发更全面的测试用例。

缺点

  • 计算成本高:生成和运行大量变异体需要大量计算资源。
  • 等价变异体问题:某些变异体可能在功能上与原始程序等价,难以检测。
  • 复杂性:对于大型项目,生成和管理变异体可能非常复杂。

六、总结

变异测试通过引入人为错误来评估测试用例的有效性,帮助发现测试用例的不足并改进测试质量。尽管存在一些缺点,但它在提高软件质量方面具有重要作用。

 

posted @ 2025-03-05 00:04  excellent_1  阅读(335)  评论(0)    收藏  举报