在 NetBeans IDE 中編寫 JUnit 測試

測試應用程序是開發週期中不可缺乏的一部分,而且編寫和維護測試單元有利於確保源代碼中的方法能正常運行。IDE 集成了對 JUnit 單元測試框架的支持,它容許您快速和輕鬆地建立 JUnit 測試和測試套件。html

在本教程中,您將爲 Java 類庫項目建立簡單的 JUnit 3 JUnit 4 單元測試及測試套件。教程的第 1 部分演示如何在 JUnit 3 中建立測試。第 2 部分演示如何使用 JUnit 標註在 JUnit 4 中建立相同的測試。這兩個部分建立的測試是相同的,所以沒有必要同時完成二者,可是查看測試的兩種編寫方法能夠幫助您瞭解 JUnit 4 中引入的一些變化。。java

建立項目數據庫

要完成本教程,您首先須要建立一個名稱爲 JUnit-Sample Java 類庫項目。建立項目後,您須要將樣例項目 JUnitSampleSol 中的兩個類複製到項目 JUnit-Sample 中。框架

建立 Java 類庫項目dom

1.     從主菜單選擇文件」>「新建項目 編輯器

2.     「Java」類別中選擇「Java 類庫並單擊下一步 ide

3.     鍵入 JUnit-Sample 做爲項目名稱並設置項目位置。 函數

4.     取消選中使用專用文件夾存儲庫選項(若是該選項處於選中狀態)。 工具

在本教程中,咱們將項目庫複製到一個專門的文件夾中,由於須要與其餘用戶或項目共享庫。此選項對於 NetBeans IDE 6.0 不可用。單元測試

單擊下一步

5.     單擊完成

建立項目以後,若是您查看項目窗口中的測試庫節點,您會看到項目包含 JUnit 3 JUnit 4 庫。缺省狀況下,IDE 會在新項目中添加這兩個庫。第一次建立 JUnit 測試時,IDE會提示您選擇一個版本,而後刪除不須要的庫。

·        

·         經過執行如下步驟從 Kenai 簽出項目源代碼:

1.     從主菜單中選擇團隊開發」> "Kenai" >「 Kenai 中獲取源代碼

或者,也能夠選擇打開 Kenai 項目以將項目添加到 "Kenai" 控制板,而後獲取項目源代碼。

2.     Kenai 中獲取源代碼對話框中,單擊「Kenai 資源庫旁邊的瀏覽以打開瀏覽 Kenai 項目對話框,從而找到 Kenai 資源庫。

3.     輸入 NetBeans IDE Samples Catalog 以進行搜索。

4.     選擇 "NetBeans IDE Samples Catalog"NetBeans IDE 樣例目錄)並單擊肯定

5.     單擊要獲取的文件夾旁邊的瀏覽以指定要獲取的文件夾,而後選擇 "NB67" / "Java" / "JUnitSampleSol"。單擊肯定

6.     指定用於存儲源代碼的本地文件夾(本地文件夾必須爲空)。

7.     單擊 Kenai 中獲取

單擊 Kenai 中獲取後,IDE 會將本地文件夾初始化爲 Subversion 資源庫,並簽出項目源代碼。

8.     在完成簽出操做後將會顯示一個對話框,在該對話框中單擊打開項目

建立 Java

在本練習中,您須要將樣例項目 JUnitSampleSol 中的文件 Utils.java Vectors.java 複製到您建立的類庫項目中。

1.     項目窗口中,右鍵單擊 JUnit-Sample 項目的源包節點,而後從彈出式菜單中選擇新建」>「Java

2.     鍵入 sample 做爲包名。單擊完成

3.     IDE 中打開 JUnitSampleSol 項目,而後在項目窗口中展開該項目節點。

4.     JUnitSampleSol 項目 Source Packages 文件夾中的 Utils.java Vectors.java 複製到 JUnit-Sample sample 源包中。

若是您查看類的源代碼,您能夠看到 Utils.java 包含三個方法(computeFactorialconcatWords normalizeWord),而且 Vectors.java 包含兩個方法(equals scalarMultiplication)。接下來,爲各種建立測試類併爲這些方法編寫一些測試用例。

編寫 JUnit 3 單元測試

在本節中,您將爲 Vectors.java Utils.java 類建立基本的 JUnit 3 單元測試。您將使用 IDE 根據您項目中的類來建立框架測試類。而後,您將修改生成的測試方法並添加新測試方法。

第一次使用 IDE 在項目中建立測試時,IDE 將提示您選擇一個 JUnit 版本。您選擇的版本將成爲缺省的 JUnit 版本,而且 IDE 將爲該版本生成全部後續測試和測試套件。

Vectors.java 建立測試類

在本練習中,您將爲 Vectors.java 建立一個 JUnit 測試框架。

1.     右鍵單擊 Vectors.java 並選擇工具」>「建立 JUnit 測試

2.     選擇 JUnit 版本對話框中,選擇「JUnit 3.x」

當您選擇 JUnit 3.x 時,IDE 將從項目中刪除 JUnit 4 庫。

3.     建立測試對話框中,將測試類的名稱修改成 VectorsJUnit3Test

更改測試類的名稱以後,您將看到一個關於修更名稱的警告。缺省名稱基於要測試的類名,並在該名稱後面附加單詞 Test。舉例來講,對於 MyClass.java 類,測試類的缺省名稱爲 MyClassTest.java。一般,最好是保留缺省名稱,可是在教程中您將更改該名稱,由於您還將在相同的包中建立 JUnit 4 測試,而且測試類的名稱必須是唯一的。

4.     取消選中測試初始化函數測試釋放方法單擊肯定

