Java單元測試框架 --- Junit4

1、什么是Junit4

JUnit4是一個易學(xué)易用的Java單元測試框架,一般我們在寫完一段代碼或一個方的時候,都要測試一下這段代碼和這個方法的邏輯是不是正確,輸入一定的數(shù)據(jù),返回的數(shù)據(jù)是不是我們想要的結(jié)果,即我們在寫單個業(yè)務(wù)代碼針對結(jié)果進行測試。這時Junit就派上了大用場了。

2、為何使用Junit4

也許有的初學(xué)者會說,項目完成之后測試不行嗎?如果你要這么想的話,那就了,因為隨著你代碼的增加,你牽扯到的模塊和項目中的邏輯就會越來越多,這樣測試起來就會非常的麻煩,而且容易出錯。Junit看起來是增加了代碼量,可是它可以大大的減少后期的測試時間,提升代碼的質(zhì)量,讓代碼更易于維護。

3、Junit4的快速入門

下載并導(dǎo)入Junitjar包:

首先得需要去網(wǎng)上下載一個Junit4的一個jar包,保存到自己本地電腦里面打開myEclipse新建一個Java項目,通過右擊項目-->Build Path --->Configure Build Path -->Add External JARs--->找到自己剛保存的jar路徑,點擊OK就可以啦

創(chuàng)建測試目錄:

接下來就要為我們的測試建立特殊的路徑,這個特殊特殊在哪里呢,因為我們的測試代碼要單獨保存不能與源代碼進行混淆,到項目結(jié)束后可以直接把它刪除,而且不會對項目造成影響。怎么創(chuàng)建呢:右擊項目名稱--->new---->suorce folder--->輸入你想要的測試文件名點擊OK就可以啦。

接下來我們得在項目中的src目錄下創(chuàng)建一個包,注意這兒的包名和test里面的包名要保持一致,在我們src的包下寫我們項目的邏輯方法,在test的報下寫我們的測試方法,結(jié)構(gòu)如圖所示,

image.png

下面我們來寫一段簡單的邏輯代碼進行測試演練

package com.junit;

public class method_junti {
    public int add(int a, int b) {
        return a + b;
    }

    public int subtract(int a, int b) {
        return a - b;
    }

    public int multiply(int a, int b) {
        return a * b;
    }

    public int division(int a, int b) {
        return a / b;
    }
}

方法很簡單,就是一般的加減乘除,下面我們就可以進行測試了,怎么測試呢: 在我們的測試目錄下新建測試類junit_test,然后定義測試方法。代碼如下:

package com.junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class junit_test {

    
    //測試方法必須有@test;
    //該測試方法必須由public void修飾,沒有返回值;
    //該方法不帶任何參數(shù);
    //新建一個源代碼測試文件單獨存放測試代碼;
    //測試類的包和被測試類的包保持一致;
    //測試方法間互相獨立沒有任何依賴;
    @Test
    public void testAdd(){
        
        assertEquals(4, new method_junti().add(3, 0));
    }
    
    @Test
    public void testSubtract(){
        assertEquals(3, new method_junti().subtract(6, 3));
    }
    
    @Test
    public void testMultiply(){
        assertEquals(6, new method_junti().multiply(6, 1));
    }
    
    @Test
    public void testDivision(){
        assertEquals(6, new method_junti().division(6, 1));
    }
}

下面來講解一下assertEquals()這個函數(shù),它的第一個參數(shù)是你預(yù)期的一個結(jié)果,第二個參數(shù)使我們想測試的函數(shù),這個函數(shù)我們要通過先new出函數(shù)所在的類,然后通過類來調(diào)用方法,方法里面的參數(shù)就是你在寫該方法是傳進來的參數(shù)。在這里最好在你需要測試的方法的前面加上test,這樣的話就會比較規(guī)范一些

寫完之后你可以點擊測試類,然后在點擊run as,再點擊Junit test,你就能在彈出的窗口中看到你的測試結(jié)果,它會提示你失敗的個數(shù)和錯誤的個數(shù)。如果你只想測試一個方法怎么辦呢,在你創(chuàng)建的測試類的下面還有目錄,列表里面的會列出你所有的測試方法,你就可以右擊你想測試的方法,然后run as ---> junit test,測試成功后就會看到一個綠色的條,結(jié)果如圖:

image.png

在這里如果我們每一個方法都要自己手動的敲出它的測試方法,在這里我們只是簡單的測試了幾個方法,在項目中如果我們有很多的方法需要測試,一個一個的敲的話會有些浪費時間了,這里給大家介紹一個快速生成測試方法的一個方法:
點擊src下的method_junit.java--->右擊new--->看看后面的提示框中有么有Junit test case,如果沒有的話點擊other,在提示框中輸入Junit 就會出現(xiàn)--->在彈出的對話框中找到Source folder,點擊后面的Browse將其改為含有test的那個目錄,這里有些可能會提示名字重復(fù),把下面的 Name改改就行--->點擊next--->你會看到method_junit里面的所有法,這時候你就可以選中它們,成成測試方法如下:

