2013-09-10 34 views
2

以tdd方式實現時,您是否聲明瞭類的內部或僅關於其公共api?TDD。斷言班級的內部是否正確?

可以說我正在實現一個二進制堆。添加一個對象後,我想斷言堆proerty被保留。 你是否有意義通過反思獲得內部數組,然後斷言其內容? 即

@Test 
    public void shouldPreserveHeapProperty() { 
     // when 
     heap.push(3); 
     heap.push(2); 
     heap.push(1); 

     // then 
     assertThat(Reflection.get(heap,"elements"))).contains(3,2,1);//made up Reflection class 
    } 

也許它的公共API?但它需要每個測試 多個斷言即

@Test 
    public void shouldPreserveHeapProperty() { 
     // when 
     heap.push(3); 
     heap.push(2); 
     heap.push(1); 

     // then 
     assertThat(heap.pop()).isEqualTo(3); 
     assertThat(heap.pop()).isEqualTo(2); 
     assertThat(heap.pop()).isEqualTo(1); 
    } 

什麼是更多,你將如何實施並行代碼的測試?有時,如果不訪問內部鎖,模擬死鎖或等待真的很困難。

+0

使'elements'包私有,所以你不需要反射來測試它。 – ZhongYu

回答

1

我認爲你應該只使用API​​。也就是說,您可以使用包私有訪問來爲您的測試代碼和友好的類提供有限訪問權限,以避免某些應該公開的項目。

要做到這一點,你會發現要測試你的mutator方法,你還需要一些getter方法來訪問對象的重要屬性。對於一個堆棧,你可能只需要push和pop mutators,但是對於測試來說,獲得一個大小的getter可能是有用的。

我發現這樣限制自己自然會導致通過契約方式編程,這是一件好事。

當您想重構班級時,訪問私人數據的測試很麻煩。你應該能夠很容易地改變你的私人信息,但是你必須改變你的測試代碼。

您的示例測試嘗試檢查該類是否保留堆屬性。這不是一個測試可以檢查的事情。 heap屬性是對所有push和pop序列的約束。嘗試使用一個按鈕,然後一個彈出,然後再按兩個按鈕,然後兩個彈出,來完成一個測試用例。通過歸納,他們一起作爲一個可憐的證明人證明你的班級對所有序列都是正確的。

每個測試只應包含一個斷言的想法很常見,但不必要而且麻煩。當你重構代碼,並且存在引入錯誤的危險時,你希望最大化檢測這些錯誤的機會。所以你應該檢查你正在測試的mutatir的所有後置條件以及所有的類的不變量。這可能是非常多的斷言,因此每個測試用例的多重斷言是唯一實用的方法。

+0

斷言兩個彈出窗口產生正確的兩個數字在技術上可能是兩個斷言,但邏輯上只有一個斷言。這就是「每次測試的一個斷言」。 – EricSchaefer