單擊肯定以後,IDE 將在 sample 測試包目錄中建立一個 JUnit 測試框架。

項目須要一個目錄供測試包建立測試。測試包目錄的缺省位置爲項目的根目錄,可是根據項目的不一樣,您能夠在項目的屬性對話框中爲目錄指定不一樣的位置。

在編輯器中查看生成的測試類 VectorsJUnit3Test.java,您能夠看到 IDE equal scalarMultiplication 方法生成了如下具有測試方法的測試類。

public class VectorsJUnit3Test extends TestCase {

    /**

     * Test of equal method, of class Vectors.

     */

    public void testEqual() {

        System.out.println("equal");

        int[] a = null;

        int[] b = null;

        boolean expResult = false;

        boolean result = Vectors.equal(a, b);

        assertEquals(expResult, result);

        // TODO review the generated test code and remove the default call to fail.

        fail("The test case is a prototype.");

    }

 

    /**

     * Test of scalarMultiplication method, of class Vectors.

     */

    public void testScalarMultiplication() {

        System.out.println("scalarMultiplication");

        int[] a = null;

        int[] b = null;

        int expResult = 0;

        int result = Vectors.scalarMultiplication(a, b);

        assertEquals(expResult, result);

        // TODO review the generated test code and remove the default call to fail.

        fail("The test case is a prototype.");

    }

}

各生成測試的方法主體是做爲指導單獨提供的,所以須要將它們修改成實際的測試用例。若是您不須要生成的代碼,能夠在建立測試對話框中取消選中缺省方法主體

IDE 生成測試方法的名稱時,各方法名稱將前面附加一個 test,由於 JUnit 3 使用命名約定和反射來標識測試。要標識測試方法,各測試方法須要遵循 test<NAME> 語法。

JUnit 4 中,再也不須要使用這種測試方法命名語法,由於您可使用標註來標識測試方法,而且測試類再也不須要擴展 TestCase

Vectors.java 編寫測試方法

在本練習中,您將修改生成的方法以實現測試功能,並修改缺省的輸出消息。您不須要修改運行測試的輸出消息,可是您可能但願修改輸出來幫助標識顯示在「JUnit 測試結果輸出窗口中的結果。

1.     在編輯器中打開 VectorsJUnit3Test.java

2.     修改 testScalarMultiplication 的測試框架,方法是修改 println 的值並刪除生成的變量。如今,測試方法應以下所示(粗體爲更改部分):

3.  public void testScalarMultiplication() {

4.      System.out.println("* VectorsJUnit3Test: testScalarMultiplication()");

5.      assertEquals(expResult, result);

}

6.     如今,添加一些斷言來測試方法。

7.  public void testScalarMultiplication() {

8.      System.out.println("* VectorsJUnit3Test: testScalarMultiplication()");

9.      assertEquals(  0, Vectors.scalarMultiplication(new int[] { 0, 0}, new int[] { 0, 0}));

10.    assertEquals( 39, Vectors.scalarMultiplication(new int[] { 3, 4}, new int[] { 5, 6}));

11.    assertEquals(-39, Vectors.scalarMultiplication(new int[] {-3, 4}, new int[] { 5,-6}));

12.    assertEquals(  0, Vectors.scalarMultiplication(new int[] { 5, 9}, new int[] {-9, 5}));

13.    assertEquals(100, Vectors.scalarMultiplication(new int[] { 6, 8}, new int[] { 6, 8}));

}

該測試方法使用 JUnit assertEquals 方法。要使用斷言,您須要提供輸入變量和預期的結果。在運行被測試的方法時,要經過測試,測試方法必須根據提供的變量成功返回全部預期的結果。您應該添加足夠數量的斷言來涵蓋各類可能的排列。

14.  修改 testEqual 的測試框架:刪除生成的方法主體並添加如下 println

    System.out.println("* VectorsJUnit3Test: testEqual()");

如今,測試方法應以下所示:

public void testEqual() {

    System.out.println("* VectorsJUnit3Test: testEqual()");

}

15.  修改 testEqual 方法:添加如下斷言(顯示爲粗體)。

16.public void testEqual() {

17.    System.out.println("* VectorsJUnit3Test: testEqual()");

18.    assertTrue(Vectors.equal(new int[] {}, new int[] {}));

19.    assertTrue(Vectors.equal(new int[] {0}, new int[] {0}));

20.    assertTrue(Vectors.equal(new int[] {0, 0}, new int[] {0, 0}));

21.    assertTrue(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 0}));

22.    assertTrue(Vectors.equal(new int[] {5, 6, 7}, new int[] {5, 6, 7}));

23. 

24.    assertFalse(Vectors.equal(new int[] {}, new int[] {0}));

25.    assertFalse(Vectors.equal(new int[] {0}, new int[] {0, 0}));

26.    assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0, 0, 0}));

27.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0}));

28.    assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0}));

29.    assertFalse(Vectors.equal(new int[] {0}, new int[] {}));

30. 

31.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 1}));

32.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 1, 0}));

33.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {1, 0, 0}));

34.    assertFalse(Vectors.equal(new int[] {0, 0, 1}, new int[] {0, 0, 3}));

}

此方法使用 JUnit assertTrue assertFalse 方法來測試各類可能的結果。要經過此方法的測試,assertTrue 必須所有爲 true,而且 assertFalse 必須所有爲 false

Utils.java 建立測試類

如今,你能夠爲 Utils.java 建立測試框架。在上一練習中建立了測試以後,IDE 會提示您選擇 JUnit 的版本。但此次,並無提示要求您選擇版本。