package com.junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class method_juntiTest2 {

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

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

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

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

再把里面fail后面的語句刪了就可以寫你想測試的東西呢!

4、junit測試失敗的兩種情況:

在前面的情況中我們都是測試的是成功的例子,但是Junit的作用只是測試的方法里的返回數(shù)據(jù)是不是正確的,但是在數(shù)據(jù)返回正確的情況下我們未必是正確的,就比如如果你要求的是長方形的面積,但是你用的是周長公式,當你在測試的時候他也會給你測試成功,得到預(yù)期的結(jié)果,也就是說我們的測試用例對于邏輯錯誤是無能為力的

測試失敗的情況一
當我們預(yù)期值和程序執(zhí)行的結(jié)果不一樣的時候就會測試失?。?br> 比如我們上面的測試加法函數(shù)的方法:

@Test
public void testAdd(){
      assertEquals(3, new method_junti().add(3, 0));
}

如果把預(yù)期結(jié)果3,改為4,就會測試失敗,failure的后面就會出現(xiàn)一個1,提示一個測試失敗,運行時就能看到,這個應(yīng)該不難理解。如果你仔細觀察的話,下面還會有相關(guān)的提示,如圖所示:

image.png

測試失敗情況二:
下面我們在來測試除法:

@Test
public void testDivision(){
    assertEquals(6, new method_junti().division(6, 1));
}

如果在這里把除數(shù)改為0,會出現(xiàn)什么情況呢:后面的提示框中的error數(shù)就會變1;提示有一個錯誤。于是我們得出下面的兩種情況:

1、failure一般由單元測試使用的斷言方法判斷失敗所引起的,這表示測試點發(fā)現(xiàn)了問題,也就是說程序輸出的結(jié)果和預(yù)期的不一樣
2、error是由代碼異常引起的,他可能是由于測試代碼本身的錯誤,也可能是被測試代碼中隱藏的一個bug

5、Junit的運行流程:

首先我們先在test包下的com.junit新建一個junit case,和并且直接命名junit_case。在創(chuàng)建的時候把setUpBeforeClass(),tearDownAfterClass(),setUp() ,tearDown() 選上就會得到下面的代碼:

package com.junit;

import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;

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


public class Junit_case {
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

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

下面我們在每個方法中輸入一句簡單的輸出語句,看看他們的運行狀態(tài),如下:

package com.junit;

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 Junit_test1 {

    
    /* 1、BeforeClass修飾的方法會在所有方法被調(diào)用前執(zhí)行
     * 而且該方法是靜態(tài)的,所以當測試類被加載后接著就執(zhí)行它
     * 在內(nèi)存中它只會存在一份,適合加載配置文件
     * 2、AfterClass修飾的方法用來對資源的清理,如關(guān)閉數(shù)據(jù)庫的連接
     * befoer和after修飾的方法在每個test修飾的方法執(zhí)行前會被各執(zhí)行一次,假如有兩個
     * test文件,before和after會被各執(zhí)行兩次;
     * */
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        System.out.println("this is beforeclass");
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        System.out.println("this is afterclass");
    }

    @Before
    public void setUp() throws Exception {
        System.out.println("this is before");
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("this is after");
    }

    @Test
    public void test1() {
        System.out.println("this is test1");
    }

}

如果運行上面的代碼,就會得到下面的結(jié)果

6、junit的常用注解:

上面我已經(jīng)講解了@test,@BeforeClass,@AfterClass,@Before,@After這些注解的詳解可見這位仁兄的博客,下面提供相關(guān)地址:http://blog.csdn.net/zixiao217/article/details/52951679
對于@test,他除了將一個普通的方法修飾為測試方法外,還可以處理異常,設(shè)置超時。下面來對test的異常處理做講解test有兩個參數(shù):expected和timeout,即異常處理和設(shè)置超時如果對我們上面的除數(shù)為0的那個方法進行異常處理,那么我們就可以看到代碼能夠正常,測試通過,代碼如下:

@Test(expected=ArithmeticException.class)
public void testDivision(){
     assertEquals(6, new method_junti().division(6, 0));
}

在測試一些對性能有要求的方法中設(shè)置超時是很有必要的,它可以檢測你的代碼能否在這個
時間段內(nèi)運行出結(jié)果,設(shè)置方法如下:

@Test(timeout=2000)//單位是毫秒
 public void testWhile(){
    while(true){
        System.out.println("run forever");
    }
}

@Ignore:在test方法上加上該修飾,測試的時候就會不執(zhí)行該測試方法;
@RunWith可以更改測試運行器;我們除了使用junit提供的測試運行器之外,還可以自定義
我們的運行器,只要繼承org.junit.runner.Runner
代碼如下:

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})
public class SuitTest {
    
    public void test(){
        /*
         * 由于在開發(fā)的項目中,測試的類很多,一個一個運行很浪費時間,于是可以寫一個測試
         * 套件把所有需要測試的類組合在一起測試運行
         * 1、寫一個測試入口,這個類不含其它的方法;
         * 2、更改測試運行器@RunWith(Suite.class)
         * 3、將要測試的類作為數(shù)組放在@Suite.SuiteClasses({})中;
         */
        
    }
}

7、junit的參數(shù)設(shè)置

在上面的測試中,我們對一個方法都是只測試了一組數(shù)據(jù),可是在真正的項目中,一組數(shù)據(jù)往往是不夠的,我們需要很多組數(shù)據(jù),如果每一組數(shù)組寫一個測試方法的話那可把我們的工作人員累死了!這時我們可以使用參數(shù)設(shè)置來解決這個問題。
代碼如下:

package com.junit;
import static org.junit.Assert.*;

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

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

@RunWith(Parameterized.class)
public class ParameterTest {
    //聲明變量存放預(yù)期值和測試數(shù)據(jù);
    int expected=0;
    int input1=0;
    int input2=0;
    
    @Parameters
    public static Collection<Object[]> test(){
    
        return Arrays.asList(new Object[][]{
                {3,1,2},
                {4,2,2}
            });     
    }

    public ParameterTest(int expected,int input1,int input2){
        this.expected=expected;
        this.input1=input1;
        this.input2=input2;
    }
    @Test
    public void testAdd(){
        assertEquals(expected, new method_junti().add(input1, input2));
    }   
}

我們需要測試多組數(shù)據(jù),那么我們就需要用到數(shù)組來存放多組數(shù)據(jù),這里用Arrays.asList來接收。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容