2012-10-15 32 views
2

我最近一直在寫很多單元測試。有一個場景,我無法找到一個乾淨的解決方案......測試一個巨大的分解方法及其內部幫助方法

比方說,你有一個方法的野獸:

public void bigMethod() { 
    // a lot of code goes in here 
} 

爲了使您的生活更輕鬆,你的代碼更清潔你平時分解等獸成更小的內方法:

public void bigMethod() { 
    a(); 
    b(); 
    c(); 
    // etc. 
} 

可以測試所有的內方法(一()中,b(),C()等)獨立地。問題是bigMethod()也應該被測試,但它唯一做的就是鏈接一些其他方法的調用,並且已經經過了徹底的測試!

你如何處理這種情況?您不能僅僅因爲需要確保a(),b()和c()在IN PROPER ORDER中被調用而不對bigMethod()進行測試。但是爲bigMethod()寫一個測試會導致很多重複測試。每次減少這種重複是很麻煩的,因爲你會這樣做。這在我腦海

一個想法是:

public void bigMethod() { 
    helperA.a(); 
    helperB.b(); 
    helperC.c(); 
    // etc. 
} 

在這種情況下,你測試每一個輔助類,然後確保bigMethod()調用它們序。乾淨而乾淨,但在項目中引入了很多非常小的類。

幫助測試ninjas!

+0

'尼斯和清潔,但介紹了很多非常小的班進入project.'小,乾淨,簡單,易於測試,mockable,可重複使用,並與一個責任。對我來說聽起來不那麼糟糕... – digitaljoel

回答

2

通常情況下,最佳做法是讓您的單元測試測試bigMethod(),因爲它是公開的方法,並且測試無法識別內部輔助方法。

如您所指出的那樣,如果您重構了內部實現bigMethod(),那麼對類的內部工作知道太多的測試往往很脆弱,必須進行大量修改。

所以我的建議是重寫你的測試,專注於bigMethod(),然後不必擔心代碼重複。

1

你無法找到一個好的解決方案的原因是,將該方法拆分成順序件並不能真正改善事情。事實上,它可能使調試變得更加困難,因爲您必須跨越方法邊界共享狀態,可能使用實例變量。

我知道這不是你想要聽到的答案,但是如果你真的想改進代碼,你會退後一步,重新分析bigMethod做了什麼,並重寫它,將它的各種函數分成類適當的接口。理想情況下,您還可以重構調用bigMethod的地方,但我意識到這可能超出了您分配的任務的範圍。

+0

我不同意。將該方法拆分爲順序片段確實提高了可讀性。這就是所謂的「提取直到你放棄」:) http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCEQFjAA&url=http%3A%2F%2Fblog.objectmentor。 com%2Farticles%2F2009%2F09%2F11%2Fone-things-extract-until-you-drop&ei = N0h8UPf6B6fA0QXRlYGgAg&usg = AFQjCNG2db-4FvjCtyT70J5HIBu0XKi1qQ – Mik378

+0

這一切都取決於原始代碼以及它是如何分解的。爲了分裂而拆分可能是好的或壞的,並且根據我的經驗(從閱讀數千行遺留代碼)通常不是一個好主意。 –

+1

@ Mik378:鮑勃馬丁是一位善於撰寫不良建議的高手,使其看起來非常棒。他使用的代碼適合被分成非常小的部分;很多代碼就是這樣,但有些代碼不是。我曾有一位曾經無意識地抨擊Eclipse中的「抽取方法」重構的同事,直到我們的代碼變得難以理解,難以維護,一團糟。他可能讀了很多鮑勃馬丁。 –

1

首先,如果a(),b()c()是公共方法,以下所有文本都有意義。

bigMethod()測試重點放在內部通話的後果,這意味着隨後b()和隨後c()a()電話。

這完全是獨立測試每種方法的另一種情況。

所以根據我來說,添加特定的測試bigMethod()沒有透露有一些重複,而是一個新的有趣的例子來檢查:內部通話的合作。

我會保持你的代碼的第一個版本,並測試它:)

事實上,這似乎是與項目交付的類似常見的問題:

假設單獨終於研製收集他們三個項目。這樣做的

三種可能性:

  • 測試僅這三個項目分別
  • 等待測試只混合三個項目
  • 測試這些見風使舵的!

從邏輯上講,第三種可能性是希望的;單元測試也是一樣。

a()b()c()可能有意想不到的行爲,這並不妨礙bigMethod()有一個期望的結果成反比,bigMethod()可以儘管獨立方法試驗成功的有意想不到的結果。

0

我認爲解決方案不能清楚地顯示給你的原因是因爲你沒有真正想出和定義a(),b()c()的性質。你一定要弄清楚下列哪些a()b()c()是:

  1. 內部,密不可分的bigMethod(),使在它之外沒有任何意義的子部分。

  2. 屬於班級公共合同一部分的方法有助於提高其凝聚力,可以從外部獨立調用。

  3. 畢竟不屬於班級的方法。把它們拿出來會有利於課堂的凝聚力,並使它們更容易重用。

一旦你明白了這一點,如何測試它們的答案很容易。

  1. 只是測試bigMethod()作爲原子塊是,不要試圖用其內部子部分的可見度範圍撥弄讓他們測試。

  2. 獨立地測試a(),b()c()。然後測試bigMethod(),使用部分模擬,並驗證以正確的順序調用子方法。您也可以測試bigMethod()的結果,使其成爲一種集成測試,而不是單元測試,因爲您提到了重複問題。

  3. 獨立地測試a(),b()c()。然後測試bigMethod(),使用mocks作爲它們的對象,並確認bigMethod()正確地與這些對象進行交談。

相關問題