1.     右鍵單擊 Utils.java 並選擇工具」>「建立 JUnit 測試

2.     在對話框中,選中測試初始化函數測試釋放方法(若是爲未選中狀態)。

3.     建立測試對話框中,將測試類的名稱修改成 UtilsJUnit3Test。單擊肯定

單擊肯定以後,IDE 將在測試包」>"samples" 目錄中建立測試文件UtilsJUnit3Test.java。能夠看到,除了爲 Utils.java 中的方法建立 testComputeFactorialtestConcatWords testNormalizeWord 測試框架以外,IDE 還建立了測試初始化函數方法 setUp 和測試釋放方法 tearDown

Utils.java 編寫測試方法

在本練習中,您將添加一些測試用例來演示一些經常使用的 JUnit 測試元素。您還將在方法中添加 println,由於一些方法缺省不打印任何輸出。經過在方法中添加 println,您能夠稍後在 JUnit 測試結果窗口中查看方法是否已經運行以及它們運行的順序。

測試初始化函數和釋放方法

setUp tearDown 方法用於初始化和釋放測試條件。您不須要使用 setUp tearDown 方法來測試 Utils.java,可是此處演示了它們的運行原理。

setUp 方法是一個測試初始化方法,它在測試類中的各測試用例以前運行。運行測試不須要測試初始化方法,可是,若是您須要在運行測試以前初始化一些變量,則可使用測試初始化方法。

setUp 方法是一個測試釋放方法,它在測試類中的各測試用例以後運行。運行測試不須要測試釋放方法,可是,您可能須要使用釋放方法來清理運行測試用例時所需的任何數據。

1.     執行如下更改(顯示爲粗體),在各方法中添加一個 println

2.  @Override

3.  protected void setUp() throws Exception {

4.      super.setUp();

5.      System.out.println("* UtilsJUnit3Test: setUp() method");

6.  }

7.   

8.  @Override

9.  protected void tearDown() throws Exception {

10.    super.tearDown();

11.    System.out.println("* UtilsJUnit3Test: tearDown() method");

}

運行測試時,各方法的 println 文本將出如今「JUnit 測試結果輸出窗口中。若是您沒有添加 println,則不會在輸出中顯示方法已經運行。

在測試中使用簡單的斷言

這個簡單的測試用例將測試 concatWords 方法。您沒有使用生成的 testConcatWords 測試方法,而是使用新的 testHelloWorld 測試方法,該方法使用單個簡單的斷言來測試方法是否正確地鏈接了字符串。測試用例中的 assertEquals 將使用 assertEquals(EXPECTED_RESULT, ACTUAL_RESULT) 語法來測試預期結果是否等於實際結果。在本例中,若是 concatWords 方法的輸入爲 "Hello"", ","world" "!",則預期結果應該等於 "Hello, world!"

1.     刪除生成的測試方法 testConcatWords

2.     添加如下方法來測試concatWords 方法。

3.  public void testHelloWorld() {

4.      assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));

}

5.     添加一個 println 語句,用於在「JUnit 測試結果窗口中顯示關於測試的文本。

6.  public void testHelloWorld() {

7.      System.out.println("* UtilsJUnit3Test: test method 1 - testHelloWorld()");

    assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));

比較:在測試中使用簡單的斷言(JUnit 4

在測試中使用超時

此測試演示如何檢查方法的完成是否花費了過長的時間。若是方法花費了過長的時間,則測試線程將中斷並致使測試失敗。您能夠在測試中指定時間限制。

測試方法將調用 Utils.java 中的 computeFactorial 方法。您能夠假定 computeFactorial 方法是正確的,可是在本例中,您但願測試計算是不是在 1000 毫秒以內完成的。computeFactorial 線程和測試線程是在相同時間啓動的。測試線程將在 1000 毫秒事後中止並拋出一個 TimeoutException 異常,除非 computeFactorial 線程先於它完成。您將添加一條消息,這樣在拋出 TimeoutException 時會顯示該消息。

1.     刪除生成的測試方法 testComputeFactorial

2.     添加 testWithTimeout 方法,該方法用於計算隨機生成數的階乘。

3.  public void testWithTimeout() throws InterruptedException, TimeoutException {

4.      final int factorialOf = 1 + (int) (30000 * Math.random());

5.      System.out.println("computing " + factorialOf + '!');

6.   

7.      Thread testThread = new Thread() {

8.          public void run() {

9.              System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

10.        }

11.    };

}

12.  修復導入,以導入 java.util.concurrent.TimeoutException

13.  在方法中添加如下代碼(顯示爲粗體),其做用是當測試任務的執行時間過長時中斷線程並顯示一條消息。

14.    Thread testThread = new Thread() {

15.        public void run() {

16.            System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

17.        }

18.    };

19. 

20.    testThread.start();

21.    Thread.sleep(1000);

22.    testThread.interrupt();

23. 

24.    if (testThread.isInterrupted()) {

25.        throw new TimeoutException("the test took too long to complete");

26.    }

}

在拋出超時以前,您能夠經過修改 Thread.sleep 代碼行來更改毫秒數。

27.  添加如下 println(顯示爲粗體),用於在「JUnit 測試結果窗口中輸出關於測試的文本。

