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)
         …………………………