2009-10-28 87 views
4

我們是否應該在編寫單元測試的時候着眼於DRY,因爲功能的變化會影響儘可能少的代碼,我們的可預測性,即代碼的操作是微不足道的。基本上我問的是在創建非常一般的幫助程序方法和多個單元測試可以使用的幫助程序方法之間的權衡,而不是將測試代碼限制在單個單元測試中。作爲一個實例採取工廠,具有以下方法簽名的情況下:單元測試:干與可預測性

public Node buildNode(String path, String name, Map<String, Object> attributes); 

根據參數提供所得節點對象將是不同的,因此,我們需要測試的不同的可能性。如果我們的目標是可預見性在第一個例子給我們可能會寫兩個獨立的單元測試,但如果我們的目標是幹我們寧願加一個共同的輔助方法,如第二個例子:

EXAMPLE1: 
@Test 
public void testBuildBasicNode() { 
    Node node = testee.buildNode("/home/user", "Node", null); 
    assertEquals("/home/user/Node", node.getAbsolutePath()); 
    assertEquals(false, node.isFolder()); 
} 

@Test 
public void testBuildAdvancedNode() { 
    Map<String, Object> attributes = new HashMap<String, Object>(); 
    attributes.put("type", NodeType.FOLDER); 
    Node node = testee.buildNode("/home/user", "Node", attributes); 
    assertEquals("/home/user/Node", node.getAbsolutePath()); 
    assertEquals(true, node.isFolder()); 
} 

EXAMPLE2: 
@Test 
public void testBuildBasicNode() { 
    Node node = testee.buildNode("/home/user", "Node", null); 
    Node comparisonNode = buildComparisonNode("/home/user", "Node", null); 
    assertEquals(comparisonNode, node); 
} 

@Test 
public void testBuildAdvancedNode() { 
    Map<String, Object> attributes = new HashMap<String, Object>(); 
    attributes.put("type", NodeType.FOLDER); 
    Node node = testee.buildNode("/home/user", "Node", attributes); 
    Node comparisonNode = buildComparisonNode("/home/user", "Node", attributes); 
    assertEquals(comparisonNode, node); 
} 

private Node buildComparisonNode(String path, String name, Map<String, Object> attributes) { 
    // Not just a duplicate of the buildNode method, 
    // can be more trivial if we only limit it to unit tests that share some common attributes 
    ... 
} 

我對第一個例子(可預測性)的問題是,如果任何功能改變(比如說說如何格式化AbsolutePath),它需要在所有單元測試中進行更改。我對第二個例子的問題是,buildComparisonNode感覺像是應該測試的東西,我當然不想開始編寫測試測試。

另外,作爲一個結束思想,您是否會聲明在示例單元測試中使用的字面值字符串的最終變量,還是它們很好?

+0

一個單位案例=一個測試。我沒有看到DRY =) – mauris 2009-10-28 06:05:17

回答

8
  1. 好問題。我之前聽說過「單元測試可能潮溼,但不能溼透...」。爲了保持測試的可維護性,重點(或可預測性)是關鍵。你的團隊越大,我認爲你應該對此越重要。另一件需要考慮的事情是,如果有特定的測試助手代碼,它本身可以成爲一個API,所以如果每個人都知道如何使用它,這可能不是一個壞主意。我的經驗法則是,如果我可以在自動重構中使用IDE來完成重複操作,那麼我將刪除重複項,並且可以給它一個好名字。

  2. 一個建議...看看Nat Pryce的Test Data Builder模式寫作關於更可維護/可擴展的方法。

+0

謝謝,那個測試數據生成器模式很巧妙! – Zecrates 2009-10-28 08:28:59

+0

+1:不要着迷於DRY單元測試,這會破壞目的。測試必須超級清晰(值得信賴),而且不一定要高效。任何體面的單元測試庫都允許繼承,所以你可以很容易地將一些通用代碼放在超類中。 – 2009-10-28 15:39:48

4

儘管DRY適用於生產代碼,但它並不總是適用於單元測試。你真的希望每個測試都相互獨立,這通常意味着重複自己。另一方面,我發現將某些事情分組到所有測試使用的助手方法中是很有用的,只要它不將測試耦合在一起,那麼它應該沒問題。我通常減少重複的一個地方是使用測試數據構建器來構建我測試中存在於特定狀態中的對象。

我的經驗法則是保持我的測試儘可能小而且可讀。如果使用DRY可以幫助實現,那麼我使用它。如果不是,那麼我不會。 :-)

希望有所幫助。我不是單元測試方面的世界專家,所以我可能會很錯。 :-)

0

另一件事想 - 通常,當你在測試中刪除重複它告訴你,什麼是產品代碼或設計正在等待一個合法的理由(在生產代碼庫使用)將其移動到生產代碼。我記不起我從哪裏得到那個啊......但是我認爲這與TDD as if you mean it有關。