µJava (muJava)是针对Java程序的变异测试系统,官网地址见µJava官网
0.下载
需要下载的文件有:
- mujava.jar
- openjava.jar
- mujava.config
- junit.jar (可选,见后文)
可在官网下载,或点此下载我的压缩包(含环境配置+测试示例)。
0.环境配置
*mujava运行的是Java程序,Java的环境配置见Eclipse+JDK配置那点事。
将下载的mujava相关文件放到一个文件夹,这里为C:\muJava
- 添加mujava环境变量CLASSPATH:
C:\mujava\mujava.jar;C:\mujava\openjava.jar;C:\mujava\junit.jar
注意:
- 官网介绍文档在此处未设置junit.jar的环境变量,直到测试环节才添加。并且,不知道是不是版本问题,使用Eclipse自带的junit.jar包总会在测试环节出现错误,只有使用我的压缩包中的junit.jar才会正常进行。
- 官网中添加的
C:\mujava\classes
我也没明白其用处,删除后不影响,所以删除了。 - 此处未包含Java的环境配置内容,完整的Java+mujava的CLASSPATH应是:
.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;C:\mujava\mujava.jar;C:\mujava\openjava.jar;C:\mujava\junit.jar
创建一个文件夹,如C:\mujavaHome;将mujava.config 移至 该文件夹,并用记事本打开将MuJava_HOME设置为该文件夹,即
MuJava_HOME=C:\mujavaHome
;最后在该文件夹下创建如下结构目录:
在C:\mujavaHome下创建两个Txt,另存为cmd后缀,方便运行mujava程序。txt分别内容为:
GenMutants.cmd:java mujava.gui.GenMutantsMain
RunTest.cmd:java mujava.gui.RunTestMain > TestResult.txt
*运行mujava的目录要包含mujava.config
1.生成变体
先对muJavaHome的文件夹进行解释:
文件夹 | 说明 |
---|---|
src | 待测Java程序源代码 |
classes | src中源代码经过正确编译的.class文件 |
testset | JUnit测试用例的.class文件(见后文) |
result | 生成的变体结果 |
下面对Calculator.java进行变异测试,该文件在我的压缩包中有。
- 将Calculator.java复制到src文件夹,将通过Eclipse编译生成的Calculator.class复制到classes文件夹,运行GenMutants.cmd。
- 正常运行可以看到如下界面,在左侧勾选需进行变异的Java程序,在右侧勾选需要使用的变异算子(方法级别与类级别),点击Generate。
生成完毕后可在其余两个选项卡中查看生成的变体,变体.java与.class位于result文件夹。
2.编写测试用例
muJava的测试集是JUnit测试用例。每个测试是一个方法,其包含待测程序的一些列函数调用。测试方法和测试类都应该是public。编写JUnit测试用例的方法见Eclipse中使用JUnit进行单元测试。
压缩包中包含Calculator.java的JUnit测试类CalculatorTest.java。
将JUnit测试用例的.class文件复制在testset文件夹。
3.运行变异测试
运行RunTest.cmd,见如下界面。设定相关参数后点击Run进行变异测试。测试完成后可以看到统计结果,测试结果的详细内容被输出到muJavaHome\TestResult.txt中。
至此,完成了对Calculator.java的变异测试。
4.测试结果分析
除了在GUI上查看测试结果统计信息,更详细的测试输出可以在mujavaHome/TestResult.txt中查看。对输出内容的分析(查看大图):
- CalculatorTest:测试用例集合类名,该类的每个方法都是一个测试用例,如后面的testAdd、testSub、testMulti、testDiv、test5。
- Generating Original Test Results:对待测类Calculator 原程序的测试结果,应该要全部正确pass,作为软件测试中的oracle。
- 第一个Executing Mutants:对待测类Calculator 类级别变体 Class-Level的测试结果。即使没有进行类级别测试,也会输出该块。
- 之后的Executing Mutants:对待测类Calculator 方法级别变体 Method-Level的测试结果。从第二个Executing Mutants开始,每个Executing Mutants块是对待测类Calculator中的每个方法的测试结果,出现顺序与待测类中的方法顺序一致。如,之后出现的4个Executing Mutants块依次是对Calculator.add()、sub()、multi()、div()的测试结果(上图只展示了一个方法的测试结果)。
- test report列出某个用例可以杀死的所有变体
- mutant report列出某个变体可以被哪些用例杀死
- 若存在对多个方法的测试(即有多个Executing Mutants块),test report和mutant report都会累加测试结果。也就是说,之后出现的report会累计之前的report,最后一个Executing Mutants块的report包含了对所有方法的测试结果。
- 若没有类级别变体或者方法级别变体,则最后一行分别出现 [Notice] There are no mutants to apply
5.注意点
- 需要变异的Java程序中,for循环的迭代变量i只能在for()中定义,否则出错。
for (int i = 0; i < len; ++i) //OK
int i;
for (i = 0; i < len; ++i) //生成变体时会出错
- Java可以对基础数据类型和对应的包装类型实现隐式转换,如func(char,char)可以接受Character类型的对象作为输入参数。但是muJava不能识别这种隐式转换,在生成变体时会引发找不到func(Character,Character)成员的错误。因此需要在原程序中将隐式转换改为显式转换,如(char)Character