在为我最喜欢的突变测试框架(NinjaTurtles)编写“Off By One”突变测试器的过程中,我编写了以下代码来提供检查我实现的正确性的机会:
public int SumTo(int max)
{
int sum = 0;
for (var i = 1; i <= max; i++)
{
sum += i;
}
return sum;
}
现在这看起来很简单,我并没有想到尝试改变 IL 中的所有文字整数常量会出现问题。毕竟,只有 3 个(the 0
、the1
和 the ++
)。
错误的!
在第一次运行时,它变得非常明显,它永远不会在这个特定的实例中工作。为什么?因为将代码更改为
public int SumTo(int max)
{
int sum = 0;
for (var i = 0; i <= max; i++)
{
sum += i;
}
return sum;
}
只在总和上加上 0(零),这显然没有效果。如果它是多重集合,则不同的故事,但在这种情况下它不是。
现在有一个相当简单的算法来计算整数的总和
sum = max * (max + 1) / 2;
我很容易使突变失败,因为从其中的任何一个常数中加或减 1 都会导致错误。(鉴于max >= 0
)
因此,针对这种特殊情况解决了问题。虽然它没有做我想要的突变测试,即检查当我丢失时会发生什么++
- 实际上是一个无限循环。但这是另一个问题。
所以 - 我的问题: 是否有任何琐碎或非琐碎的情况,其中从 0 或 1 开始的循环可能会导致无法以类似方式重构(被测代码或测试代码)的“一个突变”测试失败?(请举例)
注意:当测试套件在应用突变后通过时,突变测试失败。
更新:一个不那么琐碎的例子,但仍然可以重构测试以使其失败的例子如下
public int SumArray(int[] array)
{
int sum = 0;
for (var i = 0; i < array.Length; i++)
{
sum += array[i];
}
return sum;
}
var i=0
如果您给它的测试var i=1
输入是new[] {0,1,2,3,4,5,6,7,8,9}
. 但是,将测试输入更改为new[] {9,8,7,6,5,4,3,2,1,0}
,变异测试将失败。因此,成功的重构证明了测试。