cover_image

如何通过变异测试助力Java项目单测覆盖率提升

360质量效能 360质量效能
2023年08月18日 04:00

图片

通常在软件测试过程中,我们会关注测试用例的代码覆盖率。理想情况下,测试用例应该能够覆盖所有业务代码的函数、方法和模块,从而实现100%的代码覆盖率。然而,达到理想目标并不意味着测试用例已经健全。接下来,笔者将向您介绍一种称为“变异测试”的方法,它可以帮助我们实现目标覆盖率并补充测试用例。


图片

变异测试(Mutation testing)

官方解释

图片


通俗地讲,变异测试会在程序编译或运行时产生微小的突变(即“变异体”),理想的测试用例能够检测出突变体带来的程序行为异常。如果一个突变体能被测试用例发现该错误,则称其被消灭(即“killed”),表明该测试用例是有效的。反之,如果程序行为变化无法被测试用例捕获,则称突变体存活(即“survived”),表明该测试用例是无效的,需要补充相应的突变测试用例。

图片



图片

变异测试 with PITest

PITest和Jumble都是Java程序中的变异测试工具,它们的作用是通过对程序代码进行人为修改(即“变异”)来生成一系列的变异体,然后运行测试用例对这些变异体进行测试,以评估测试用例的质量和覆盖率。相比于Jumble框架,PITest有以下优点:

• 独立的变异测试框架

• 支持多种语言

• 生成的变异体数量相对较多,因此PITest的覆盖率更高

• 会自动为每个测试用例生成变异体

基于以上优点和实际需求选择使用PITest框架。以下介绍使用PITest框架的过程。

1.maven引入PIT插件

图片

2.被测代码

图片

3.单测用例

图片

4.在被测代码执行单元测试,确保单元测试用例都是通过的

5.通过mvn命令运行PIT,并生成mutationCoverage 报告。图中可以发现,代码覆盖度是90%,但Mutation覆盖度仅为76%。

图片

生成的突变覆盖度报告结合了突变覆盖和线覆盖信息。其中,深绿色表示已经被测试用例覆盖的突变体,深粉色表示未被测试用例覆盖的突变体;浅粉色表示未被测试用例覆盖的代码行,浅绿色表示已被测试用例覆盖的代码行。

举例分析突变报告内容,源代码中红箭头所指的第12行对应于产生突变的红箭头指向的第12行。该行代码由“changed conditional boundary”(即条件边界变更)引起了变异,但测试用例没有捕获到这个突变,因此该突变被标记为“survived”。

图片

6.为了捕获这个突变,需要添加新的测试用例来覆盖边界条件,以达到让测试用例将突变杀掉(即“killed”)的目的。

图片

7.再次运行PIT,并生成新的突变覆盖度报告。补充的测试用例将突变杀掉(即“killed”)。

图片



图片

变异类型

通过上面的例子,可以是有多种变异类型的。下面是常见的变异测试类型

• 条件边界变异(Conditionals Boundary Mutator)

对关系运算(<, <=, >, >=)进行变异,例如把“<”突变成“<=”

• 反向条件变异(Negate Conditionals Mutator)

对关系运算(==, !=, <=, >=, <, >)进行变异,例如把"=="变成"!="

• 增量运算变异(Increments Mutator)

对递增或者递减的运算(++, --)进行变异,例如把“++”变成“--”

如果想单独测试某一种或某几种变异类型,可以在pom文件中configuration属性添加相关变异条件,例如

图片




小结

变异测试属于白盒测试范畴,需要对每个代码变异反复运行测试。如果单元测试已经做得比较完备,那么变异测试能够发挥其最大的价值。

总之,变异测试有助于评估测试用例的质量,测试人员设计的测试用例杀掉的变异体越多,说明其设计的测试用例质量越高。











图片



图片

图片

分享给第一个想到的人


图片

继续滑动看下一个
360质量效能
向上滑动看下一个