1. 简介
------------
 
编写测试用例是一项困难且耗时的工作,但同时又是好的软件工程的重要部分。Randoop是一个随机测试的测试用例生成的工具,能够自动的为Java代码中的类生成单元测试。官网地址 https://randoop.github.io/randoop/manual/index.html ,这篇文章也是基于官网介绍Randoop的。
 
Writing tests is a difficult and time-consuming activity, and yet it is a crucial part of good software engineering. Randoop automatically generates unit tests for Java classes.
 
Randoop除了能够结合JUnit生成随机测试用例之外,还有Randoop.NET适用于微软的.NET平台,比如说C#语言等。如下例子给出了用Randoop生成的测试用例的样例(注释均是手工添加的)。
 
// This test shows that the JDK collection classes
// can create an object that is not equal to itself.
@Test
public static void test1() {
 
LinkedList list = new LinkedList();
Object o1 = new Object();
list.addFirst(o1);
 
// A TreeSet is an ordered collection. According to the API
// documentation, this constructor call should throw a
// ClassCastException because the list element is not Comparable. But
// the constructor silently (and problematically) accepts the list.
// 据API文档介绍,TreeSet是一个有序的集合类
// 因此在下面的t1对象声明,调用TreeSet构造方法时,由于list元素并不是可比较的
// 故此行理应抛出一个ClassCastException异常
// 但是构建方法却并没有抛出异常
TreeSet t1 = new TreeSet(list);
 
Set s1 = Collections.synchronizedSet(t1);
 
// At this point, we have successfully created a set (s1)
// that violations reflexivity of equality: it is not equal
// to itself! This assertion fails at run time on OpenJDK.
// 此时,我们已经成功创建了Set对象s1
// 但是下述的断言语句会运行失败,因为s1并不等于本身
org.junit.Assert.assertTrue(s1.equals(s1));
}
 
Randoop可以输出2中类型的单元测试:
 
  • 能引发程序中的bug的揭错测试 (Error-revealing Test)
  • 能用于发现未来bug的回归测试 (Regression Test)
 
首先,运行Randoop的揭错测试,如果发现了程序中的bug,你需要反复修改这些bug,并重新运行Randoop直到全部通过测试为止;然后,当你代码出现了版本更替后,运行Randoop的回归测试,来测试你的新版本代码。
 
2. 安装
------------
 
这里以Randdop3.1.2为例,首先在github上找到下载页 https://github.com/randoop/randoop/releases/,选择当前(2017.4)最新版本3.1.2,即randdop_3.1.2.zip。

 

下载之后,跟其他的JDK,Pyhon,MySql一样,需要配置环境变量,这个应该是比较轻车熟路的了,配置RANDOOP_PATH,和RANDOOP_JAR,并添加到 path 当中去。
 
  • 设置变量RANDOOP_PATH为你的解压包路径
  • 设置变量RANDOOP_JAR为你的jar文件路径
 
3. 运行
------------
 
我们通过调用Randoop的主函数(randoop.main.Main)来运行Randoop,在命令行中输入命令
java  -ea  randoop.main.Main  [command args]
 
classpath路径需要包含randoop.jar的路径,以及你需要测试的Java类的路径。【注意在Windows下面冒号:要变成分号; 并且 %RANDOOP_JAR% 变成 ${RANDOOP_JAR}】
 
...  -classpath  bin:%RANDOOP_JAR%  ...
 
产生单元测试,简单的例子,其中gentests表示生成测试的命令,参数有2个,--testclass规定了测试的类,--timelimit规定了生成的时间限制(秒)
 
java  -ea  -classpath [myclasspath];%RANDOOP_JAR% randoop.main.Main gentests 
        --testclass=org.yf.linear.LinkedList --timelimit=60
 
4. 测试生成
------------
 
下面以一个简单的例子来介绍Randoop如何生成单元测试的。
 
比如我们想要为java.util.Collection类和java.util.Arrays的单元测试。注意,Randoop只会为你指定的类来生成单元测试的。首先,创建一个myclass.txt文本文件来存放你想要测试的类,内容如下
 
java.util.Collections
java.util.Arrays
 
然后,调用Randoop如下所示,注意gentests后面可以接单个的类,即--testclass;也可以接类的文本列表,即--classlist,但注意是txt格式,且每一个类占一行。
 
java  -ea  -classpath [myclasspath];%RANDOOP_JAR%  randoop.main.Main  gentests  
        --classlist=myclass.txt   --timelimit=60
 
在60秒之后,Randoop就会保存所产生的单元测试,最后,Randoop就会打印出JUnit文件的名字,类似如下的Java文件
 
Randoop的使用
由图可知,Randoop可以生成2类主要的测试集:1)ErrorTest*.RegressionTest*.java,即回归测试。所有在ErrorTest中的测试会失败,而所有在RegressionTest中的测试会通过。
 
5. 运行测试
 
在上1小节,我们讲到了如何生成ErrorTest和RegressionTest2种测试类型的单元测试,生成了各种测试文件,那么如何运行这些JUnit测试呢?我们需要调用junit.jar包和hamcrest-core.jar包,具体的执行语句如下(在我的JUnit文章中有提到过,如何借助JUnit工具执行我们的测试代码)
 
java  -classpath  .;[junit路径][hamcrest路径]  org.junit.runner.JUnitCore  ErrorTest
 
java  -classpath  .;[junit路径][hamcrest路径]  org.junit.runner.JUnitCore  RegressionTest
 
也可以直接把这些Java文件,复制到项目的测试包中,比如放到test包中
 
Randoop的使用
 
然后直接运行 Run As JUnit 就可以了,如下图结果
 
Randoop的使用