2011-01-07 22 views
9

我們的團隊正在緩解TDD並努力應對單元測試的最佳做法。我們的測試代碼使用依賴注入。我們的測試通常遵循Arrange-Act-Assert佈局,我們在Moq的編配部分中模擬依賴關係。可重複使用的模擬與每次測試中的嘲諷

從理論上講,單元測試應該是一個屏蔽層,可以在重構時保護您。但它正在變成一個阻止我們這樣做的錨。我試圖確定我們的流程失敗的地方。

考慮簡單的例子:

  • XRepository.Save有它的簽名和行爲/合同變更。
  • XController.Save使用XRepository.Save,因此重構爲使用新界面。但從外部來看,公共合同並沒有改變。

我預計控制器測試做需要進行重構,而是證明給我看我的新控制器實現榮譽不變的合同。但我們在這裏失敗了,因爲情況並非如此。

每個控制器測試都會動態地模擬存儲庫接口。他們都需要改變。此外,由於每個測試都不想模擬所有的接口和方法,因此我們發現我們的測試與特定的實現相關聯,因爲它需要知道模擬的方法。

對於我們擁有的更多測試,重構變得越來越難以重構!或者更準確地說,我們嘲笑界面的次數越多。

所以我的問題:

  1. 使用的即時任何偏好嘲笑在每個測試VS製作可重複使用的手工製作的模擬爲每個接口?

  2. 鑑於我的故事,我是否缺少一些原理或陷入常見陷阱?

謝謝!

+2

每當你需要嘲笑某事時,首先想想如果你可以手動創建嘲笑。你會經常發現即時模擬通常會帶來明顯複雜的氣味。如果是這樣的話,那麼創建手動嘲笑其他去飛行嘲笑 –

+1

需要考慮的東西:http://en.wikipedia.org/wiki/Interface_segregation_principle – TrueWill

回答

9

您不錯過任何原則,但這是一個常見問題。我認爲每個團隊都以自己的方式解決(或不)。

副作用

您將繼續就此問題與它有副作用的任何功能。我已經找到了副作用的功能我不得不做出這樣的保證部分或全部測試以下內容:

  • 那它是/不叫
  • 它被稱爲次數
  • 是什麼參數傳給它
  • 通話順序。

確保測試通常意味着違反封裝(我與實現交互並瞭解它)。每當你這樣做時,你總會隱含地將測試與實現結合起來。這會導致您在更新您要公開/測試的實施部分時必須更新測試。

可重複使用的嘲弄

我已經用可重複使用的模擬考試有很大的影響。它們的折衷是它們的實現更復雜,因爲它需要更完整。你確實減少了更新測試以適應重構的成本。

驗收TDD

另一種選擇是改變你的什麼測試。由於這實際上是關於改變你的測試策略,所以不能輕言放棄。您可能需要先做一些分析,看看它是否真的適合您的情況。

我以前用TDD做單元測試。我遇到了一些我覺得我們不應該處理的問題。特別是在重構期間,我注意到我們通常不得不更新許多測試。這些重構不在一個代碼單元內,而是主要組件的重組。我知道很多人會說這個問題是頻繁的大變動,而不是單元測試。我們的規劃/架構可能會導致部分重大變化。但是,對於導致方向變化的業務決策也是如此。這些和其他合法的原因導致需要對代碼進行大的修改。最終的結果是大型重構因所有測試更新而變得更加緩慢和痛苦。

由於單元測試未涵蓋的集成問題,我們也遇到了錯誤。我們通過手動驗收測試做了一些。實際上,我們做了相當多的工作,使驗收測試儘可能低。他們仍然是手動的,我們感覺單元測試和驗收測試之間有很多交叉,應該有一種方法來降低實現這兩者的成本。

然後公司就裁員了。突然之間,我們沒有足夠的資源來投入編程和維護。我們被推動爲包括測試在內的所有事情獲得最大回報。我們開始添加所謂的部分堆棧測試來覆蓋我們所遇到的常見集成問題。事實證明,它們非常有效,所以我們開始做較不經典的單元測試。我們還擺脫了手動驗收測試(Selenium)。我們慢慢推進測試開始測試的地方,直到我們實際上正在進行驗收測試,但沒有瀏覽器。我們將模擬GET,POST或PUT方法到特定的控制器並檢查驗收標準。

  • 該數據庫是否被正確更新
  • 返回
  • 正確的HTTP狀態代碼的頁面返回的是:
    • 是有效的HTML 4.01嚴格
    • 包含我們要發送的信息回給用戶

我們結束了更少的錯誤。特別是幾乎所有的集成bug,以及由於大量重構造成的bug幾乎完全消失。

有權衡。事實證明,職業球員遠遠超過了缺席狀態的利弊。缺點:

  • 測試通常更復雜,幾乎每個人都測試一些副作用。
  • 我們可以知道什麼時候中斷了,但它不像單元測試那樣有針對性,所以我們必須做更多的調試才能找出問題出在哪裏。
+0

謝謝。我認爲我們正朝着同樣的方向前進。目前我們已經進行了從域級對象開始的集成測試 - 它們不像測試控制器那麼直接。控制器仍然通過嘲笑其依賴性進行測試。感謝您的評論。 –

1

我一直在努力解決這類問題,並且沒有一個我認爲是堅實的答案,但這裏是一個初步的思考方式。我觀察到兩種單元測試

  1. 有測試在哪裏練習公共接口,這些都非常重要,如果我們要重建信心,他們證明我們遵守我們的合同給我們的客戶。這些測試最好通過手工製作的可重用模擬來處理,這些模擬處理一小部分測試數據。
  2. 有「覆蓋」測試。這些往往是爲了證明我們的實現行爲正確時,依賴關係不正常。這些我認爲需要在飛行模擬中挑起特定的實現路徑。
+0

感謝您的評論。它證實了我的一些想法。我想我正試圖更多地關注合同測試,並且認爲如果代碼路徑沒有成爲合約的一部分,那麼這是多餘的。但也許我們需要更加務實。 –