28.public void testWithTimeout() throws InterruptedException, TimeoutException {

29.    System.out.println("* UtilsJUnit3Test: test method 2 - testWithTimeout()");

30.    final int factorialOf = 1 + (int) (30000 * Math.random());

31.    System.out.println("computing " + factorialOf + '!');

           

針對預期異常的測試

此測試演示如何針對預期異常進行測試。若是未拋出指定的預期異常,則會致使方法失敗。在本例中,您將測試當輸入變量爲負數時(-5),computeFactorial 方法是否會拋出 IllegalArgumentException

1.     添加如下 testExpectedException 方法,它將以輸入 -5 調用 computeFactorial 方法。

2.  public void testExpectedException() {

3.      try {

4.          final int factorialOf = -5;

5.          System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

6.          fail("IllegalArgumentException was expected");

7.      } catch (IllegalArgumentException ex) {

8.      }

}

9.     添加如下 println(顯示爲粗體),用於在「JUnit 測試結果窗口中輸出關於測試的文本。

10.public void testExpectedException() {

11.    System.out.println("* UtilsJUnit3Test: test method 3 - testExpectedException()");

    try {

禁用測試

此測試演示如何臨時禁用測試方法。在 JUnit 3 中,若是某個方法名稱沒有以 test 開頭,則它不會被識別爲測試方法。在本例中,您將 DISABLED 置於測試方法的名稱以前來禁用它。

1.     刪除生成的測試方法 testNormalizeWord

2.     在測試類中添加如下測試方法:

3.  public void testTemporarilyDisabled() throws Exception {

4.      System.out.println("* UtilsJUnit3Test: test method 4 - checkExpectedException()");

5.      assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));

}

測試方法 testTemporarilyDisabled 將在您運行測試類時運行。

6.     DISABLED_(顯示爲粗體)置於測試方法的名稱以前。

7.  public void DISABLED_testTemporarilyDisabled() throws Exception {

8.      System.out.println("* UtilsJUnit3Test: test method 4 - checkExpectedException()");

9.      assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));

}

如今,您已經編寫了測試。接下來,您能夠運行測試並在「JUnit 測試結果窗口中查看測試輸出。

運行測試

運行 JUnit 測試以後,結果將顯示在 IDE 「JUnit 測試結果窗口中。您能夠單獨運行 JUnit 測試類,或者也能夠從主菜單中選擇運行」>「測試 PROJECT_NAME來運行項目的全部測試。若是您選擇運行」>「測試,則 IDE 將運行測試包文件夾中的全部測試類。要運行單獨的測試類,右鍵單擊測試包節點下的測試類並選擇運行文件

·         從主菜單中選擇運行」>「測試項目 (JUnit-Sample)」

運行測試以後,您將在「JUnit 測試結果窗口中看到如下結果之一:

在此圖像中(單擊圖像查看大圖),您能夠看到項目經過了全部測試。左側窗格顯示各測試方法的結果,右側窗格顯示測試輸出。若是您查看輸出,您能夠看到測試運行的順序。添加到各測試方法中的 println 在輸出窗口中輸出測試的名稱。您還能夠看到,在 UtilJUnit3Test 中,setUp 方法在各測試方法以前運行,而 tearDown 方法在各方法以後運行。

在此圖像中(單擊圖像查看大圖),您能夠看到項目未經過其中一個測試。testTimeout 方法花費了過長的運行時間,而且測試線程被中斷,致使測試失敗。它花了超過 1000 毫秒來計算出隨機生成數(22991)的階乘。.

建立單元測試類後,下一步將建立測試套件。請參見建立 JUnit 3 測試套件,瞭解如何以組的方式運行特定的測試,從而避免單獨運行各個測試。

編寫 JUnit 4 測試

在本練習中,您將爲 Vectors.java Utils.java 建立 JUnit 4 單元測試。JUnit 4 測試用例與 JUnit 3 測試用例相同,可是您會發現其編寫測試的語法更加簡單。

您將使用 IDE 根據項目中的類來建立測試框架。第一次使用 IDE 建立測試框架時,IDE 會提示您選擇 JUnit 版本。

若是您已經選擇了 JUnit 3.x 做爲測試缺省版本,則須要將缺省版本更改成 JUnit 4.x。要更改缺省的 JUnit 版本,右鍵單擊測試庫節點,選擇添加庫並將 JUnit 4 庫添加到項目中。建立新測試時,在提示選擇 JUnit 版本的窗口中選擇 version 4.x。選擇 JUnit 4.x 以後,IDE 將刪除沒必要要的 JUnit 3.x 庫。您仍然能夠運行 JUnit 3 測試,可是您建立的任何新測試都將使用 JUnit 4

Vectors.java 建立測試類

在本練習中,您將爲 Vectors.java 建立 JUnit 測試框架。

1.     右鍵單擊 Vectors.java 並選擇工具」>「建立 JUnit 測試

2.     選擇 JUnit 版本對話框中,選擇「JUnit 4.x」

選擇 JUnit 4.x 以後,IDE 將刪除 JUnit 3 庫。若是您的項目中有 JUnit 4 庫,那麼您能夠編寫和運行 JUnit 3 JUnit 4 測試。

3.     建立測試對話框中,將測試類的名稱修改成 VectorsJUnit4Test

更改測試類的名稱以後,您將看到一個關於修更名稱的警告。缺省名稱基於要測試的類名,並在該名稱後面附加單詞 Test。舉例來講,對於 MyClass.java 類,測試類的缺省名稱爲 MyClassTest.java。與 JUnit 3 不一樣,在 JUnit 4 中,測試不須要以單詞 Test 結尾。一般,最好是保留缺省名稱,但因爲在本教程中您將在相同的包中建立全部 JUnit 4 測試,所以測試類的名稱必須是唯一的。

4.     取消選中測試初始化函數測試釋放方法單擊肯定

單擊肯定以後,IDE 將在 sample 測試包目錄中建立一個 JUnit 測試框架。

