2012-08-10 62 views
4

考慮事件的順序如下:測試正確的事情,技術,避免重複覆蓋

  1. 你寫一個函數A(),做一個工作單元
  2. 你寫AA測試函數A()到確保沒有bug存在
  3. 你寫功能B()使用功能A()
  4. 你寫AA測試功能B(),以確保沒有bug存在
    個4.1試驗功能B()蓋功能A()正如你至少有2個試驗覆蓋了一些相同的功能

問題1的結果:是值得它來編寫函數A()開始與測試?

  1. 您編寫大量的代碼
  2. 你寫了一個巨大的迴歸測試,測試程序功能的終端到終端
    6.1實際上這單一的迴歸測試重複絕大多數已經寫

測試問題2:通過執行以下步驟,代碼中包含許多測試,這些測試不止一次覆蓋相同的事物。有沒有一種技術可以避免這種情況?

承擔:

對於這個問題的目的,請假設B則兩件事情,其中​​之一是在其整體

void performLifeChoice() { // B() 
    if (timeIsRight) { 
    askForPromotion(); // A() 
    } else { 
    goBackToSchool(); 
    } 
} 
+1

僅僅因爲'B()''使用A()'到一定程度,並不意味着它所調用的調用可能會導致所有的A()可能出現的問題,當直接用更多的輸入或條件進行測試時會出現這些問題。 – TheZ 2012-08-10 22:30:11

+0

假設'B()'做了很多事情,其中​​一個是完整的'A()'。通過測試B,您可以間接測試A – JAM 2012-08-10 22:31:06

+0

將'null'傳遞給'B()',您可能會發現問題並修復問題,使其無法達到'A()',但直接進行測試時,問題顯而易見。 – TheZ 2012-08-10 22:32:56

回答

3

我一般的回答是肯定的,你必須寫單元測試A(),原因有二:

1)你可能最終會調用A()從不同的上下文B(),並在在這種情況下,你會很高興知道A()正在工作,並避免測試重複。如果你沒有單獨測試A(),你最終會重寫兩次實際上是相同的測試,代碼的等價分支。 2)相關的,如果你不單獨測試A(),你可能會最終導致海龜一直在下降。現在想象一下,一個函數C()在它的一個分支中調用B(),而D()調用C()等等。如果你按照只測試更高級別函數的路徑,那麼你最終會並進行整合測試,這將不得不涵蓋越來越多的前提條件。保持各個單元在儘可能小的環境下進行測試,原則上可以避免這個問題。

我的答案的隱含結論是,如果A()絕不會從B()以外的地方調用,那麼可能值得使A()變爲私有的,並且在那一點上,測試可能會變成「可選的」。另一方面,保持該測試可能仍然有用,因爲它可以幫助您確定何時B()失敗,這是因爲您破壞了A()。用Kent Beck的話來說,「如果一個測試失敗了,可能有多少錯誤?答案越接近1,測試就越」單位「。」 - 有單元測試可以幫助您精確地確定代碼中哪裏出錯。

現在如何在不添加先決條件的情況下測試B()而不實際複製A()的測試呢?

這就是嘲笑/殘留或類似技術可以發揮作用的地方。如果您考慮B()正在做什麼,它實際上並不執行A(),它充當「協調器」,將條件傳遞給各種路徑。在我看來,適當的測試將是「當TimeIsRight,然後B()應該調用A()」時,A()提供的答案與B()無關,這是A()的責任,單元測試封面。

在那個框架中,對B()的測試應該Assert是,當TimeIsRight時調用A(),而不是A()返回。根據代碼的具體情況,您可以考慮在B()中使用A()「可替代」,例如通過接口或通過注入到A()的函數。

+0

也許在第二點,你應該明確地提出'缺陷隔離'。例如一個大塊的集成測試不會幫助你隔離缺陷位置。而對被調用函數的集中測試將幫助你完成這個工作。如果您已經放下了編寫自動化測試的努力,那麼您不應該進行調試。 – Gishu 2012-08-14 05:42:30

+0

@gishu同意你的評論,這就是爲什麼我添加了貝克引用,這對我來說傳達了單元測試的想法,以指明缺陷的來源。我會考慮如何使它更加明確,謝謝大家的意見,並且總體上對TDD主題做出了巨大貢獻! – Mathias 2012-08-14 06:08:04

1

在這個例子中,不,這不是真的在我看來,值得這樣寫測試只是爲了A.然而,在大多數情況下,A和B都將採取參數,而B將永遠不會對A的可能參數輸入的全部範圍進行操作,但是A的單元測試將會應該!),所以在這種情況下單元測試A並不是浪費,因爲它們覆蓋了不通過B傳遞的參數,不管是什麼B的參數輸入是。

3

由於方法似乎是在同一個班級,

  • 如果A()是私有的,只是測試B()A()將作爲B()測試的一部分進行測試。

  • 如果A()是公開的,請不要在測試B()時測試它。在單獨的測試中驗證A()的正確性。然後在另一個測試中,只需檢查B()正確地調用A()。在你的例子中,這意味着驗證在timeIsRight的情況下askForPromotion()是否被調用。

請注意,如果A()和B()在不同的類中,情況會稍有不同。

順便提及,與TDD方法,你的事件的順序應該是2 1。4. 3.)