測試在軟件生命週期中的重要性,不用我多說想必你們也都很是清楚。軟件測試有不少分類,從測試的方法上可分爲:黑盒測試、白盒測試、靜態測試、動態測試等;從軟件開發的過程分爲:單元測試、集成測試、確認測試、驗收、迴歸等。java
在衆多的分類中,與開發人員關係最緊密的莫過於單元測試了。像其餘種類的測試基本上都是由專門的測試人員來完成,只有單元測試是徹底由開發人員來完成的。那麼今天咱們就來講說什麼是單元測試,爲何要進行單元測試,以及如更好的何進行單元測試。 小程序
什麼是單元測試? less
單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。好比咱們能夠測試一個類,或者一個類中的一個方法。
ide
爲何要進行單元測試? 函數
爲何要進行單元測試?說白了就是單元測試有什麼好處,其實測試的好處無非就是減小bug、提升代碼質量、使代碼易於維護等。單元測試有什麼好處請看一下百度百科中概括的四條: 工具
一、它是一種驗證行爲。
程序中的每一項功能都是測試來驗證它的正確性。它爲之後的開發提供支援。就算是開發後期,咱們也能夠輕鬆的增長功能或更改程序結構,而不用擔憂這個過程當中會破壞重要的東西。並且它爲代碼的重構提供了保障。這樣,咱們就能夠更自由的對程序進行改進。 單元測試
二、它是一種設計行爲。
編寫單元測試將使咱們從調用者觀察、思考。特別是先寫測試(test-first),迫使咱們把程序設計成易於調用和可測試的,即迫使咱們解除軟件中的耦合。 測試
三、它是一種編寫文檔的行爲。
單元測試是一種無價的文檔,它是展現函數或類如何使用的最佳文檔。這份文檔是可編譯、可運行的,而且它保持最新,永遠與代碼同步。 spa
四、它具備迴歸性。
自動化的單元測試避免了代碼出現迴歸,編寫完成以後,能夠隨時隨地的快速運行測試。
設計
如何更好的進行單元測試?
在討論如何更好的進行單元測試以前,先來看看咱們之前是怎麼測試代碼的。
之前是這樣測試程序的:
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" ) );