單元測試系列一:使用JUint進行單元測試


1.   Junit簡介

1.1    什么是JUnit

JUnit是一個Java語言的單元測試框架,由Erich Gamma和Kent Beck編寫的一個回歸測試的框架(regression testing framework)。多數Java開發工具都已經集成了JUnit作為單元測試的工具,它是xUnit的一個子集。

XUnit是一套基於測試驅動開發的測試框架,可以使我們快速的進行單元測試,家族成員有PythonUnit、CppUnit、JUnit。

1.2    特性

JUnit是一個開放源代碼的Java測試框架,用於編寫和運行可重復的測試,包括以下特性:

1)用於測試期望結果的斷言(Assertion);

2)用於共享共同測試數據的測試工具;

3)用於方便的組織和運行測試的測試套件;

4)圖形和文本的測試運行器。

1.3    JUnit3與JUnit4的區別

JUnit3需要在方法名前加test作為前綴。

JUnit3中所有的方法都必須使用@text注解。

JUnit3必須繼承junit.framework.TestCase類。

1.4    為什么要使用JUnit

通常一個項目中有成千上萬的方法,以前一般的做法是寫一些測試代碼看輸出結果,然后由自己來判斷結果是否正確,使用JUnit的好處就是這個結果是否正確的判斷是由JUnit來完成的。我們只要關注結果是否正確就可以了。測試框架可以幫助我們對編寫的程序進行有目的性的測試,減少代碼中的bug,使用斷言機制直接將預期結果與實際結果對比,確保對結果的可預知性。

1.5    JUnit中使用到jar包

jar包就是別人已經寫好的一些類,然后將這些類進行打包,你可以將這些jar包引入到你的項目中,然后就可以直接使用這些jar包中的類和屬性以及方法。

JUint包含:

junit.jar。

hamcrest-core.jar,設置匹配性規則的一個框架,可以有效增強JUnit測試的能力。

2.   JUnit的基本過程

2.1    如何開發測試用例

eclipse中包含JUnit的測試框架,所以不需要單獨下載jar包,我們可以使用Eclipse進行單元測試。

1)首先,我們需要創建一個被測試類,打開選項eclipse,選擇File>>New>>Java Project,在Project Name中輸入項目名稱,例:junit4Demo,點擊“Finish”,如下圖所示:

2) 創建好的項目在Project Explorer中顯示,如下圖所示:

3) 項目名稱右鍵>>New>>Package,在Name中輸入包名,例:com.util,點擊“Finish”,如下圖所示:

 

4) 創建好的包顯示在項目的src目錄下,如下圖所示:

 

5) 包名右鍵>>New>>Class,在Name中輸入類名,例:Calculate,點擊“Finish”,如下圖所示:

6) 被測試類創建好后,如下圖所示:

7) 被測試類包含加減乘除的運算的四個方法,所以添加代碼如下:

package com.util;

public class Calculate {

         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 divide(int a,int b){

                   return a/b;

         }

}

8) 接下來導入JUnit的jar包,項目右鍵>>Build Path>>Configure Bulid Path,如下圖所示:

9) 選擇Libraries>>Add Library>>JUnit>> JUnit4,點擊“Finish”,點擊“OK”, JUnit的jar包被導入項目中,如下圖所示:

10) 為了保證源代碼與測試代碼的分離,查找起來方便,可以在src目錄下創建test目錄,src右鍵>>New>>Source Folder,Folder Name設置為“test”,點擊“Finish”,如下圖所示:

11) 創建好的目錄顯示在src目錄下,如下圖所示:

 

12) 包名右鍵>>New>>JUnit Test Cas,Name輸入“CalculateTest”,選擇Source folder為“test”點擊 “Finish”,如下圖所示:

13) 這個測試類會自動為我們生成一個測試方法的模板,如下圖所示:

