Junit4 單元測試框架的經常使用方法介紹

Junit 介紹:java

Junit是一套框架(用於JAVA語言),由 Erich Gamma 和 Kent Beck 編寫的一個迴歸測試框架(regression testing framework),即用於白盒測試。數據庫

 

本文介紹的內容:框架

1 Junit Myeclipse測試類的生成eclipse

JUnit 4 經常使用的幾個annotation 介紹與使用 (@Before  @After @Test @Ignore @BeforeClass @AfterClass)函數

3 經常使用的斷言介紹oop

4 特殊的處理 (限時測試,異常測試)單元測試

5 參數化配置 (@Parameters)測試

 

準備測試代碼this

測試的方法(正確、錯誤方法、死循環、拋異常)spa

LogicService 
package com.logic;

public class LogicService {
    
    public int add(int x ,int y){ //加法
        return x+y;
    }
    
    public int sub(int x ,int y){ //減法
        return x-y;
    }
    
    public int div(int x ,int y){ //除法 
        return x/y;
    }
    
    public int div2(int x ,int y){ //除法  作了異常判斷
        try {
            int z = x/y;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return x/y;
    }
    
    public void loop(int x ,int y){ //死循環
        for(;;)
            x=y;
    }    
    
    public void unCompleted(int x ,int y){ //未完成的模塊
        //還在開發中
    }
    
}

 

一  Myeclipse測試類的生成

1 對須要測試的類點右鍵 NEW 一個Junit Test Case

 

 

2 點擊NEXT

 注意 1 選擇NEW Junit 4 test

        2 source folder 是默認會填寫上以前右鍵NEW的那個類,若是不是的話,請自行進行修改

        3 package 默認會填寫當前的包名 我的建議從新開個測試包-即在包後面加上.test 表示是單元測試用例專用包與源代碼分離

        4 name 默認會在以前右鍵NEW的那個類的基礎的後面加上Test 若是不是的話,建議自行進行修改,便於標示

        5 初始化的方法,我通常會勾上個setUp,這個請隨意。

        

3 繼續點擊NEXT

1 這裏能夠選擇須要測試的方法,我通常都是全選的而後在生成的測試類中再作處理

2 點擊finish完成

 

4 生成的單元測試類

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class LogicServiceTest {

    @Before
    public void setUp() throws Exception {
    }

    @Test
    public void testAdd() {
        fail("Not yet implemented");
    }

    @Test
    public void testSub() {
        fail("Not yet implemented");
    }

    @Test
    public void testDiv() {
        fail("Not yet implemented");
    }

    @Test
    public void testDiv2() {
        fail("Not yet implemented");
    }

    @Test
    public void testLoop() {
        fail("Not yet implemented");
    }

    @Test
    public void testUnCompleted() {
        fail("Not yet implemented");
    }

}

 

二 JUnit 4 經常使用的幾個annotation 介紹與使用 (@Before  @After @Test @Ignore @BeforeClass @AfterClass)

1 經常使用的annotation介紹

 @Before:初始化方法,在任何一個測試執行以前必須執行的代碼; 

 @After:釋放資源,在任何測試執行以後須要進行的收尾工做。在每一個測試方法執行以後執行一次,該annotation只能修飾public void 方法;

 @Test:測試方法,代表這是一個測試方法。在Junit中將會自動被執行。該annotation只你呢個修飾public void 方法

 @Ignore:忽略的測試方法,標註的含義就是「某些方法還沒有完成,暫不參與這次測試」;

 @BeforeClass:針對全部測試,只執行一次,且必須爲public static void;通常用於初始化必要的消耗較大的資源,例如數據庫鏈接等

 @AfterClass:針對全部測試,將會在全部測試方法執行結束後執行一次,且必須爲public static void; 

 

2 經常使用的annotation測試

 修改單元測試類LogicServiceTest

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

public class LogicServiceTest {

    @Before
    public void setUp() throws Exception {
        System.out.println("@Before");//測試@Before
    }

    @After
    public void end() throws Exception {
        System.out.println("@After");//測試@@After
    }

    @BeforeClass
    public static void init() throws Exception {
        System.out.println("@BeforeClass");//測試@BeforeClass
    }

    @AfterClass
    public static void disstroy() throws Exception {
        System.out.println("@AfterClass");//測試@AfterClass
    }

    @Test
    public void testAdd() {
        System.out.println("@Test testAdd");//測試@Test
    }

