2010-06-08 112 views
14

所以我已經開始佈局單元測試下面的代碼位:單元測試架構問題

public interface MyInterface { 
    void MyInterfaceMethod1(); 
    void MyInterfaceMethod2(); 
} 

public class MyImplementation1 implements MyInterface { 
    void MyInterfaceMethod1() { 
    // do something 
    } 

    void MyInterfaceMethod2() { 
    // do something else 
    } 

    void SubRoutineP() { 
    // other functionality specific to this implementation 
    } 
} 

public class MyImplementation2 implements MyInterface { 
    void MyInterfaceMethod1() { 
    // do a 3rd thing 
    } 

    void MyInterfaceMethod2() { 
    // do something completely different 
    } 

    void SubRoutineQ() { 
    // other functionality specific to this implementation 
    } 
} 

幾個實現和更多的期望來。

我最初的想法是給自己節省時間重新編寫單元測試是這樣的:

public abstract class MyInterfaceTester { 
    protected MyInterface m_object; 

    @Setup 
    public void setUp() { 
    m_object = getTestedImplementation(); 
    } 

    public abstract MyInterface getTestedImplementation(); 

    @Test 
    public void testMyInterfaceMethod1() { 
    // use m_object to run tests 
    } 

    @Test 
    public void testMyInterfaceMethod2() { 
    // use m_object to run tests 
    } 
} 

,我可以再子類容易測試實現像其他具體方法,使:

public class MyImplementation1Tester extends MyInterfaceTester { 
    public MyInterface getTestedImplementation() { 
    return new MyImplementation1(); 
    } 

    @Test 
    public void testSubRoutineP() { 
    // use m_object to run tests 
    } 
} 

並且同樣適用於實施2。

所以我的問題確實是:有什麼理由不這樣做? JUnit似乎很喜歡它,它滿足了我的需求,但在我閱讀過的任何單元測試書籍和示例中,我沒有真正看到過類似的東西。

有沒有一些我不知不覺中違反的最佳做法?我是否爲自己的心痛定下了自己的路?有沒有更好的方式,我沒有考慮過?

感謝您的任何幫助。

回答

17

有沒有什麼理由不這樣做?

不需要。測試是正是這個原因。

我在任何單元測試書籍和例子中都沒有看到過類似的東西。

繼續閱讀。介紹不包括這一點。

有沒有我不知不覺中違反的一些最佳做法?

上午我設置自己彌補心痛的道路?

一些人感到緊張 「脆測試」 號。您可以在這裏找到一些問題,尋找方法,以便對軟件進行更改並不會導致更改測試。從長遠來看,試圖創建「健壯」測試是愚蠢的。您需要編寫測試,以便對軟件的可見界面級別進行的每個小改動均需要測試重寫。

您想測試,以便不可見的內部更改不需要測試重寫。

類和子類的使用與這些考慮事項是正交的。

在那裏我有沒有考慮過更好的方法嗎?

編號面向對象的一點。正是由於這個原因,測試是一個類。

5

雖然我支持SLott 100%我也會考慮JUnit的參數化測試,而不是測試類層次結構如下:

@RunWith(Parameterized.class) 
public class MyInterfaceTester { 
    private MyInterface m_object; 

    public void MyInterfaceTester(MyInterface object) { 
    m_object = object; 
    } 

    @Parameters 
    public static Collection<Object[]> data() { 
    List<Object[]> list = new ArrayList<Object[]>(); 

    list.add(new Object[]{new MyImplementation1()}); 
    list.add(new Object[]{new MyImplementation2()}); 

    return list; 
    } 

    @Test 
    public void testMyInterfaceMethod1() { 
    // use m_object to run tests 
    } 

    @Test 
    public void testMyInterfaceMethod2() { 
    // use m_object to run tests 
    } 
} 

測試類層次結構無需:剛剛在data添加另一個列表元素添加新的實現方法。

+0

不知道這個功能,感謝分享。更多信息,以及一個工作示例:http://www.devx.com/Java/Article/31983/0/page/3其他感興趣的人。 – 2010-06-09 02:01:10

1

如果你真的在每個測試課上做了相同的設置和拆卸,那麼你在做什麼很好,但我發現在實踐中這幾乎從來不是這樣。實際上,大多數情況下,如果你有一個實例化測試數據的設置方法,那麼你甚至都不想要。相反,在一個測試類中,您可以設置任何基礎結構,並且每個測試方法都會設置它自己的對象實例來測試它的某個方面。

+0

當然,將getTestedImplementation()調用移動到每個測試的第一行,並將結果放入本地可能是我想要的。從新物體開始可能更安全。但是現在,實現類中沒有狀態,所以只需要創建一次。 – 2010-06-09 02:03:13