14) 在測試類中添加加減乘除四個方法的被測試代碼,在測試過程中我們經常用到的斷言方法有:assertEquals方法,該方法可以判斷actualValue(實際值)與expectedValue(期望值)是否一致,如果兩者不一致,則會拋出java/lang.AssertionError錯誤,打印出message(如果參數中有message的話),並跳出這個測試方法,下面的測試方法就是用這個方法去判斷預期值與 實際值是否一致,如下圖所示:

package com.util;

import static org.junit.Assert.*;

import org.junit.Test;

public class CalcuateTest {

         @Test

         public void testAdd() {

                   assertEquals(6,new Calculate().add(4, 2));

         }

         @Test

         public void testSubtract() {

                   assertEquals(2,new Calculate().subtract(4, 2));

         }

         @Test

         public void testMultipy() {

                   assertEquals(8,new Calculate().multiply(4, 2));

         }

         @Test

         public void testDivide() {

                   assertEquals(6,new Calculate().divide(2, 4));

         }

}

15) 被測試類名右鍵>>Run As>>JUnit Test,選擇測試類,點擊“OK”,打開JUnit視圖,我們可以看到四個測試方法全部通過,如下圖所示:

2.2    介紹 JUnit視圖

Runs總共介個測試方法/運行方法的個數;

Errors拋出異常方法的計數器,是由代碼異常引起的,它可以產生於測試代碼本身的錯誤,也可能是被測試代碼中一個隱藏的bug;

Failures失敗方法的計數器,一般單元測試中使用斷言方法判斷失敗所引起的,這表示測試點發現了問題,就是誰程序輸出結果和我們預期的不一樣;

狀態條:綠色代表成功,紅色代表失敗;

空白區域:本次運行方法或類的個數;

總結:

1)測試方法前必須使用@Test進行修飾;

2)測試方法使用public void進行修飾,不能帶任何參數;

3)新建一個源代碼目錄來存在我們的測試代碼;

4)測試類的包應該和被測試類保持一致;

5)測試單元中的每個方法可以獨立測試,測試方法間不能有任務的依賴;

6)測試類使用Test作為類名的后綴(不是必須);

7)測試方法使用test作為方法名的前綴(不是必須)。

3.   JUnit的使用詳解

3.1    JUnit的運行流程

1)  創建一個測試方法,在JUnit Test Case頁面中輸入Name為“JunitFlowTest”,並選中頁面下方的四個方法,點擊“Finish”,如下圖所示:

2)  新建的測試類中自動生成這個方法的模板,我們會發現這四個方法並沒有使用@Test進行修飾,而是分別使用的@BeforeClass、@Before、@After、@AfterClass進行修飾,如下圖所示:

3)  我們在每個測試方法中打印一句話,在寫兩個使用@Test修飾的方法,代碼如下:

package com.util;

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

         @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...");

         }

         @Test

         public void test2() {

                   System.out.println("this is test2...");

         }

}

4)  運行測試類,查看運行結果:

總結:

1)  @BeforeClass修飾的方法會在所有方法前被調用前執行,而且該方法是靜態的,所以當測試類加載后接着就會運行它,而且在內存中它只會存在一份實例,它比較適合加載配置文件;

2)  @AfterClass所修飾的方法通常用來對資源的清理,如關閉數據庫鏈接;

3)  @Before和@After會在每個測試方法前各執行一次,通過被稱之為固定代碼的意思,意思就是一定會執行的代碼段。

3.2    常用注解

@Test是將一個普通的方法修飾為測試方法,Test有兩個屬性:

1.@Test(expected=xx.class)

1)  創建一個測試方法,在JUnit Test Case頁面中輸入Name為“AnotationTest”,,點擊“Finish”,在類中添加如下代碼:

package com.util;

import static org.junit.Assert.*;

import org.junit.Ignore;

import org.junit.Test;

public class AnotationTest {

         @Test(expected=ArithmeticException.class)