    @Test
    public void testSub() {
        System.out.println("@Test testSub");//測試@Test
    }

    @Ignore
    public void testDiv() {
        System.out.println("@Ignore ");//測試@Ignore
    }

    @Ignore
    public void testDiv2() {
        System.out.println("@Ignore ");//測試@Ignore
    }

    @Ignore
    public void testLoop() {
        System.out.println("@Ignore ");//測試@Ignore
    }

    
    public void testUnCompleted() {
        System.out.println("@Ignore ");//測試未標註
    }

}

 

執行結果

執行結果分析

1 @BeforeClass和@AfterClass只執行一次,在全部方法開始前/後

2 @Before和@After在每一個@Test標註的方法先後各執行一次

3 @Test 標註的方法都會執行一次(表示要測試的方法)

4 @Ignore方法不會被執行,沒有annotation的方法也不會被執行

5 總結  @BeforeClass –> (@Before –> @Test –> @After) –> @AfterClass

 

理解了以上註解後就能夠嘗試着在平常的項目中使用Junit進行單元測試了。

 

3 經常使用的斷言介紹

assertEquals(String msg, Object expectRes, Object Res) --------  用於值判斷

判斷expectRes.equals(Res) ,表示值等於的判斷,失敗則拋MSG

assertSame(String msg, Object expectRes, Object Res)  --------  用於地址判斷

判斷expectRes==Res,表示地址等於的判斷,失敗則拋MSG

assertTrue(String msg,Boolean result) ----------------------------用於Boolean判斷

判斷result是true仍是false,失敗則拋MSG

assertNull(String msg,Object result)-------------------------------用於NULL判斷

判斷result是否爲NULL,失敗則拋MSG

fail(String msg);---------------------------------------------------直接停止方法運行

直接停止方法運行,拋出MSG

 

測試代碼

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.logic.LogicService;

public class LogicServiceTest {
    LogicService logserv ;

    @Before
    public void setUp() throws Exception {
        logserv = new LogicService();
    }

    @Test
    public void testAdd() {
        String a = "aa";
        String t = "a";
        String b = "a"+t;
        assertEquals("assertEquals", a, b) ; //A與B的關係是值相等,地址不相等,這個用例會成功
    }

    @Test
    public void testSub() {
        String a = "aa";
        String t = "a";
        String b = "a"+t;
        assertSame("assertSame", a, b) ; //A與B的關係是值相等,地址不相等,這個用例會失敗
    }

    @Test
    public void testDiv() {
        assertTrue("assertTrue",true);//用例成功
        assertTrue("第二個爲false失敗",false);//用例失敗
    }

    @Test
    public void testDiv2() {
        assertNull("assertNull",null);//用例成功
        assertNull("第二個爲notNull失敗","a");//用例失敗
    }

    @Ignore
    public void testLoop() {
    }

    @Ignore
    public void testUnCompleted() {
    }

}

 

執行結果分析

這裏我再也不截圖了

1 成功

2 失敗,返回MSG爲assertSame

3 第一個成功,第二個失敗,返回MSG爲第二個爲false失敗

4 第一個成功,第二個失敗,返回MSG爲第二個爲notNull失敗

斷言是用來判斷被測方法執行的結果與預期結果是否匹配

 

4 特殊的處理 (限時測試,異常測試)

1 Junit提供限時處理的機制。

@Test(timeout=1000) 單位毫秒

當方法用時超過1000毫秒時,此方法會自動停止並執行失敗

package com.logic.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.logic.LogicService;

public class LogicServiceTest {
    LogicService logserv ;

    @Before
    public void setUp() throws Exception {
        logserv = new LogicService();
    }

    @Ignore
    public void testAdd() {
    }

    @Ignore
    public void testSub() {
    }

    @Ignore
    public void testDiv() {
    }

    @Test(timeout=1000) 
    public void testDiv2() {
        System.out.print("我不會超過1000毫秒的");
    }

    @Test(timeout=1000) 
    public void testLoop() {
        logserv.loop(1, 1);//此方法使用的是死循環實現,因此必定會超過限時,超過限時後此方法會自動停止
    }

    @Ignore
    public void testUnCompleted() {
    }

}

執行結果

loop方法超時報錯,div2方法不超時成功

 

2 Junit提供異常處理的機制。

@Test(expected=Exception.class) 其中Exception.class能夠寫的更加具體

測試

