菜鳥學Java(二十一)——如何更好的進行單元測試——JUnit


測試在軟件生命周期中的重要性,不用我多說想必大家也都非常清楚。軟件測試有很多分類,從測試的方法上可分為:黑盒測試、白盒測試、靜態測試、動態測試等;從軟件開發的過程分為:單元測試、集成測試、確認測試、驗收、回歸等。


在眾多的分類中,與開發人員關系最緊密的莫過於單元測試了。像其他種類的測試基本上都是由專門的測試人員來完成,只有單元測試是完全由開發人員來完成的。那么今天我們就來說說什么是單元測試,為什么要進行單元測試,以及如更好的何進行單元測試。


什么是單元測試?

單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。比如我們可以測試一個類,或者一個類中的一個方法。


為什么要進行單元測試?

為什么要進行單元測試?說白了就是單元測試有什么好處,其實測試的好處無非就是減少bug、提高代碼質量、使代碼易於維護等。單元測試有什么好處請看一下百度百科中歸納的四條:


1、它是一種驗證行為。
程序中的每一項功能都是測試來驗證它的正確性。它為以后的開發提供支援。就算是開發后期,我們也可以輕松的增加功能或更改程序結構,而不用擔心這個過程中會破壞重要的東西。而且它為代碼的重構提供了保障。這樣,我們就可以更自由的對程序進行改進。


2、它是一種設計行為。
編寫單元測試將使我們從調用者觀察、思考。特別是先寫測試(test-first),迫使我們把程序設計成易於調用和可測試的,即迫使我們解除軟件中的耦合。


3、它是一種編寫文檔的行為。
單元測試是一種無價的文檔,它是展示函數或類如何使用的最佳文檔。這份文檔是可編譯、可運行的,並且它保持最新,永遠與代碼同步。


4、它具有回歸性。
自動化的單元測試避免了代碼出現回歸,編寫完成之后,可以隨時隨地的快速運行測試。


如何更好的進行單元測試?


在討論如何更好的進行單元測試之前,先來看看我們以前是怎么測試代碼的。

以前是這樣測試程序的:

 

    public int add(int x,int y) {
        return x + y;
    }
        
    public static void main(String args[]) {
        int z = new Junit().add(2, 3);
        System.out.println(z);
    }

 

 

如上面所示,在測試我們寫好的一個方法時,通常是用一個main方法調用一下我們要測試的方法,然后將結果打印一下。現在看來這種方式已經非常out了,所以出現了很多單元測試的工具,如:JUnit、TestNG等。借助它們可以讓我們的單元測試變得非常方便、高效。今天就說說如何利用JUnit進行單元測試。


我們新建一個Java Project以便進行演示,至於Java Project怎么創建我就不在此贅述了,如果連怎么建Java Project,那你還不適合看這篇文章。建好以后在該項目的“src”目錄上右擊,選擇new——》JUnit Test Case,然后按下圖填寫必要信息:



填寫好包名和類名(選擇New JUnit 4 Test),點擊最下面的那個“Browse”按鈕來選擇需要測試的類:



手動輸入我們要測試的類,選擇該類,點擊“OK”,回到第一張圖的界面,然后點擊“Next”,來到下圖:



勾選要測試的方法,點擊“Finish”,這樣我們的JUnit測試實例就建好了。然后就可以寫具體的測試了:

 

 
        
package com.tgb.junit.test;

//靜態引入
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

import com.tgb.junit.Junit;

public class JUnitTest {

    @Test
    public void testAdd() {
        int z = new  Junit().add(2, 3);
        assertThat(z , is(5));
    }

    @Test
    public void testDivide() {
        int z = new Junit().divide(4, 2);        
        assertThat(z, is(2));
    }
}
 
        

 

 
        


寫好以后,右擊該類選擇“Run As”——》“JUnit Test”,出現下圖代表測試通過:

 



到這里,可能有人會有疑問,JUnit跟用main方法測試有什么區別呢?

首先,JUnit的結果更加直觀,直接根據狀態條的顏色即可判斷測試是否通過,而用main方法你需要去檢查他的輸出結果,然后跟自己的期望結果進行對比,才能知道是否測試通過。有一句話能夠很直觀的說明這一點——keeps the bar green to keeps the code clean。意思就是說,只要狀態條是綠色的,那么你的代碼就是正確的。

第二點,JUnit讓我們同時運行多個測試變得非常方便,下面就演示一下如何進行多實例測試:

首先我們要再建一個待測試類,然后再建一個對應的JUnit測試實例,步驟略。然后在我們測試實例的包上右擊選擇“Run As”——》“Run Configurations”,如下圖;



選擇第二項“Run all tests in the selected project, package or source folder”,然后點擊“Run”效果如下:



可以看到,我們本次測試了兩個類,共三個方法,這種方便的效果在測試實例越多的情況下,體現的越明顯。至於main方法運行多個測試,想想就覺得非常麻煩,這里就不演示了。


JUnit除了可以測試這些簡單的小程序,還可以測試Struts、JDBC等等,這里只是用這個小程序做過簡單的介紹。本實例使用的是hamcrest斷言,而沒有使用老的斷言,因為hamcrest斷言更加接近自然語言的表達方式,更易於理解。


本實例需要引入以下三個jar包:

hamcrest-core-1.3.jar
hamcrest-library-1.3.jar
junit-4.10.jar


最后附上常用hamcrest斷言的使用說明:

數值類型
//n大於1並且小於15,則測試通過
assertThat( n, allOf( greaterThan(1), lessThan(15) ) );
//n大於16或小於8,則測試通過
assertThat( n, anyOf( greaterThan(16), lessThan(8) ) );
//n為任何值,都測試通過
assertThat( n, anything() );
//d與3.0的差在±0.3之間,則測試通過
assertThat( d, closeTo( 3.0, 0.3 ) );
//d大於等於5.0,則測試通過
assertThat( d, greaterThanOrEqualTo (5.0) );
//d小於等於16.0,則測試通過
assertThat( d, lessThanOrEqualTo (16.0) );

字符類型
//str的值為“tgb”,則測試通過
assertThat( str, is( "tgb" ) );
//str的值不是“tgb”,則測試通過
assertThat( str, not( "tgb" ) );
//str的值包含“tgb”,則測試通過
assertThat( str, containsString( "tgb" ) );
//str以“tgb”結尾,則測試通過
assertThat( str, endsWith("tgb" ) ); 
//str以“tgb”開頭,則測試通過
assertThat( str, startsWith( "tgb" ) ); 
//str忽略大小寫后,值為“tgb”,則測試通過
assertThat( str, equalToIgnoringCase( "tgb" ) ); 
//str忽略空格后,值為“tgb”,則測試通過
assertThat( str, equalToIgnoringWhiteSpace( "tgb" ) );
//n與nExpected相等,則測試通過(對象之間)
assertThat( n, equalTo( nExpected ) ); 

collection類型
//map中包含key和value為“tgb”的鍵值對,則測試通過
assertThat( map, hasEntry( "tgb", "tgb" ) );
//list中包含“tgb”元素,則測試通過
assertThat( iterable, hasItem ( "tgb" ) );
//map中包含key為“tgb”的元素,則測試通過
assertThat( map, hasKey ( "tgb" ) );
//map中包含value為“tgb”的元素,則測試通過
assertThat( map, hasValue ( "tgb" ) );

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM