http://my.oschina.net/u/565871/blog/144927 java
JUnit是由 Erich Gamma和Kent Beck编写的一个回归测试框架(regression testing framework)。JUnit测试是程序员测试,即所谓白盒测试,由于程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。程序员
?数据库
1框架
2ide
3函数
4oop
5单元测试
6测试
7ui
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public
class
JunitAnnotation {
// execute before class
@BeforeClass
public
static
void
beforeClass() {
System.out.println(
"in before class"
);
}
// execute after class
@AfterClass
public
static
void
afterClass() {
System.out.println(
"in after class"
);
}
// execute before test
@Before
public
void
before() {
System.out.println(
"in before"
);
}
// execute after test
@After
public
void
after() {
System.out.println(
"in after"
);
}
// test case
@Test
public
void
test() {
System.out.println(
"in test"
);
}
// test case ignore and will not execute
@Ignore
(“unimplemented”)
public
void
ignoreTest() {
System.out.println(
"in ignore test"
);
}
}
@Test:JUnit 3.x是经过对测试方法的命名(test+方法名)来肯定是不是测试,且全部的测试类必须继承TestCase。JUnit 4.x只须要在方法前加上@Test 就能够定义一个测试方法。
注意:测试方法必须是public void,即公共、无返回值的;能够抛出异常。
@Ignore :该注解标记的测试方法在测试中会被忽略。当测试的方法尚未实现,或者测试的方法已通过时,或者在某种条件下才能测试该方法(好比须要一个数据库链接,而在本地测试的时候,数据库并无链接),那么使用该注解来标记这个方法。同时能够为该注解传递一个String的参数,代表为何会忽略这个测试方法。好比:@lgnore(“该方法尚未实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。
@BeforeClass:当咱们运行几个有关联的用例时,可能会在数据准备或其它前期准备中执行一些相同的命令,这个时候为了让代码更清晰,更少冗余,能够将公用的部分提取出来, 放在一个方法里,并为这个方法注解@BeforeClass。意思是在测试类里全部用例运行以前,运行一次这个方法。例如建立数据库链接、读取文件等。
注意:方法名能够任意,但必须是public static void,即公开的、静态的、无返回值的。这个方法只会运行一次。
@AfterClass:跟@BeforeClass对应,在测试类里全部用例运行以后,运行一次。用于处理一些测试后续工做,例如清理数据,恢复现场。
注意:一样必须是public static void,即公开的、静态的、无返回值的。这个方法只会运行一次。
@Before:使用了该注解的方法在每一个测试方法执行以前都要执行一次。主要用于一些独立于用例之间的准备工做。好比两个用例都须要读取数据库里的用户A信息,但第一个用例会删除这个用户A,而第二个用例须要修改用户A。那么能够用@BeforeClass建立数据库链接。用@Before来插入一条用户A信息。
注意:必须是public void,不能为static。
@After :使用了该注解的方法在每一个测试方法执行以后要执行一次。
@Runwith:即测试运行器,放在测试类名以前,用来肯定测试类怎么运行的,当不指定这个注解时,使用默认Runner来运行测试代码,即@RunWith(JUnit4.class)。
常见的运行器有:
      (1)@RunWith(Parameterized.class):参数化运行器,配合@Parameters使用JUnit的参数化功能。
      (2)@RunWith(Suite.class)
@SuiteClasses({ATest.class,BTest.class,CTest.class})
测试集运行器配合使用测试集功能。
      (3)@RunWith(JUnit4.class):JUnit 4的默认运行器
(4)@RunWith(JUnit38ClassRunner.class):用于兼容junit3.8的运行器
      (5)一些其它运行器具有更多功能。例如@RunWith(SpringJUnit4ClassRunner.class)集成了Spring的一些功能。
@Parameters:用于JUnit的参数化功能,用来标记准备数据的方法。
注意:该方法须要知足必定的要求:
(1)该方法必须为public static的
              (2)该方法返回值必须为java.util.Collection类型
(3)该方法的名字不作要求
              (4)该方法没有参数
为了保证单元测试的严谨性,咱们模拟了不一样的测试数据来测试方法的处理能力,为此咱们编写了大量的单元测试方法。而这些测试方法大同小异:代码结构都是相同的,不一样的仅仅是测试数据和指望值。为了下降代码的冗余,JUnit 4提供了参数化测试,即只写一个测试方法,把这若干种状况做为参数传递进去,一次性的完成测试。
JUnit 4参数化测试的五个步骤:
     (1)为准备使用参数化测试的测试类指定特殊的运行器org.junit.runners.Parameterized。
     (2)为测试类声明几个变量,分别用于存放指望值和测试所用数据。
     (3)为测试类声明一个带有参数的公共构造函数,并在其中为第二个环节中声明的几个变量赋值。
     (4)为测试类声明一个使用注解 org.junit.runners.Parameterized.Parameters饰的,返回值为java.util.Collection的公共静态方法,并在此方法中初始化全部须要测试的参数对。
    (5)编写测试方法,使用定义的变量做为参数进行测试。
    Demo以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@RunWith
(Parameterized.
class
)
public
class
SquareTest {
private
static
Calculator calculator =
new
Calculator();
private
int
param;
//参数
private
int
result;
//指望值
// 准备数据 
@Parameters
public
static
Collection data() {
return
Arrays.asList(
new
Object[][]{{
2
,
4
},{
0
,
0
},{-
3
,
9
}});
}
//构造函数,对变量进行初始化
public
SquareTest(
int
param,
int
result) {
this
.param = param;
this
.result = result;
}
@Test
public
void
square() {
calculator.square(param);
assertEquals(result, calculator.getResult());
}
}
在一个项目中,只写一个测试类是不可能的,咱们会写出不少不少个测试类。但是这些测试类必须一个一个的执行,也是比较麻烦的事情。鉴于此,JUnit为咱们提供了打包测试的功能,将全部须要运行的测试类集中起来,一次性的运行完毕,大大的方便了咱们的测试工做。具体代码以下:
1
2
3
4
@RunWith
(Suite.
class
)
@Suite
.SuiteClasses({ CalculatorTest.
class
,SquareTest.
class
})
public
class
AllCalculatorTests{
}
   你们能够看到,这个功能也须要使用一个特殊的Runner,所以咱们须要向@RunWith注解传递一个参数Suite.class。同时,咱们还须要另一个注解@Suite.SuiteClasses,来代表这个类是一个打包测试类。咱们把须要打包的类做为参数传递给该注解就能够了。有了这两个注解以后,就已经完整的表达了全部的含义,所以下面的类已经可有可无,随便起一个类名,内容所有为空既可。
在JUnit 4以前,对错误的测试,咱们只能经过fail来产生一个错误,并在try块里面assertTrue(true)来测试。如今,能够经过@Test 注解中的expected属性来测试异常。expected属性的值是一个异常的类型。
Demo以下:
1
2
3
4
@Test
(expected=ArithmeticException.
class
)
public
void
testDivide() {
new
Calculator().divide(
6
,
0
);
}
      对于那些逻辑很复杂,循环嵌套比较深的程序,颇有可能出现死循环,所以必定要采起一些预防措施。限时测试是一个很好的解决方案。咱们给这些测试方法设定一个执行时间,超过了这个时间,他们就会被系统强行终止,而且系统还会向你汇报该方法结束的缘由是由于超时,这样你就能够发现这些Bug了。要实现这一功能,只须要给@Test 注解加一个timeout属性,该注解传入了一个时间(毫秒)给测试方法,若是测试方法在指定的时间以内没有运行完,则测试失败。
      Demo以下:
1
2
3
4
@Test
(timeout=
1000
)
public
void
testDeathLoop() {
new
Calculator().deathLoop();
}
单元测试运行结果:java.lang.Exception: test timed out after 1000 milliseconds
         at test.Calculator.deathLoop(Calculator.java:25)
         at test.CaculatorTest.testDeathLoop(CaculatorTest.java:26)
         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
         …………………………