2010-04-24 90 views
1

我是單元測試新手,因此想做一些實踐練習來熟悉jUnit框架。正確定義jUnit測試用例

我創建了一個程序,它實現一個字符串乘法器

public String multiply(String number1, String number2) 

爲了測試乘法器方法,我創建了一個測試套件包含以下測試例(與所有需要的整數解析等)

public class MultiplierTest { 
    @Test 
    public void testMultiply() { 
     Multiplier multiplier = new Multiplier(); 
     // Test for 2 positive integers 
     assertEquals("Result", 5, multiplier.multiply("5", "1")); 

     // Test for 1 positive integer and 0 
     assertEquals("Result", 0, multiplier.multiply("5", "0")); 

     // Test for 1 positive and 1 negative integer 
     assertEquals("Result", -1, multiplier.multiply("-1", "1")); 

     // Test for 2 negative integers 
     assertEquals("Result", 10, multiplier.multiply("-5", "-2")); 

     // Test for 1 positive integer and 1 non number 
     assertEquals("Result", , multiplier.multiply("x", "1")); 

     // Test for 1 positive integer and 1 empty field 
     assertEquals("Result", , multiplier.multiply("5", "")); 

     // Test for 2 empty fields 
     assertEquals("Result", , multiplier.multiply("", "")); 
    } 
} 

以類似的方式,我可以創建涉及邊界情況(考慮數字是int值)或甚至虛數值的測試用例。

1)但是,以上最後3個測試用例的期望值應該是多少? (一個特殊的數字表示錯誤?)

2)我錯過了哪些額外的測試案例?

3)是測試乘數法的assertEquals()方法不夠還是需要其他的方法,如assertTrue(),assertFalse(),assertSame()等

4)這是正確的方式去開發測試用例?我如何「完全」從這個練習中受益?

5)什麼應該是測試乘法器方法的理想方法?

我在這裏很無能。如果任何人都可以幫助回答這些問題,我將不勝感激。謝謝。

+0

只是一件小事 - 所有的測試都有「結果」作爲字符串。該字符串應該是信息性的 - 例如,在第一個字符串中,您可能會說「5 * 1!= 5」。 – 2010-04-24 02:17:50

+0

這是5個問題,而不是1個, – Raedwald 2016-08-22 07:17:47

回答

3

1)但是,上面最後3個測試用例的期望值應該是多少? (一個特殊的數字表示錯誤?)

正如其他答覆者所解釋的,它取決於乘數的接口合約。您應該考慮您(或其客戶,一般情況下)應該如何使用它,在發生特定錯誤或極端情況時應該如何處理等。在Java中,慣例是在這種情況下拋出異常。

2)我錯過了哪些額外的測試用例?

這,我想起一對夫婦的情況:

// test commutativity 
assertEquals("0", multiplier.multiply("0", "5")); 
assertEquals("-1", multiplier.multiply("1", "-1")); 
assertEquals("149645", multiplier.multiply("173", "865")); 
assertEquals("149645", multiplier.multiply("865", "173")); 

// test some more unusual cases of multiplying with 0 
assertEquals("0", multiplier.multiply("-5", "0")); 
assertEquals("0", multiplier.multiply("0", "-0")); 
// test with numbers starting with '+' 
assertEquals("368", multiplier.multiply("+23", "+16")); 
assertEquals("-368", multiplier.multiply("-23", "+16")); 

// test multiplying huge values without overflow 
assertEquals("18446744073709551616", multiplier.multiply("4294967296", "4294967296")); 
assertEquals("18446744073709551616", multiplier.multiply("-4294967296", "-4294967296")); 

3)是測試乘數法的assertEquals()方法不夠還是需要其他的方法,如assertTrue(),assertFalse (),assertSame()等

在這種情況下,所有你需要的是比較兩個值的相等性。在其他測試中,您可能需要不同種類的斷言。

4)這是開發測試用例的正確方法嗎?我如何「完全」從這個練習中受益?

單元測試沒有單一的「正確」方法。最接近的可能是test driven development,如果你從頭開始編寫代碼,這是許多人(包括我自己)推薦的。

您從這個練習中受益很可能是您熟悉JUnit並嘗試了一段時間的「測試者帽子」。