項目須要一個目錄來保存測試包建立的測試。測試包目錄的缺省位置爲項目的根目錄,可是根據項目的類型不一樣,您能夠在項目的屬性對話框中爲目錄指定不一樣的位置。

在編輯器中查看 VectorsJUnit3Test.java,您能夠看到 IDE 生成了測試方法 testEqual testScalarMultiplication。在 JUnit 4 中,各測試方法都添加了 @Test 標註。IDE 根據 Vectors.java 中的方法的名稱爲測試方法生成了名稱,可是,不須要將 test 置於測試方法的名稱以前。各生成測試方法的缺省主體是做爲指導單獨提供的,所以須要將它們修改成實際的測試用例。

若是您不須要生成的方法主體,能夠在建立測試對話框中取消選中缺省方法主體

IDE 還生成了如下測試類初始化函數和釋放方法:

@BeforeClass

public static void setUpClass() throws Exception {

}

 

@AfterClass

public static void tearDownClass() throws Exception {

}

建立 JUnit 4 測試類時,IDE 會生成缺省的類初始化函數和釋放方法。標註 @BeforeClass @AfterClass 用於標記應在測試類以前及以後運行的方法。您能夠刪除這些方法,由於您在 Vectors.java 測試時不須要它們。

您能夠經過在選項窗口中配置「JUnit」選項來配置缺省生成的方法。

Vectors.java 編寫測試方法

在本練習中,您將修改生成的各測試方法:使用 JUnit assert 方法來測試方法,並更改測試方法的名稱。在 JUnit 4 中,您在命名測試方法時擁有了更好的靈活性,由於測試方法是由 @Test 標註指示的,而且不須要將單詞 test 置於測試方法以前。

1.     在編輯器中打開 VectorsJUnit4Test.java

2.     修改 testScalarMultiplication 的測試框架,方法是修改方法名稱、修改 println 的值並刪除生成的變量。如今,測試方法應以下所示(粗體爲更改部分):

3.  @Test

4.  public void ScalarMultiplicationCheck() {

5.      System.out.println("* VectorsJUnit4Test: ScalarMultiplicationCheck()");

6.      assertEquals(expResult, result);

}

在編寫測試時,不須要更改打印的輸出。在本練習中,其做用是可以更加輕鬆地識別輸出窗口中的測試結果。

7.     如今,添加一些斷言來測試方法。

8.  @Test

9.  public void ScalarMultiplicationCheck() {

10.    System.out.println("* VectorsJUnit4Test: ScalarMultiplicationCheck()");

11.    assertEquals(  0, Vectors.scalarMultiplication(new int[] { 0, 0}, new int[] { 0, 0}));

12.    assertEquals( 39, Vectors.scalarMultiplication(new int[] { 3, 4}, new int[] { 5, 6}));

13.    assertEquals(-39, Vectors.scalarMultiplication(new int[] {-3, 4}, new int[] { 5,-6}));

14.    assertEquals(  0, Vectors.scalarMultiplication(new int[] { 5, 9}, new int[] {-9, 5}));

15.    assertEquals(100, Vectors.scalarMultiplication(new int[] { 6, 8}, new int[] { 6, 8}));

}

在此測試方法中,您使用了 JUnit assertEquals 方法。要使用斷言,您須要提供輸入變量和預期的結果。在運行被測試的方法時,要經過測試,測試方法必須根據提供的變量成功返回全部預期的結果。您應該添加足夠數量的斷言來涵蓋各類可能的排列。

16.  testEqual 測試方法的名稱更改成 equalsCheck

17.  修改 equalsCheck 測試方法,刪除生成的方法主體並添加如下 println

System.out.println("* VectorsJUnit4Test: equalsCheck()");

如今,測試方法應以下所示:

@Test

public void equalsCheck() {

    System.out.println("* VectorsJUnit4Test: equalsCheck()");

}

18.  修改 equalsCheck 方法:添加如下斷言(顯示爲粗體)。

19.@Test

20.public void equalsCheck() {

21.    System.out.println("* VectorsJUnit4Test: equalsCheck()");

22.    assertTrue(Vectors.equal(new int[] {}, new int[] {}));

23.    assertTrue(Vectors.equal(new int[] {0}, new int[] {0}));

24.    assertTrue(Vectors.equal(new int[] {0, 0}, new int[] {0, 0}));

25.    assertTrue(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 0}));

26.    assertTrue(Vectors.equal(new int[] {5, 6, 7}, new int[] {5, 6, 7}));

27. 

28.    assertFalse(Vectors.equal(new int[] {}, new int[] {0}));

29.    assertFalse(Vectors.equal(new int[] {0}, new int[] {0, 0}));

30.    assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0, 0, 0}));

31.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0}));

32.    assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0}));

33.    assertFalse(Vectors.equal(new int[] {0}, new int[] {}));

34. 

35.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 1}));

36.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 1, 0}));

37.    assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {1, 0, 0}));

38.    assertFalse(Vectors.equal(new int[] {0, 0, 1}, new int[] {0, 0, 3}));

}

此方法使用 JUnit assertTrue assertFalse 方法來測試各類可能的結果。要經過此方法的測試,assertTrue 必須所有爲 true,而且 assertFalse 必須所有爲 false

