为什么要进行单元测试? 平时最简单的方法就是写main方法,进行测试。
但是这个方法并不好。为什么,假如类有很多,方法很多,改动很多,那你写main方法就写死了。100个类,就得写100个main方法,而且需要人为地观察结果。
JUnit测试过的方法一定可以用,而且之后在这个方法上再写的方法出错的可能小。虽然写JUnit也花时间,但是很值得。另外就是后期维护,如果你的代码不够健壮,那么这个成本很高很高。最好是前期多花点时间,保证代码健壮,这样可以降低后期的成本,从而达到相对低的综合成本。另外,当你和别人合作的时候,比如你做服务器端别人做客户端,如果你的代码没有检查好,别人很可能以为是自己的代码错了,浪费了很多时间去检查。
那么,你最好在src目录下再建一个包com.junit.test,里面新建一个JUnit Test Case文件,取名叫做ExampleTest,选择你要测试的类,选择你要测试的方法。
假如有一个方法叫做,add(int x, int y); 那么你的ExampleTest里面就会有一个testAdd()的方法,你可以按如下操作:
int z = new Example().add(3,5);
assertEquals(8, z);
但是这个方法并不好。为什么,假如类有很多,方法很多,改动很多,那你写main方法就写死了。100个类,就得写100个main方法,而且需要人为地观察结果。
JUnit测试过的方法一定可以用,而且之后在这个方法上再写的方法出错的可能小。虽然写JUnit也花时间,但是很值得。另外就是后期维护,如果你的代码不够健壮,那么这个成本很高很高。最好是前期多花点时间,保证代码健壮,这样可以降低后期的成本,从而达到相对低的综合成本。另外,当你和别人合作的时候,比如你做服务器端别人做客户端,如果你的代码没有检查好,别人很可能以为是自己的代码错了,浪费了很多时间去检查。
还有一个就是有一种比较流行的开发方式,那就是TDD,先写测试代码,然后根据需要通过的测试性能来构建代码。
那么,你最好在src目录下再建一个包com.junit.test,里面新建一个JUnit Test Case文件,取名叫做ExampleTest,选择你要测试的类,选择你要测试的方法。
假如有一个方法叫做,add(int x, int y); 那么你的ExampleTest里面就会有一个testAdd()的方法,你可以按如下操作:
int z = new Example().add(3,5);
assertEquals(8, z);
从JUnit4开始有了一个重载方法,assertEquals(String msg, double expected, double actual),并且每个断言方法都有这个重载方法,就是多添加了一个假如出错了会返回的message。
这样就行了,因为本身引入的类里面的方法都是静态的,所以不需要新建对象或者写类名,直接调用方法名。
然后去工程处,在ExampleTest.java类处点右键,run as Junit Test,如果显示的是绿色就行。
好处,可多个方法同时测试。
这样就行了,因为本身引入的类里面的方法都是静态的,所以不需要新建对象或者写类名,直接调用方法名。
然后去工程处,在ExampleTest.java类处点右键,run as Junit Test,如果显示的是绿色就行。
好处,可多个方法同时测试。
另外一个重要的东西,也是JUnit4之后才出现的assertThat方法,这个东西直接可以替代所有的assert方法。可以提倡这种方法,不再使用其它的assert方法,就指着这一个使用就行。当然,这个方法也有2个重载方法。一个带有message,一个不带。怎么说呢?觉得还是最好养成习惯带一个message吧,以后无论怎样进行调试的时候比较统一。说说这个方法吧。。。
assertThat(String reason, T actual, Matcher<T> matcher)
什么意思呢?给一个实际应该返回的值,再加一句Matcher语句,这个的源码来自于Hamcrest包,去网上下载好。下all那个。下好以后添加到path里面去,使用import static.org.hamcrest.Matchers.*;
就可以这样使用了
int z = new Example().add(3,5);
assertThat(z, is(8));
但是这个时候肯定会出错,因为hamscrest的classloader和 junit的classloader不一样。参照反射。
解决方法,自己下载JUnit,添加其jar包到path里面去就行。
以后反正就用这个就行了。
在Eclipse运行测试的时候,窗口中会显示两栏,failure和error, 区别是什么呢?
failure是测试失败,预期值和实际值不符合
error是程序出错,如果程序出错了系统根本就不再理会failure了
Annotation
在你写测试类的时候,里面有测试方法,在每一个测试方法声明之前都必须有一个@Test的标记,这个就叫做annotation,当然不止这么一个。
如果一个方法有可能抛出异常,那么就 @Test(expected=java.lang.xxxException.class)
如果需要让一个方法在多少时间之内执行完毕,那么就 @Test(timeout=100),这样就表明100毫秒之内,这样可以检查程序的执行效率
@Ignore,表明在这一次的测试中,暂时不考虑它,直接把这个标签写在最上面
@Before,在每一个测试方法之前运行
@After,在每一个测试方法之后运行
上面这两个东西什么情况下使用呢?加入你在测试之前需要打开一个文件,测试完毕之后需要关闭,那么你就需要写2个方法在方法开始之前打开,方法结束之后关闭。
@BeforeClass,@AfterClass
这两个也可以顾名思义了,在类初始化之前就运行,在所有测试运行结束之后运行。需要注意的一点是,因为@BeforeClass是在类还没有初始化之前就运行的,所以说,被上面2个annotation标注的方法,必须是静态方法。
什么时候需要用到它们呢?如果你需要提前搭建一些耗时间的环境或者取得一些资源的时候,比如建立和数据库的连接,可能需要花一些时间,这样最好就是在类加载之前就先进行了。
最后说一个其它问题,当你一次测试多个类的时候怎么做呢?
右键->Run As->Run Configurations,选上Run all tests in the selected project。。。
这样就可以一次进行了,假如一个工程里面有很多类,这个时候Junit的优势就体现出来了。
@Before,在每一个测试方法之前运行
@After,在每一个测试方法之后运行
上面这两个东西什么情况下使用呢?加入你在测试之前需要打开一个文件,测试完毕之后需要关闭,那么你就需要写2个方法在方法开始之前打开,方法结束之后关闭。
@BeforeClass,@AfterClass
这两个也可以顾名思义了,在类初始化之前就运行,在所有测试运行结束之后运行。需要注意的一点是,因为@BeforeClass是在类还没有初始化之前就运行的,所以说,被上面2个annotation标注的方法,必须是静态方法。
什么时候需要用到它们呢?如果你需要提前搭建一些耗时间的环境或者取得一些资源的时候,比如建立和数据库的连接,可能需要花一些时间,这样最好就是在类加载之前就先进行了。
最后说一个其它问题,当你一次测试多个类的时候怎么做呢?
右键->Run As->Run Configurations,选上Run all tests in the selected project。。。
这样就可以一次进行了,假如一个工程里面有很多类,这个时候Junit的优势就体现出来了。