    @Test(expected=Exception.class)
    public void testDiv() {
        System.out.print(logserv.div(3, 0));
    }

    @Test(expected=Exception.class)
    public void testDiv2() {
        System.out.print(logserv.div(3, 0));
    }

執行結果

兩個都經過

 

測試

    @Test(expected=Exception.class)
    public void testDiv() {
        System.out.print(logserv.div(3, 0));
    }

    @Test
    public void testDiv2() {
        System.out.print(logserv.div(3, 0));
    }

執行結果

第一個經過 第二個不經過 異常爲除數不能爲zero

 

5 參數化配置 (@Parameters)   重要

進行單元測試的時候,一般一個方法須要好幾個case進行測試,Junit提供參數化便於咱們對方法進行多種參數的組合測試

若是不使用參數化進行測試的話,那麼咱們的測試類會作的很臃腫

例如

    @Test
    public void testAdd() {
        assertEquals("1+1 失敗",2,logserv.add(1, 1) );
    }
    @Test
    public void testAdd1() {
        assertEquals("1+2 失敗",3,logserv.add(1, 2) );
    }
    @Test
    public void testAdd2() {
        assertEquals("1+3 失敗",3,logserv.add(1, 3) );
    }
    @Test
    public void testAdd3() {
        assertEquals("1+4 失敗",3,logserv.add(1, 4) );
    }

這樣的測試類顯然看起來不是很理想,代碼過於重複

 

參數化的實現過程(重要)

1 在測試類上增長

@RunWith(Parameterized.class)並引入

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

2 寫上構造類的函數及定義入參

例如

@RunWith(Parameterized.class)
public class LogicServiceTest {
    LogicService logserv ;
    int parm1 ;//定義入參
    int parm2 ;//定義入參
    int res;//定義入參
    
   public LogicServiceTest(int parm1,int parm2,int res){//定義構造函數
       this.parm1=parm1;
       this.parm2=parm2;
       this.res=res;
   }

3 定義一個返回結果爲collection類型的方法並寫上@Parameters 

注意 Arrays.asList()裏面NEW的Object的要與定義的參數一一對應

例如

public class LogicServiceTest {
    LogicService logserv ;
    int parm1 ;//定義入參
    int parm2 ;//定義入參
    int res;//定義入參
    
   public LogicServiceTest(int parm1,int parm2,int res){//定義構造函數
       this.parm1=parm1;
       this.parm2=parm2;
       this.res=res;
   }
   
   @Parameters   
   public static Collection<Object[]> initParm(){
       return  Arrays.asList(new Object[][]{
          {1,1,2},{1,2,3},{1,3,4},{1,3,5}//{}裏的參數必定要和構造函數一一對應
   });
   }

4 編寫測試方法,調用參數

    @Test
    public void testAdd() {
        assertEquals(res,logserv.add(parm1, parm2));
    }

5 測試類代碼全景(準備執行)

package com.logic.test;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.logic.LogicService;

@RunWith(Parameterized.class)
public class LogicServiceTest {
    LogicService logserv;
    int parm1;// 定義入參
    int parm2;// 定義入參
    int res;// 定義入參

    public LogicServiceTest(int parm1, int parm2, int res) {// 定義構造函數
        this.parm1 = parm1;
        this.parm2 = parm2;
        this.res = res;
    }

    @Parameters
    public static Collection<Object[]> initParm() {
        return Arrays.asList(new Object[][] { { 1, 1, 2 }, { 1, 2, 3 },
                { 1, 3, 4 }, { 1, 3, 5 } // {}裏的參數必定要和構造函數一一對應
                });
    }

    @Before
    public void setUp() throws Exception {
        logserv = new LogicService();
    }

    @Test
    public void testAdd() {
        assertEquals(res, logserv.add(parm1, parm2));
    }

    @Ignore
    public void testSub() {
    }
}

6 執行結果

總結:使用了參數化後測試類的代碼簡化了很多,並且執行起來效果很不錯

 

收尾

經過本文能夠了解到:

1 Junit Myeclipse測試類的生成

2 JUnit 4 經常使用的幾個annotation 介紹與使用 (@Before  @After @Test @Ignore @BeforeClass @AfterClass)

3 經常使用的斷言介紹

4 特殊的處理 (限時測試,異常測試)

5 參數化配置 (@Parameters)

相關文章
相關標籤/搜索