JUnit是一个Java语言的单元测试框架。
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个
回归测试
框架(regression testing framework)。Junit测试是程序员测试,即所谓
白盒测试
,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。
![](https://img-blog.csdn.net/20151220163502980?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20151220163416614?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
JUnit特点:
JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试。他是用于
单元测试框架体系xUnit的一个实例(用于java语言)。它包括以下特性:
1、用于测试期望结果的断言(Assertion)
2、用于共享共同测试数据的测试工具
3、用于方便的组织和运行测试的测试套件
4、图形和文本的测试运行器
常用于极限编程:
要求在编写代码之前先写测试,这样可以强制你在写代码之前好好的思考代码(方法)的功能和逻辑,否则编写的代码很不稳定,那么你需要同时维护测试代码和实际代码,这个工作量就会大大增加。因此在极限编程中,基本过程是这样的:构思-> 编写测试代码-> 编写代码-> 测试,而且编写测试和编写代码都是增量式的,写一点测一点,在编写以后的代码中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度。
编写测试代码的必要性:
不要认为压力大,就不写测试代码。相反编写测试代码会使你的压力逐渐减轻,因为通过编写测试代码,你对类的行为有了确切的认识。你会更快地编写出有效率地工作代码。
下面是一些具体的编写测试代码的技巧或较好的实践方法:
1. 不要用TestCase的
构造函数初始化Fixture,而要用setUp()和tearDown()方法。
2. 不要依赖或假定测试运行的顺序,因为JUnit利用Vector保存测试方法。所以不同的平台会按不同的顺序从Vector中取出测试方法。
3. 避免编写有副作用的TestCase。例如:如果随后的测试依赖于某些特定的交易数据,就不要提交交易数据。简单的
回滚就可以了。
4. 当继承一个测试类时,记得调用父类的setUp()和tearDown()方法。
5. 将测试代码和工作代码放在一起,一边同步编译和更新。(使用Ant中有支持junit的task.)
6. 测试类和测试方法应该有一致的命名方案。如在工作类名前加上test从而形成测试类名。
7. 确保测试与时间无关,不要依赖使用过期的数据进行测试。导致在随后的维护过程中很难重现测试。
8. 如果你编写的软件面向国际市场,编写测试时要考虑国际化的因素。不要仅用母语的Locale进行测试。
9. 尽可能地利用JUnit提供地assert/fail方法以及
异常处理的方法,可以使代码更为简洁。
10.测试要尽可能地小,执行速度快。
11.不要硬性规定数据文件的路径。
12.利用Junit 的自动异常处理书写简洁的测试代码
事实上在Junit 中使用try-catch 来捕获异常是没有必要的,Junit 会自动捕获异常。那些没有被捕获的异常就被当成错误处理。
13. 充分利用Junit 的assert/fail 方法
assertSame()用来测试两个引用是否指向同一个对象
assertEquals()用来测试两个对象是否相等
14. 确保测试代码与时间无关
15. 使用文档生成器做测试文档。
JUnit和ant结合
ant 提供了两个 target : junit 和 junitreport 运行所有
测试用例,并生成 html 格式的报表
具体操作如下:
1.将 junit.jar 放在 ANT_HOMElib 目录下
2.修改 build.xml ,加入如下 内容:
-------------- One or more tests failed, check the report for detail... -----------------------------
运行 这个 target ,ant 会运行每个 TestCase,在 report 目录下就有了 很多 TEST*.xml 和 一些网页打开 report 目录下的 index.html 就可以看到很直观的测试运行报告,一目了然。
在Eclipse中开发、运行JUnit测试相当简单。因为Eclipse本身集成了JUnit相关组件,并对JUnit的运行提供了无缝的支持。
junit4.x
(1)、使用junit4.x版本进行单元测试时,不用测试类继承TestCase父类,因为,junit4.x全面引入了Annotation来执行我们编写的测试。
[3]
(2)、junit4.x版本,引用了注解的方式,进行单元测试;
(3)、junit4.x版本我们常用的注解:
A、@Before 注解:与junit3.x中的setUp()方法功能一样,在每个测试方法之前执行;
B、@After 注解:与junit3.x中的tearDown()方法功能一样,在每个测试方法之后执行;
C、@BeforeClass 注解:在所有方法执行之前执行;
D、@AfterClass 注解:在所有方法执行之后执行;
E、@Test(timeout = xxx) 注解:设置当前测试方法在一定时间内运行完,否则返回错误;
F、@Test(expected = Exception.class) 注解:设置被测试的方法是否有异常抛出。抛出异常类型为:Exception.class;
G、@Ignore 注解:注释掉一个测试方法或一个类,被注释的方法或类,不会被执行。
一个JUnit4的测试代码:
Calculator.java
package com.leo.calculator;
public class Calculator {
private int x ;
private int y ;
private int result ;
public void setX(int ix){
x = ix ;
}
public int getX(){
return x ;
}
public void setY(int iy){
y = iy ;
}
public int getY(){
return y ;
}
public int getResult(){
return result ;
}
//add
public int add(int x, int y){
result = x + y ;
return result ;
}
//subtract
public int subtract(int x, int y){
result = x - y ;
return result ;
}
//multiply
public int multiply(int x, int y){
result = x*y ;
return result ;
}
//divide
public double divide(int x, int y){
double result = (double)x/y ;
return result ;
}
}
JUnit4的测试单元:
CalculatorTest.java
package com.leo.calculator;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestCalc {
private Calculator mycalc;
@BeforeClass
// 在所有方法执行之前执行
public static void globalInit() {
System.out.println("init all method...");
}
@AfterClass
// 在所有方法执行之后执行
public static void globalDestory() {
System.out.println("destory all method...");
}
@Before
// 在每个测试方法之前执行
public void setUp() {
System.out.println("start setUp method");
mycalc = new Calculator();
}
@After
// 在每个测试方法之后执行
public void tearDown() {
System.out.println("end tearDown method");
}
@Test(timeout = 600) // 设置限定测试方法的运行时间 如果超出则返回错误
public void testAdd() {
System.out.println("testAdd method");
int result = mycalc.add(2, 3);
assertEquals(5, result);
}
@Test
public void testSubtract() {
System.out.println("testSubtract method");
int result = mycalc.subtract(1, 2);
assertEquals(-1, result);
}
@Test
public void testMultiply() {
System.out.println("testMultiply method");
int result = mycalc.multiply(2, 3);
assertEquals(6, result);
}
@Test
public void testDivide() {
System.out.println("testDivide method");
double result = 0;
try {
result = mycalc.divide(6, 2);
} catch (Exception e) {
fail();
}
assertEquals(3, result,0);
/*
assertEquals(double expected,double actul) 被废弃了(deprecated),
换成assertEquals(double expected,double actul,double delta)
后面加了一个误差值delta,针对于浮点数而言。
*/
}
@Test(expected = Exception.class)
public void testDivide2() throws Exception {
System.out.println("testDivide2 method");
mycalc.divide(6, 0);
fail("test Error");
}
public static void main(String[] args) {
}
}
测试结果输入如下:
界面显示输出如下:
控制台输出信息为:
控制台的输出信息与各个测试方法并不是前后对应的,可以说明,在执行各个测试方法的时候,没有严格的按照方法定义的先后执行,而是多个线程同时执行的。
但是,方法的执行顺序为:
Junit 4 的单元测试用例执行顺序为:@BeforeClass –> @Before –> @Test –> @After –> @AfterClass;
每一个测试方法的调用顺序为:@Before –> @Test –> @After。
方法的执行先后没有严格顺序。