2016-08-19 69 views
10

如果狀態爲SP,則可以刪除Sample。我有這個測試:我應該測試預計不會發生任何事件的情況:

@Test 
public void canBeDeletedWhenStatusIsP() { 
    Sample sample = new Sample(); 
    sample.setState("P"); 
    assertTrue(sample.canBeDeleted()); 
} 

@Test 
public void canBeDeletedWhenStatusIsS() { 
    Sample sample = new Sample(); 
    sample.setState("S"); 
    assertTrue(sample.canBeDeleted()); 
} 

我應該走得更遠嗎? 不能被刪除時應該如何測試?例如:

@Test 
public void cantBeDeletedWhenStatusINeitherPNorS() { 
    Sample sample = new Sample(); 
    sample.setState("Z"); 
    assertFalse(sample.canBeDeleted()); 
} 

這是測試有用嗎?測試命名如何?這個邏輯會被測試嗎?

回答

13

SaintThread給你一個很好的「直接」答案。

但讓我們退後一步。因爲你在生產代碼中做錯了什麼。最有可能的是,您的生產代碼在該字符串上做了一些類似於開關的操作,表示示例狀態。不僅僅是一次,而且還包括它提供的所有方法。而且...這不是一個好的面向對象的設計!

相反,你應該使用多態,如:

abstract class Sample { 
    boolean canBeDeleted(); 
// ... probably other methods as well 

與和各種具體子類,像

class ZSample extends Sample { 
    @Override canBeDeleted() { return false; } 
// ... 

最後,你有

class SampleFactory { 
    Sample createSampleFrom(String stateIdentifier) { 
    // here you might switch over that string and return a corresponding object, for example of class ZSample 

然後,你的測試歸結爲:

  1. 測試工廠;例如輸入「Z」,它返回ZSample的一個實例
  2. 測試Sample的所有子類;例如,對於ZSample的一個實例,canBeDeleted()返回false

問題是:您的代碼確實執行FSM(有限狀態機)的工作。那麼不要使用if/else遍佈整個地方;相反,做OO的事情:創建一個顯式的狀態機。而且,免費獎金:這種方法也可以將你的Sample對象變爲不變的;這通常比不得不處理隨時間改變狀態的對象更好(因爲例如不變性對多線程問題有很大幫助)。免責聲明:如果你的「樣本」類只是關於那一種方法,也許上述是矯枉過正。但在任何其他情況下......可能會退後一步,看看我的建議是否會爲您的設計增添價值!

+0

謝謝。完美的解釋。 –

+1

不客氣。有趣的事情;我有史以來第一次在兩個答案中得到+10分......同一天。太糟糕了,大多數聲譽......對我來說都有點失落。但仍然 - 很高興我能幫忙! – GhostCat

2

在我看來,你應該測試:

cantBeDeletedWithoutStatus

assertFalse(sample.canBeDeleted()); 

cantBeDeletedWhenStatusIsInvalid

sample.setState("Z"); 
assertFalse(sample.canBeDeleted()); 

cantBeDeletedWhenStatusIsToggledToInvalid

sample.setState("P"); 
sample.setState("Z"); 
assertFalse(sample.canBeDeleted()); 

canBeDeletedWhenStatusIsToggledToS

sample.setState("Z"); 
sample.setState("S"); 
assertFalse(sample.canBeDeleted()); 

canBeDeletedWhenStatusIsToggledToP

sample.setState("Z"); 
sample.setState("P"); 
assertFalse(sample.canBeDeleted()); 

讓我知道你的想法在評論

+0

謝謝。這有幫助:) –

1

我們應該希望我們的測試是徹底的,因此他們可能會檢測到許多類的錯誤。所以簡單的答案是肯定的,測試無操作的情況。

你不會告訴狀態可能的值。讓我們假設他們必須是大寫英文字母,給26個州。你的問題與「我應該有26個測試用例」基本相同。這是很多,但不是很多禁止。現在想象一個更復雜的情況,對於這種情況,狀態是一個int,所有的int值都是可能的。全面測試它們將是不切實際的。該怎麼辦?

處理測試時有很多輸入或初始狀態的方法是使用等價劃分。將輸入或狀態分爲輸入和狀態集合,以便集合中的所有元素應該導致相同的行爲並且彼此相鄰。所以在你的情況下,等價分區可能是A-O,P,Q-R,S,T-Z。然後爲每個分區分配一個測試用例。

相關問題