         public void testDivide() {

                   assertEquals(3,new Calculate().divide(6,0));

         }

}

2)  運行后查看JUnit視圖,觀察測試結果,我們可以發現測試結果通過,沒有報錯,如果處理異常的代碼刪除掉就會出錯,因為添加這個屬性后,預期會拋出一個算數異常,可以捕獲這個異常,如下圖所示:

2.@Test(timeout=毫秒)

1)  在AnotationTest類中修改代碼如下:

package com.util;

import static org.junit.Assert.*;

import org.junit.Ignore;

import org.junit.Test;

public class AnotationTest {

         @Test(timeout=2000)

         public void testWhile(){

                   while(true){

                            System.out.println("run forever");

                   }

         }

}

2)  運行后查看運行結果,如下圖所示,發現沒有一直循環下去,在2s時自動結束循環,可以用它來做一些簡單的性能測試,比如說讀取一個文件,可以設置超時時間,如果超過這個時間可以認為測試不成功。

@Ignore所修飾的方法會被測試運行器忽略

1)  在AnotationTest類中修改代碼如下:

package com.util;

import static org.junit.Assert.*;

import org.junit.Ignore;

import org.junit.Test;

public class AnotationTest {

         @Ignore

         @Test(timeout=2000)

         public void testWhile(){

                   while(true){

                            System.out.println("run forever");

                   }

         }

}

2)  運行后查看運行結果,如下圖所示,在JUnit視圖中可以看到這個方法並沒有被執行,該方法會被測試運行器所忽略。

3.3    JUint測試套件的使用

在測試過程中,隨着項目的深入,項目的規模會越來越大,相應的測試類也會越來越多,那么會如果100個測試類,是不是就要運行100次,JUnit為我們提供了一個批量運行的測試類的方法,叫做測試套件,使用測試套件我們可以將所有的測試類都集合在一個測試套件中,這樣每次需要驗證系統功能的時候,只需要執行一次我們的測試套件就可以了。

如何編寫測試套件?

1)創建一個測試類,命名為SuiteTest,測試套件有一個特點,它是一個空類,所以我們將默認的test()方法刪除掉,如下圖所示:

2)我們在再新建兩個測試類,分別為TaskTest1,TaskTest2,打印一句話,如下圖所示:

3)需要使用@RunWith這個注解,修改測試運行器,將其修改為Suite.class,這樣這個類就成為測試套件的入口類,然后使用Suite.SuiteClass(),需要放入測試套件的測試類(或測試套件),它是以數組的形式作為參數,編寫的代碼如下圖所示:

package com.util;

import static org.junit.Assert.*;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.junit.runners.Suite;

@RunWith(Suite.class)

@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class})

public class SuiteTest {   

}

4)運行結果如下,可以看到TaskTest1.class、TaskTest2.class都運行了。

總結:

1)  @RunWith可以更改測試運行器,本次測試套件中更改測試運行為Suite.class;

2)  測試套件就是組織測試類一起運行的;

3)  寫一個作為測試套件的入口類,這個類里不包含其他的方法;

4)  將要測試的類作為數據傳入Suite.SuiteClass({}).

3.4    JUnit參數化設置

為了提高測試代碼的可重用度,在JUnit4中提供了參數化測試可以解決這個問題,下面看一下參數設置的步驟:

1)創建一個測試類,名稱為ParameterTest,將自動生成的測試方法的代碼刪除,如下圖所示:

2)更改測試運行器,更改為Parameterized;

3)聲明變量來存放預期值和測試數據;

4)為測試類聲明一個返回值為Collection的公共靜態方法;

5)需要一個數組類型來存放多組數據,添加@Paramters注解;

6)為測試類聲明一個帶有參數的公共的構造函數;

7)還有寫一個對加法測試的方法,整體的測試代碼如下:

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 {
    int expected=0;
    int input1=0;
    int input2=0;
    @Parameters
    public static Collection<Object[]> t(){
        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 Calculate().add( input1,input2));
    }

