往往我们为了图方便都会在程序中打印很多的debug信息,然后等项目正式上线的时候在去除这些debug,这样的事情JUnit能够很好的胜任,我们能通过TestSuite定义自己的测试套件,TestSuite也可以嵌套,我们可以在一个TestSuite里添加很多的TestSuite,这样我们的测试用例可以通过一个程序接口全部跑一遍,比如我们有一个读文件的类,如下:
package com.java.fileio;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderUtil {
private FileReader fi = null;
public FileReaderUtil(String filePath) throws FileNotFoundException{
fi = new FileReader(filePath);
}
public char read() throws IOException{
char c = (char)fi.read();
return c;
}
public void close() throws IOException{
fi.close();
}
}
现在我们要测试read方法,包括第四个字符一定要是‘d’,还有边界测试(测试开始的字符、最后的字符,最后字符之后再读取的话字符),我们可以这样写测试用例:
package com.java.junit;
import java.io.FileNotFoundException;
import java.io.IOException;
import com.java.fileio.FileReaderUtil;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* @author rgs
*
*/
public class FileReaderUtilTest extends TestCase {
private FileReaderUtil input;
public FileReaderUtilTest(String name){
super(name);
}
public void testRead() throws IOException{
char ch = '&';
for(int i=0;i<4;i++){
ch = (char)input.read();
assertEquals('d', ch);
}
}
public void testReadEnd() throws IOException{
char ch = '&';
for(int i=0;i<5;i++){
ch = (char)input.read();
System.out.println(ch);
}
assertEquals(100, ch);
}
public void testReadBoundries() throws IOException{
char ch = '&';
ch = input.read();
assertEquals("read first char", 'd',ch);
for(int i=1;i<5;i++){
ch = (char)input.read();
}
ch = input.read();
System.out.println(">>>"+ch);
assertEquals("read at end", 100,input.read());
}
@Override
protected void setUp(){
try {
input = new FileReaderUtil("D:\\data.txt");
} catch (FileNotFoundException e) {
throw new RuntimeException("unable to open the file");
}
}
@Override
protected void tearDown(){
try {
input.close();
} catch (IOException e) {
throw new RuntimeException("error on closing the file");
}
}
public static TestSuite suite(){
TestSuite suite = new TestSuite();
suite.addTest(new TestSuite(FileReaderUtilTest.class));
return suite;
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
// junit.textui.TestRunner.run(new TestSuite(FileReaderUtilTest.class));
}
}
这里我们继承自TestCase这个类,里面有两个很实用的方法我们可以override,他们是setUp和tearDown,没错,正如你所想,他们是在你的运行测试用例里每一个以test开头的函数之前做初始化并在test结束之后做清理工作,比如这里有三个test打头的方法:testRead,testReadEnd和testReadBoundries,那么也就是说在运行他们前后都会执行setUp和tearDown里面的内容,这就充分保证了各个测试点之间相互独立,不会相互影响。
这里还要说一下的是TestSuite类的使用,我们可以有如下几种方式去添加测试套件:
第一种:
public static TestSuite suite1(){
TestSuite suite = new TestSuite();
suite.addTest(new FileReaderUtilTest("testRead"));
return suite;
}
这种方式一次添加一个测试方法,这里就是FileReaderUtilTest里的‘testRead’方法,至于这里怎么做到的,就是借助java的反射机制。你可能会觉得如果我一个测试类里有几十个需要执行的测试方法,那我岂不是要添加几十次了,幸好junit框架的开发人员和我们一样懒,给我们提供了一次添加一个或多个测试类的机制,如下:
第二种:
public static TestSuite suite(){
TestSuite suite = new TestSuite();
suite.addTest(new TestSuite(FileReaderUtilTest.class));
// suite.addTest(new TestSuite(FileReaderUtilTest1.class));
return suite;
}
按这种方式添加默认就会将你所添加类里以‘test’打头的方法作为测试方法执行,无论采用上面哪种方式,最后都是用如下的方式去调用:
junit.textui.TestRunner.run(suite());
这里的suite()方法返回TestSuite实例。
其实很多时候有这点技能基本就足够我们做单元测试了。