比較: Vectors.java 編寫測試方法(JUnit 3

Utils.java 建立測試類

如今,您將爲Utils.java 建立 JUnit 測試方法。在上一練習中建立了測試類以後,IDE 會提示您選擇 JUnit 的版本。此次,IDE 並未提示您選擇版本,由於您已經選擇了 JUnit 版本,而且該版本中已經建立了全部後續 JUnit 測試。

若是您選擇 JUnit 4 做爲版本,那麼仍然能夠編寫和運行 JUnit 3 測試,可是 IDE 將使用 JUnit 4 模板來生成測試框架。

1.     右鍵單擊 Utils.java 並選擇工具」>「建立 JUnit 測試

2.     在對話框中,選中測試初始化函數測試釋放方法(若是爲未選中狀態)。

3.     建立測試對話框中,將測試類的名稱修改成 UtilsJUnit4Test。單擊肯定

單擊肯定以後,IDE 將在測試包」>「samples」目錄中建立測試文件UtilsJUnit4Test.java。能夠看到,IDE Utils.java 中的方法生成了 testComputeFactorialtestConcatWords testNormalizeWord 測試方法。IDE 還爲測試和測試類生成了初始化函數和釋放方法。

Utils.java 編寫測試方法

在本練習中,您將添加一些測試用例來演示一些經常使用的 JUnit 測試元素。您還將在方法中添加一個 println,由於一些方法不會在「JUnit 測試結果窗口中打印任何輸出,以表示方法已運行或經過測試。經過在方法中添加 println,您能夠了解方法是否已經運行以及它們運行的順序。

測試初始化函數和釋放方法

Utils.java 建立測試類以後,IDE 將生成標註初始化函數和釋放方法。您能夠爲方法選擇任何名稱,由於沒有既定的命名約定。

您不須要使用初始化函數和釋放方法來測試 Utils.java,可是本教程演示了它們的運行原理。

JUnit 4 中,您可使用標註來標記如下類型的初始化函數和釋放方法。

·         測試類初始化函數。@BeforeClass 標註將方法標記爲測試類初始化方法。測試類初始化方法只能運行一次,而且在測試類中的任何其餘方法以前運行。舉例來講,您沒必要在測試初始化函數中建立數據庫鏈接並在各測試方法以前建立新鏈接,您能夠在運行測試以前使用測試類初始化函數打開鏈接。而後,您可使用測試類釋放方法來關閉鏈接。

·         測試類釋放方法。@AfterClass 標註將方法標記爲測試類釋放方法。測試類釋放方法只能運行一次,而且在測試類中的任何其餘方法完成以後運行。

·         測試初始化函數。@BeforeClass 標註將方法標記爲測試初始化方法。測試初始化方法在測試類中的各測試用例以前運行。運行測試不須要測試初始化方法,可是,若是您須要在運行測試以前初始化一些變量,則可使用測試初始化方法。

·         測試釋放方法。@After 標註將方法標記爲測試釋放方法。測試釋放方法在測試類中的各測試用例以後運行。運行測試不須要測試釋放方法,可是,您可能須要使用釋放方法來清理運行測試用例時所需的任何數據。

執行如下更改(顯示爲粗體),在初始化函數和釋放方法中添加一個 println

@BeforeClass

public static void setUpClass() throws Exception {

    System.out.println("* UtilsJUnit4Test: @BeforeClass method");

}

 

@AfterClass

public static void tearDownClass() throws Exception {

    System.out.println("* UtilsJUnit4Test: @AfterClass method");

}

 

@Before

public void setUp() {

    System.out.println("* UtilsJUnit4Test: @Before method");

}

 

@After

public void tearDown() {

    System.out.println("* UtilsJUnit4Test: @After method");

}

比較:測試初始化函數和釋放方法(JUnit 3

運行測試類時,您添加的 println 文本將顯示在「JUnit 測試結果窗口的輸出窗格中。若是您沒有添加 println,則不會在輸出中顯示初始化函數和釋放方法已經運行。

在測試中使用簡單的斷言

這個簡單的測試用例將測試 concatWords 方法。您沒有使用生成的 testConcatWords 測試方法,而是使用新的 helloWorldCheck 測試方法,該方法使用單個簡單的斷言來測試方法是否正確地鏈接了字符串。測試用例中的 assertEquals 將使用 assertEquals(EXPECTED_RESULT, ACTUAL_RESULT) 語法來測試預期結果是否等於實際結果。在本例中,若是 concatWords 方法的輸入爲 "Hello"", ""world" "!",則預期結果應該等於 "Hello, world!"

1.     刪除生成的測試方法 testConcatWords

2.     添加如下 helloWorldCheck 方法來測試 Utils.concatWords

3.  public void testHelloWorld() {

4.      assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));

}

5.     添加一個 println 語句,用於在「JUnit 測試結果窗口中顯示關於測試的文本。

6.  @Test

7.  public void helloWorldCheck() {

8.      System.out.println("* UtilsJUnit4Test: test method 1 - helloWorldCheck()");

    assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));