8)結果如下圖所示,可以看到對加法進行了兩組數據測試,使用這種方法可以對多組數據同時進行測試。

總結:

1)更改默認的測試運行器為RunWith(Parameterized.class);

2)聲明變量來存放預期值和結果值;

3)聲明一個返回值為Collection的公共靜態方法,並使用@Parameters進行修飾;

4)為測試類聲明一個帶有參數的公共構造函數,並在其中為之聲明變量賦值。

4.   Eclipse的安裝

4.1    Windows下Eclipse的安裝

1.安裝Eclipse之前,需要安裝java sdk,並將java的路徑配置到系統路徑中。

1) 首先下載如jak 1.6的版本,然后進行解壓,如圖:

2) 打開jdk-6u39-windows-i586-20151102\jdk-6u39-windows-i586目錄,運行“jdk-6u39-windows-i586.exe”,如圖:

3) 點擊“下一步”,進入自定義安裝界面,如圖:

4) 點擊“下一步”,進入安裝目標文件夾,如圖:

5) 點擊“下一步”,進入安裝進度頁面,如圖:

6) 安裝完成后,點擊“完成”,安裝完成。

7) 安裝完成后需要設置環境變量后編譯器才能正常使用,找到jdk安裝路徑C:\Program Files\Java\jdk1.6.0_39,然后右鍵“我的電腦>>屬性高級>>環境變量”,打開“環境變量”對話框,如圖:

8) 在系統變量里點擊新建,變量名稱寫JAVA_HOME,變量值填寫JDK的安裝路徑C:\Program Files\Java\jdk1.6.0_39,如圖:

9) 在系統變量里點擊新建,變量名稱填寫CLASSPATH,變量值填寫“.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar”,如圖:

10) 在系統變量里找打Path變量,這是系統自帶的,不用新建。雙擊Path,由於原來的變量值已經存在,故應在已有的變量后加上“;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin”。如圖:

11) 環境變量配置完畢,驗證的方法:在運行框中輸入cmd命令,回車輸入java,按回車出現以下畫面,如圖:

12) 輸入javac,安回車出現以下畫面,則表示設置成功,如圖:

2.下載Eclipse時注意系統的位數是32位還是64位的。

1)  下載完成后進行解壓,然后雙擊eclipse.exe進行安裝,如下圖所示:

2)  安裝過程完成后,直接打開Ide窗口,如下圖所示:

4.2    Linux下Eclipse的安裝

1    安裝Eclipse之前,需要安裝java sdk,並將java的路徑配置到系統路徑中。

1)  將壓縮包解壓到指定的安裝目錄,比如/usr,如下圖所示:

2)  此時生成名為jdk1.8.0_20的目錄,將其重命名為jdk,這一步是可選的,如下圖所示:

3)  修改/etc/profile文件,添加環境變量,如下圖所示:

4)  在文末添加下面的內容(需根據個人JDK實際安裝位置進行配置),如下圖所示:

5)  讓/etc/profile文件修改后立即生效 ,可以使用如下命令(注意"."和"/"之間的空格),如下圖所示:

6)  驗證Jdk安裝成功,查看一下Java版本,如下圖所示:

2   下載Eclipse時注意系統的位數是32位還是64位的。

1)  進入到Eclipse存放路徑,並進行解壓,如下圖所示:

2)  切換到安裝包的目錄,進行安裝,如下圖所示:

3)  選擇“Eclipse Platform”,點擊“Next”, 如下圖所示:

4)  點擊“Next”, 如下圖所示:

5)  點擊“Finish”, 如下圖所示:

6)  等待安裝,如下圖所示:

7)  點擊“Finish”,完成安裝,如下圖所示:

8)  在安裝目錄運行Eclipse,顯示如下圖,成功安裝!如下圖所示:

 


免責聲明!

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



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