本文首發於 jaychen.cc
做者 jaychenjava
寫一篇小文,介紹一下 Java 下單元測試工具 TestNG 的使用,代碼在 IDEA 環境在編寫。bash
單元測試,顧名思義,對系統中原子性的功能進行測試,通常狀況下是單元測試是針對某個功能函數的測試。編寫單元測試是系統開發中重要的一環,也是一項科學優雅的裝 X 方式。並且,編寫單元測試代碼並非一件很麻煩的事情,只要稍微學習就能夠掌握這項技能。網絡
在開始以前,須要引入 TestNG 庫,使用 maven 直接引入,在 pom.xml 添加依賴maven
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
<scope>test</scope>
</dependency>複製代碼
使用 IDEA 新建一個項目,目錄結構以下:函數
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test複製代碼
新建一個 Demo.java 類,包含以下簡單代碼工具
public class Demo {
public int add(int a, int b) {
return a + b;
}
public int sub(int a, int b) {
return a - b;
}
}複製代碼
在 IDEA 下使用快捷鍵 Ctrl + Shift + t
爲其生成測試類單元測試
這裏能夠看到,咱們選擇了 TestNG 做爲單元測試庫,IDEA 自動爲咱們生成了單元測試類的類名,其命名規則爲:被測試類+Test
。最後勾選要進行測試的方法,這裏我只選擇 add
方法。學習
肯定以後,會在 src/test/java
目錄下生成對應的類文件,能夠看到已經生成了 DemoTest.java
文件,其內容以下測試
public class DemoTest {
@Test
public void testAdd() throws Exception {
}
}複製代碼
此時,咱們就能夠開始編寫測試代碼。這裏,單元測試的目的是爲了測試 Demo#add
這個函數的功能是否準確正常,因此咱們在 testAdd
中編寫代碼ui
@Test
public void testAdd() throws Exception {
Demo d = new Demo();
assertEquals(7, d.add(3, 4));
}複製代碼
這裏,使用了 assertEquals
進行斷言,這句話至關於說:d.add(3,4)
的結果應該是 7,你幫我執行下 add
看看是否是返回 7。好了,一個單元測試的用例完成,以後就能夠直接運行該測試方法,能夠看到輸出以下:
[TestNG] Running:
===============================================
Default Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================複製代碼
代表這個測試經過,函數功能沒錯。若是咱們把代碼改爲 assertEquals(d.add(3, 4), 8);
,那麼就會出現以下提示
Expected :8
Actual :7
<Click to see difference>
at org.testng.Assert.fail(Assert.java:94)
at org.testng.Assert.failNotEquals(Assert.java:494)
...........
===============================================
Default Suite
Total tests run: 1, Failures: 1, Skips: 0
===============================================複製代碼
代表 add
方法的返回結果和指望的不一樣,方法可能存在 bug。
這裏要注意一個問題,上面咱們對 add
進行一次測試經過,不表明 add
方法就不存在 bug。assertEquals(d.add(3, 4), 7);
只是一個測試用例。這裏要理清一個概念:爲 add
函數編寫了一個單元測試函數 testAdd
,以後咱們須要使用多個測試用例來測試 add
函數是否存在 bug。爲了證實 add
沒有 bug,須要考慮全部可能的狀況,包括 輸入爲0,輸入的 a,b 參數爲負數 等等儘可能的覆蓋全部可能性。因此一個嚴謹的測試應該以下:
@Test
public void testAdd() throws Exception {
Demo d = new Demo();
assertEquals(d.add(3, 4), 7);
assertEquals(d.add(-3, 4), 1);
assertEquals(d.add(-3, -4), -7);
assertEquals(d.add(0, 4), 4);
assertEquals(d.add(0, 0), 0);
}複製代碼
上面的例子只是簡單用法,旨在讓初學者能夠快速上手瞭解 TestNG 的 用法,下面介紹一些高級用法來幫助咱們更好的進行單元測試。
@BeforeClass/@AfterClass
和 @BeforeMethod/@AfterMethod
除了 @Test
註解,TestNG 還有兩對經常使用的註解:@BeforeClass/@AfterClass
和 @BeforeMethod/@AfterMethod
。這些註解的關係以下圖:
從上圖能夠看出,@BeforeMethod/@AfterMethod
是在 @Test
註解函數執行以前/以後執行的鉤子函數。在執行每個 @Test
註解函數執行以前/以後都會執行 @BeforeMethod/@AfterMethod
註解函數。
@BeforeClass/@AfterClass
的做用和 @BeforeMethod/@AfterMethod
相似,不一樣的是,@BeforeClass/@AfterClass
是在初始化類的時候執行,這就意味着 @BeforeClass/@AfterClass
只會執行一次,而 @BeforeMethod/@AfterMethod
執行次數和 @Test
註解函數個數同樣。
public class DemoTest {
@BeforeClass
public static void beforeClass() {
System.out.println("before test....");
}
@BeforeMethod
public void beforeTest() {
System.out.println("before test...");
}
@Test
public void testAdd() {
int res = new Dao().add(1, 2);
Assert.assertEquals(res, 3);
}
@Test
public void testSub() {
int res = new Dao().sub(1, 2);
Assert.assertEquals(res, -1);
}
@AfterMethod
public void afterTest() {
System.out.println("after test....");
}
@AfterClass
public static void afterClass() {
System.out.println("after class....");
}
}複製代碼
執行上面的代碼,能夠看到 beforeClass/afterClass
只執行一次,而 beforeMethod/afterMethod
執行了兩次。
這裏還須要提一點:@BeforeClass/@AfterClass
註解的函數必須使用 static
修飾。
除了使用 assertEquals
斷言函數測試結果以外,TestNG 還提供了一些額外的測試狀況。
在 @Test
註解中添加 timeOut 參數就能夠進行超時測試,@Test(timeOut=10)
表示測試方法的運行時間應該低於 10ms,若是超時者測試失敗。超時測試對於網絡鏈接類的測試至關有用。超時測試具體用法以下
@Test(timeOut = 1)
public void testSub() {
int i =0;
while (i < 1000000000) {
i++;
}
}複製代碼
異常測試用於測試方法是否有拋出異常,經過 @Test(expected=NullPointerException.class)
來指定方法必須拋出 NullPointerException
,若是沒有拋出異常或者拋出其餘異常則測試失敗。
@Test(expectedExceptions = NullPointerException.class)
public void testSub() {
throw new NullPointerException();
}複製代碼
有時候須要測試方法按照一個特定的順序被調用,這個時候須要使用 @Test
註解的 dependsOnMethods
參數來指定依賴方法和方法的執行順序
// test1 執行以前會先執行 test2, test3
@Test(dependsOnMethods = {"test2","test3"})
public void test1(){
}
@Test
public void test2(){
}
@Test
public void test3(){
}複製代碼
好了,TestNg 的使用就到這裏了,其實單元測試並非一件麻煩的事情,花上一些時間學習一下很快就很上手。過了 TestNg 下次說下 Mockito 的使用。