比較:在測試中使用簡單的斷言(JUnit 3

在測試中使用超時

此測試演示如何檢查方法的完成是否花費了過長的時間。若是方法花費了過長的時間,則測試線程將中斷並致使測試失敗。您能夠在測試中指定時間限制。

測試方法將調用 Utils.java 中的 computeFactorial 方法。您能夠假定 computeFactorial 方法是正確的,可是在本例中,您但願測試計算是不是在 1000 毫秒以內完成的。其做用是在 1000 毫秒之好中斷測試線程。若是線程被中斷,則測試方法將拋出一個 TimeoutException

1.     刪除生成的測試方法 testComputeFactorial

2.     添加 testWithTimeout 方法,該方法用於計算隨機生成數的階乘。

3.  @Test

4.  public void testWithTimeout() {

5.      final int factorialOf = 1 + (int) (30000 * Math.random());

6.      System.out.println("computing " + factorialOf + '!');

7.      System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

}

8.     添加如下代碼(顯示爲粗體),用於設置超時並在方法執行時間過長時中斷線程。

9.  @Test(timeout=1000)

10.public void testWithTimeout() {

    final int factorialOf = 1 + (int) (30000 * Math.random());

能夠看到,超時被設置爲 1000 毫秒。

11.  添加如下 println(顯示爲粗體),用於在「JUnit 測試結果窗口中輸出關於測試的文本。

12.@Test(timeout=1000)

13.public void testWithTimeout() {

14.    System.out.println("* UtilsJUnit4Test: test method 2 - testWithTimeout()");

15.    final int factorialOf = 1 + (int) (30000 * Math.random());

16.    System.out.println("computing " + factorialOf + '!');

           

比較:在測試中使用超時(JUnit 3

針對預期異常的測試

此測試演示如何針對預期異常進行測試。若是未拋出指定的預期異常,則會致使方法失敗。在本例中,您將測試當輸入變量爲負數時(-5),computeFactorial 方法是否會拋出 IllegalArgumentException

1.     添加如下 testExpectedException 方法,它將以輸入 -5 調用 computeFactorial 方法。

2.  @Test

3.  public void checkExpectedException() {

4.      final int factorialOf = -5;

5.      System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

}

6.     @Test 標註中添加如下屬性(顯示爲粗體),指定測試應該拋出 IllegalArgumentException

7.  @Test(expected=IllegalArgumentException.class)

8.  public void checkExpectedException() {

9.      final int factorialOf = -5;

10.    System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

}

11.  添加如下 println(顯示爲粗體),用於在「JUnit 測試結果窗口中輸出關於測試的文本。

12.@Test (expected=IllegalArgumentException.class)

13.public void checkExpectedException() {

14.    System.out.println("* UtilsJUnit4Test: test method 3 - checkExpectedException()");

15.    final int factorialOf = -5;

16.    System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));

}

比較:針對預期異常的測試(JUnit 3

禁用測試

此測試演示如何臨時禁用測試方。在 JUnit 4 中,您只需經過添加 @Ignore 標註來禁用測試。

1.     刪除生成的測試方法 testNormalizeWord

2.     在測試類中添加如下測試方法:

3.  @Test

4.  public void temporarilyDisabledTest() throws Exception {

5.      System.out.println("* UtilsJUnit4Test: test method 4 - checkExpectedException()");

6.      assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));

}

測試方法 temporarilyDisabledTest 將在您運行測試類時運行。

7.     @Test 上方添加 @Ignore 標註(顯示爲粗體)來禁用測試。

8.  @Ignore

9.  @Test

10.public void temporarilyDisabledTest() throws Exception {

11.    System.out.println("* UtilsJUnit4Test: test method 4 - checkExpectedException()");

12.    assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));

}

13.  修復導入,以導入 org.junit.Ignore

