2011-01-21 54 views
2

我有一個「最佳實踐」問題。我正在爲某種方法編寫測試,但有多個輸入值。我應該爲每個輸入值編寫一個測試,還是應該更改entryValues變量值,並調用.assert()方法(針對所有可能的值範圍進行)?單元測試寫作的最佳做​​法

謝謝你的幫助。 最好的問候,

佩德羅Magueija

編輯:我使用的.NET。 Visual Studio 2010與VB。

回答

2

對每個輸入/輸出集合進行單獨的單元測試,覆蓋您嘗試測試的方法的全部可能值(或至少對於您希望單元測試的那些輸入/輸出集合)更好。

5

如果有人不得不編寫許多僅在初始輸入和最終輸出方面不同的測試,則應使用數據驅動測試。這允許您一次性定義測試以及輸入和輸出之間的映射。單元測試框架然後將其解釋爲每個案例的一個測試。如何真正做到這一點取決於你正在使用的框架。

+0

數據驅動(參數化)測試理論上聽起來不錯,但恕我直言,他們使測試案例難以理解和維護。爲每個案例分別使用描述性名稱進行測試有助於我更好地理解用例。公平的,這意味着一些重複的代碼,但重構可以最小化到可負擔的水平。 – 2011-01-23 13:46:17

+0

@Peter - 參數化測試還包含一個Description和一個Name屬性以提高可讀性 - 至少在NUnit中。我使用數據驅動的測試,單元測試中的所有步驟都是恆定的,只有輸入 - 輸出發生變化。 – Gishu 2011-02-07 09:36:27

0

你在說這個區別嗎?

- (void) testSomething 
{ 
    [foo callBarWithValue:x]; 
    assert… 
} 

- (void) testSomething2 
{ 
    [foo callBarWithValue:y]; 
    assert… 
} 

- (void) testSomething 
{ 
    [foo callBarWithValue:x]; 
    assert… 
    [foo callBarWithValue:y]; 
    assert… 
} 

第一個版本是在更好的測試失敗時,你就會有更好的主意,什麼行不通。第二個版本顯然更方便。有時我甚至會將測試值填入集合以節省工作。我通常會選擇第一種方法,因爲我可能要單獨調試這一個案例。當然,當測試值真的屬於一起並形成一個連貫的單元時,我只選擇後者。

0

你真的有兩個選擇,你沒有提到你正在使用哪種測試框架或語言,因此可能不適用。

1)如果你的測試框架支持它,使用RowTest,MBUnit和Nunit支持這個,如果你使用.NET,這將允許你在你的方法中放置多個屬性,並且每行將作爲單獨的測試執行

2)如果不按每個條件編寫一個測試,並確保給它一個有意義的名稱,以便如果(當)測試失敗時,您可以輕鬆找到問題,這對您來說意味着什麼。

編輯 其所謂的TestCase在NUnit的Nunit TestCase Explination

1
  1. 較小的測試更易於閱讀。
  2. 該名稱是測試文檔的一部分。
  3. 單獨的方法可以更準確地指出失敗的原因。

所以,如果你有一個像一個方法:

void testAll() { 
    // setup1 
    assert() 
    // setup2 
    assert() 
    // setup3 
    assert() 
} 

在我的經驗,這會非常大非常快,所以變得難以閱讀和理解,所以我會做:

void testDivideByZero() { 
    // setup 
    assert() 
} 

void testUnderflow() { 
    // setup 
    assert() 
} 


void testOverflow() { 
    // setup 
    assert() 
} 
1

我應該寫一個測試爲每個條目 值或者我應該改變 entryValues變量的值,並調用 ŧ他.assert()方法(這樣做的所有 範圍的可能值)?

如果您有一個代碼路徑,通常不會測試所有可能的輸入。你通常要測試的是「有趣」的輸入,這些輸入將成爲您將獲得的數據的良好範例。

例如,如果我有一個函數

define add_one(num) { 
    return num+1; 
} 

我不能寫一個測試所有可能的值,所以我可以用MAX_NEGATIVE_INT,-1,0,1,MAX_POSITIVE_INT作爲我的測試集,因爲它們是我可能會獲得有趣價值的好代表。

每個代碼路徑至少應有一個輸入。如果你有一個函數,每個值都對應一個唯一的代碼路徑,那麼我會考慮爲可能值的完整範圍寫一個測試。這個例子就是一個命令解析器。

define execute(directive) { 
    if (directive == 'quit') { exit; } 
    elsif (directive == 'help') { print help; } 
    elsif (directive == 'connect') { intialize_connection(); } 
    else { warn("unknown directive"); } 
} 

爲了清楚起見,我使用了elifs而不是調度表。我認爲這很清楚,每個獨特的價值都有不同的行爲,因此您需要測試每種可能的價值。

相關問題