5)什麼應該是測試乘法器方法的理想方法?

這個問題與上一個問題有什麼不同?

+0

謝謝你的指點。現在有道理。 – Epitaph 2010-04-25 02:04:42

+0

對於類似的測試用例,我可以有一個包含多個assertEquals()的方法嗎?例如,對於包含字符,特殊符號,字符串,空字符串等非法輸入的測試用例,有1個方法testArgumentMultiply()。因爲所有這些輸入都會導致相同的NumberFormatException? – Epitaph 2010-04-25 23:46:42

+0

@Epitaph,純粹主義者堅持認爲人們應該在任何測試方法中只測試一件事情。我不那麼挑剔。我努力在測試方法中測試單個連貫的用例,包括可能的幾個斷言。但是,在您的具體情況中,請注意,當調用的方法拋出異常時,調用測試方法的執行將在此處終止,因此不會執行進一步的調用。換句話說,你必須把你的每個異常測試都放到它自己獨立的測試方法中。 – 2010-04-26 07:54:26

4

首先,你的代碼有錯,因爲你有一個類,但沒有功能。我假設所有這些測試都在一個功能?如果是這樣,我會建議反對它。一般來說,你想一個測試,測試一個東西,所以:

public class MultiplierTests { 
    @Test 
    public void testSimpleMultiple() { 
    assertEquals(...); 
    } 

    ... 
} 

其次,你傳遞一個int結果在這裏:

assertEquals("Result", 5, multiplier.multiply("5", "1")); 

Multiplier.multiply()返回String

那麼你如何測試這取決於結果是什麼。如果傳入一個空字符串,它會拋出異常嗎?如果是這樣,你可以定義你的@Test註釋說,它預計的異常被拋出:

@Test(expected = IllegalArgumentException.class) 
public void test() { 
    multiplier.multiply("", "5"); 
} 
+0

在您的IllegalArgumentException示例中,如果我使用帶3個參數的assertEquals()方法,則期望值的字段應該包含如下內容 @Test(expected = NumberFormatException.class) public void testMultiply()assertEquals(「4 * a」,?,tester.multiply(「3」,「a」); } – Epitaph 2010-04-25 22:45:20

+0

@Epitaph在'IllegalArgumentException'示例中,不要使用'assertEquals()調用方法,如果沒有異常,測試將失敗。如果拋出了除IllegalArgumentException之外的異常,則測試將失敗。只有在引發'IllegalArgumentException'時纔會通過。 – cletus 2010-04-25 23:05:48

+0

謝謝。我試着爲期望的值放入「新的NumberFormatException()」,它工作。那也好嗎? – Epitaph 2010-04-25 23:29:14

2

你應該考慮增加測試用例來驗證你的異常工作正常使用@Expected註解。基本上,寫一個你知道應該產生一個異常,然後看到測試通過的情況。

確定您是否錯過複雜方法中的任何情況的好方法是通過代碼覆蓋工具來運行它們。運行所有測試,然後查看代碼覆蓋率結果。如果您的代碼中有部分代碼未被您的測試用例訪問,您可能會錯過一些代碼。

你可以找到一個很好的指導here

+0

你能推薦一些代碼覆蓋工具嗎? – Carl 2010-04-24 04:21:46

+0

這裏有一個很好的列表:http://java-source.net/open-source/code-coverage。 我建議你嘗試http://codecover.org/ 我個人使用Atlassian的Clover,但這不是免費的工具。 – Prachi 2010-04-24 17:32:25

1

如果你真的測試的邊界條件,以及你期待的數字字符串表示,或許你可以測試字符串傳遞給函數方法測試

@Test(expected= NumberFormatException.class) 
public void test() { 
    multiplier.multiply("a", "b"); 
} 

我克萊圖斯不同意他的執行,因爲他測試用例需要包含所有IllegalArgumentException,我認爲測試特定的子類比使用父例外更好。

+0

我相信'IllegalArgumentException'應該只是一個例子。 – 2010-04-24 22:36:15

+0

我承認這一點,但事實是,期望一個家長的異常可以讓你趕上很多其他意想不到的例外。 – Kartik 2010-04-26 18:02:01