比較:禁用測試(JUnit 3

如今,您已經編寫了測試。接下來,您能夠運行測試並在「JUnit 測試結果窗口中查看測試輸出。

運行測試

您能夠對整個應用程序或單獨的文件運行 JUnit 測試,並在 IDE 中查看結果。要運行項目的全部單元測試,最簡單的方法是從主菜單中選擇運行」>「測試 <PROJECT_NAME>。若是您選擇此方法,則 IDE 將運行測試包中的全部測試類。要運行單獨的測試類,右鍵單擊測試包節點下的測試類並選擇運行文件

1.     項目窗口中,右鍵單擊 UtilsJUnit4Test.java

2.     選擇測試文件

在運行 UtilsJUnit4Test.java 時,IDE 僅運行測試類中的測試。若是類經過了全部測試,那麼您將在「JUnit 測試結果窗口中看到與下圖類似的結果。

在該圖中(單擊圖像查看大圖),您能夠看到 IDE Utils.java 運行了 JUnit 測試,而且類經過了全部測試。左側窗格顯示各測試方法的結果,右側窗格顯示測試輸出。若是您查看輸出,您能夠看到測試運行的順序。您向每一個測試方法添加的 println 已將測試的名稱輸出到測試結果窗口和輸出窗口中。

UtilsJUnit4Test 中能夠看到,使用 @BeforeClass 進行標註的測試類初始化方法運行於任何其餘方法以前,而且只運行一次。使用 @AfterClass 進行標註的測試類初始化方法在類中的全部其餘方法以後運行。使用 @Before 進行標註的測試初始化方法在各測試方法以前運行。

使用測試結果窗口左側的控件,能夠方便地再次運行測試。您可使用過濾器在顯示全部測試結果和僅顯示失敗的測試之間進行切換。使用相應的箭頭,能夠跳至下一個或上一個失敗的測試。

測試結果窗口中右鍵單擊某個測試結果時,將會出現一個彈出式菜單,您能夠選擇轉至測試的源、再次運行測試或調試測試。

建立單元測試以後的下一步是建立測試套件。請參見建立 JUnit 4 測試套件,瞭解如何以組的方式運行特定的測試,從而避免單獨運行各個測試。

建立測試套件

爲項目建立測試以後,您最後將獲得許多測試類。雖然您能夠單獨運行測試類,也能夠運行項目中的全部測試,但在許多狀況下,您但願運行測試的子集或按特定的順序運行測試。您能夠經過建立一個或多個測試套件來實現此目的。舉例來講,您能夠建立測試套件來測試代碼的具體方面或具體的條件。

從根本上講,測試套件是一個類,其中包含對指定測試用例(例如,特定測試類、測試類中的測試方法以及其餘測試套件)進行調用的方法。測試套件能夠做爲測試類的一部分包括在其中,但最佳實踐建議單首創建測試套件類。

您能夠手動爲項目建立 JUnit 3 JUnit 4 測試套件,也能夠經過 IDE 來生成套件。使用 IDE 生成測試套件以後,缺省狀況下,IDE 將生成代碼來調用與測試套件相同的包中的全部測試類。建立測試套件以後,您能夠對類進行修改,指定但願做爲該套件一部分運行的測試。

建立 JUnit 3 測試套件

若是您選擇 JUnit 3 做爲測試的版本,則 IDE 能夠根據測試包中的測試類來生成 JUnit 3 測試套件。在 JUnit 3 中,您能夠指定要包含在測試套件中的測試類,方法是建立一個 TestSuite 實例並調用各測試的 addTest 方法。

1.     項目窗口中右鍵單擊項目節點,而後選擇新建」>「其餘以打開新建文件嚮導。

2.     選擇「JUnit」類別和測試套件。單擊下一步

3.     鍵入 JUnit3TestSuite 做爲文件名稱。

4.     選擇 sample 包,在測試包文件夾的 sample 文件夾中建立測試套件。

5.     取消選中測試初始化函數測試釋放方法單擊完成

單擊完成後, IDE 將在 sample 包中建立測試套件類,並在編輯器中打開類。若是 sample 包包含測試類 VectorsJUnit3Test.java UtilsJUnit3Test.java,則測試套件將包含如下代碼。

public JUnit3TestSuite(String testName) {

    super(testName);

}           

 

public static Test suite() {

    TestSuite suite = new TestSuite("JUnit3TestSuite");

    suite.addTest(new TestSuite(sample.VectorsJUnit3Test.class));

    suite.addTest(new TestSuite(sample.UtilsJUnit3Test.class));

    return suite;

}

建立 JUnit 4 測試套件

若是您選擇 JUnit 4 做爲測試的版本,則 IDE 能夠生成 JUnit 4 測試套件。JUnit 4 是向後兼容的,所以您能夠運行包含 JUnit 4 JUnit 3 測試的 JUnit 4 測試套件。在 JUnit 4 測試套件中,您能夠以 @Suite 標註的值的形式指定要包括的測試類。

要讓 JUnit 3 做爲 JUnit 4 的一部分來運行,須要 JUnit 4.4 或更高版本。

1.     項目窗口中右鍵單擊項目節點,而後選擇新建」>「其餘以打開新建文件嚮導。

2.     選擇「JUnit」類別和測試套件。單擊下一步

3.     鍵入 JUnit4TestSuite 做爲文件名稱。

4.     選擇 sample 包,在測試包文件夾的 sample 文件夾中建立測試套件。

5.     取消選中測試初始化函數測試釋放方法單擊完成

單擊完成後, IDE 將在 sample 包中建立測試套件類,並在編輯器中打開類。測試套件包含如下代碼。

@RunWith(Suite.class)

@Suite.SuiteClasses(value={UtilsJUnit4Test.class, VectorsJUnit4Test.class})

public class JUnit4TestSuite {

}

運行測試套件時,IDE 將按照測試類 UtilsJUnit4Test VectorsJUnit4Test 的列出順序來運行它們。

運行測試套件

運行測試套件與運行任何單獨測試類的方法相同。

1.     項目窗口中展開測試包節點。

2.     右鍵單擊測試套件類,而後選擇測試文件

運行測試套件以後,IDE 將按照套件中的測試的列出順序來運行它們。JUnit 測試結果顯示在「JUnit 測試結果窗口中。

在該圖中(單擊圖像查看大圖),您能夠看到 JUnit 3 測試套件的測試結果。測試套件將以單獨測試的形式來運行 UtilsJUnit3Test VectorsJUnit3Test 測試類,並在左側窗格中顯示各測試的結果。單獨運行測試時,右側窗格中的輸出與左側相同。

在該圖中(單擊圖像查看大圖),您能夠看到 JUnit 4 測試套件的測試結果。測試套件將以單獨測試的形式來運行 UtilsJUnit4Test VectorsJUnit4Test 測試類,並在左側窗格中顯示各測試的結果。單獨運行測試時,右側窗格中的輸出與左側相同。

在該圖中(單擊圖像查看大圖),您能夠看到混合測試套件的測試結果。該測試套件包括 JUnit 4 測試套件和一個 JUnit 3 測試類。測試套件將以單獨測試的形式來運行 UtilsJUnit3Test.java JUnit4TestSuite.java 測試類,並在左側窗格中顯示各測試的結果。單獨運行測試時,右側窗格中的輸出與左側相同。

小結

本教程是在 NetBeans IDE 中建立 JUnit 單元測試和測試套件的基本介紹。IDE 支持 JUnit 3 JUnit 4;本文檔介紹了 JUnit 4 中引入的一些更改,這些更改可簡化測試的建立和運行過程。

如本教程中所述,JUnit 4 的主要改進之一就是提供了對標註的支持。在 JUnit 4 中,您如今能夠將標註用於如下用途:

·         使用 @Test 標註標識測試,而不使用命名約定

·         使用 @Before @After 標註標識 setUp tearDown 方法

·         標識適用於整個測試類的 setUp tearDown 方法。帶有 @BeforeClass 標註的方法僅在類中的全部測試方法運行以前運行一次。一樣,帶有 @AfterClass 標註的方法僅在全部測試方法運行完以後運行一次。 標識預期的異常 使用 @Ignore 標註標識應跳過的測試

·         爲測試指定超時參數

一般,測試代碼能幫助確保對代碼中所作的小更改不會中斷應用程序。JUnit 等自動化測試工具簡化了測試的流程,而且常常性的測試能幫助及時捕獲代碼錯誤。

相關文章
相關標籤/搜索