变异测试java_编码的喜悦……以及Java中的变异测试
变异测试 java
多年以来,为源代码编写单元测试⼀直是⼀种好习惯。 并且还可以使⽤测试覆盖率报告来查看测试覆盖了多少代码。 尽管⾏+分⽀覆盖率报告⾮常有⽤,但是它并不能告诉您单元测试的实际效果。 因此,甚⾄在测试中没有⼀个断⾔的情况下,甚⾄有可能达到100%的覆盖率。
对更好的测试⽅法感兴趣,我参加了今年的“ 的“突变测试”研讨会。
变异测试是执⾏和分析单元测试的结果和覆盖范围的⼀种截然不同的⽅法。 ⽆需测量单元测试“访问了”多少代码,⽽是确定单元测试实际上“测试了”多少代码。
那么它实际上是如何⼯作的
变异测试背后的基本思想是对(字节)代码进⾏微⼩的更改(变异),然后执⾏测试以查看是否被单元测试检测到。
可能的突变是将“ > ”更改为“ >= ”,将“ ++ ”替换为“ -- ”,并删除“ void ”⽅法调⽤。
因此,每个突变都会创建代码的变更版本,称为“突变”。
在进⾏实际的变异测试之前,⾸先需要对原始代码执⾏单元测试,以查看是否没有测试失败。
然后,将针对每个“突变体”运⾏单元测试(这可能⾮常耗时),看是否:
我们的单元测试检测到该突变体:测试失败,因此“突变体”被视为“已杀死”。
我们的单元测试没有注意到该突变体:测试没有“没有”失败(“突变体”被认为是“存活”)并且没有注意到突变; 这意味着单元测试实际上是“不”测试(未发现)“突变体”的。
变异测试的⼀个例⼦
那么,这种“变异测试”实际上是如何⼯作的呢?
请考虑以下⽅法:
public String foo(int i) {
if ( i >= 0 ) {
return "foo";
} el {
return "bar";
}
}
单元测试仅包含⼀种测试⽅法这⼀事实:
@Test
public void testFoo() {
testee.foo(0);
}
如果我们要创建代码的“突变体”,将“ >= ”更改为“ > ”,该怎么办?
我们希望我们的单元测试⽅法能够检测到这⼀点,对吧? 好吧,在这种情况下不是因为测试⽅法不包含单个断⾔。
我们将更改⼀个“ testFoo”⽅法以包含⼀个断⾔:
@Test
public void testFoo() {
String result = testee.foo(0);
asrtEquals("foo", result);
}
现在,我们的单元测试⽅法将失败并检测(也称为“杀死”)“突变”代码。
除了将“ >= ”更改为“ > ”之外,还可以创建其他“突变体”:
可以将第⼀个return⽅法更改为返回null (⽽不是"foo" );
由于使⽤“ asrtEquals”语句,此“突变体”被“ testFoo”⽅法“杀死”,但仍未被注意到原始的“ testFoo”⽅法(没有任何断⾔)。
可以将第⼆个return⽅法更改为返回null (⽽不是"bar" );
由于没有测试⽅法实际覆盖该执⾏路径,因此该“突变”将不会被注意到。
注意 :⼀些变异测试⼯具(例如Java的PIT)甚⾄不会费⼼为第⼆个return语句创建“变异”,因为它不会被单元测试所覆盖(如传统的⾏覆盖率所检测)。
等效突变导致假阳性
与传统的⾏+分⽀覆盖相⽐,突变覆盖可能会导致假阳性。
它可能“错误地”报告(假阳性)单元测试未检测到“突变”为“未”。
例如,考虑以下Java代码:
public int someNonVoidMethod() { return 0; }
public void foo() {
int i = someNonVoidMethod();
// do more stuff with i
}
在变异测试期间(使⽤具有某些“⾮”默认配置的PIT变异测试),可能会创建以下“变异”:
public int someNonVoidMethod() { return 0; }
public void foo() {
int i = 0;
// do more stuff with i
}
“ mutant”中的“ int i = 0 ”语句在功能上与“ someNonVoidMethod ”返回0的原始代码“等效”。
由于单元测试不会(也不应该)失败,因此⽆法检测到这种“等效突变”。
因此,它将被报告为未覆盖,⽽实际上它是⼀个假阳性。
根据 ,在使⽤PIT(⼀种⽤于Java的突变测试框架)时,“等效突变”应使⽤“默认”的⼀组突变体最⼩化。
例如,默认情况下会禁⽤导致“ int i = 0 ”等效突变的PIT的“⾮⽆效⽅法调⽤突变器”。
结论
在参加了研讨会,⼀些额外的调查并与PIT合作之后,我⾮常热衷于在不久的将来在当前项⽬中使⽤“变异测试”(从新组件开始)。
与传统的覆盖率报告相适应,变异测试覆盖率实际上可以衡量您的测试质量,不能像传统的覆盖率报告那样被愚弄。
如果您也有兴趣:
请查看克⾥斯·⾥默(Chris Rimmer)的这个⾮常有趣的了突变测试的基本概念。
此外,还有⼀家名为TheLadders的公司使⽤PIT突变测试⼯具有趣的 。
Filip van Laenen还写了有关超载杂志第108版中的“变异测试”的详尽 。
最后但并⾮最不重要的⼀点是PIT突变测试上的⽂档
变异测试 java