unit-testing - 單元測試範例 - xunit教學




單元測試反模式目錄 (20)

anti-pattern :必須存在至少兩個關鍵要素才能正式區分實際的反模式和簡單的壞習慣,不好的做法或壞主意:

  • 一些重複的行為,過程或結構模式最初似乎是有益的,但最終會產生比有益結果更糟糕的後果,
  • 重構的解決方案清晰記錄,在實踐中得到驗證並可重複使用。

投票支持你在“野外”看到的TDD反模式太多次了。
詹姆斯卡爾的博客文章關於測試驅動開發yahoogroup的相關討論

如果你找到了一個'未命名'的人......他們也是。 每個反模式的一個帖子請讓票數有所收穫。

我的既得利益是找到前n個子集,以便我可以在不久的將來在午餐會上討論他們。


Chain Gang

一些必須以特定順序運行的測試,即一次測試會改變系統的全局狀態(全局變量,數據庫中的數據)和下一次測試依賴於它。

你經常在數據庫測試中看到這一點。 與teardown()的回滾操作不同,測試會將其更改提交到數據庫。 另一個常見原因是對全局狀態的更改未包含在try / finally塊中,如果測試失敗,則會進行清理。


The Sleeper,又名維蘇威火山 - Nick Pellow

在未來某個特定時間和日期注定要失敗的測試。 當測試使用Date或Calendar對象的代碼時,這通常是由不正確的邊界檢查引起的。 有時候,如果在一天的特定時間運行,如午夜,測試可能會失敗。

'The Sleeper'不應與' Wait And See '反模式混淆。

該代碼將在2000之前被更換 - 1960年的許多開發人員


免費搭車/搭載 - 詹姆斯卡爾,蒂姆奧廷格
與其寫一個新的測試用例方法來測試另一個/不同的特性/功能 ,一個新的斷言(及其相應的動作,即從AAA執行的Act步驟)在現有的測試案例中一起出現。


分身

為了測試某些東西,你必須將被測代碼的一部分複製到一個具有相同名稱和包的新類中,並且你必須使用classpath magic或者一個自定義類加載器來確保它首先可見(這樣你的副本才會被拾取向上)。

這種模式表明一個不健康的隱藏的依賴關係,你無法從測試中控制。

我看著他的臉......我的臉! 它就像一面鏡子,但讓我的血液凍結。


四十足測試

由於害怕與他們試圖測試的類太接近,這些測試在遠處行動,被無數抽象層和數千行代碼從他們正在檢查的邏輯中分離出來。 因此,它們非常脆弱,並且容易受到興趣階層史詩旅程中發生的各種副作用的影響。


圖靈測試

一個由一些昂貴的工具自動生成的測試用例,它使用一些太巧妙的數據流分析從被測試的類中蒐集到許多斷言。 讓開發人員誤以為自己的代碼經過了充分的測試,從而免除了設計和維護高質量測試的責任。 如果機器可以為你寫測試,為什麼不能把它的手指伸出來寫出應用程序呢!

你好傻。 - 世界上最聰明的電腦新學徒(從一個舊的Amiga漫畫)。


快樂的路徑

測試保持在開心路徑(即預期的結果),而不測試邊界和例外。

JUnit反模式


慢戳

單元測試運行速度非常慢。 當開發商啟動時,他們有時間去洗手間,抽煙,或者更糟糕的是,他們在一天結束之前回家測試。 (Src: James Carr的帖子

又名不會像他們應該那樣頻繁運行的測試


死樹

創建存根的測試,但測試並未實際寫入。

我已經在我們的產品代碼中看到了這一點:

class TD_SomeClass {
  public void testAdd() {
    assertEquals(1+1, 2);
  }
}

我甚至不知道該怎麼想。


母雞 - 弗蘭克卡弗
一個常見的設置遠遠超過實際的測試用例。 例如,當測試只聲明存在或不存在某些東西時,創建填充了顯然重要且唯一值的各種複雜數據結構。
高級症狀: 不合適的共享夾具

我不知道它是乾什麼的......無論如何我都加了,以防萬一。 - 匿名開發者


沒有名字的測試 - Nick Pellow

添加的測試重現錯誤跟踪器中的特定錯誤,並且其作者認為它不保證自己的名稱。 沒有增強現有的缺乏測試,而是創建了一個名為testForBUG123的新測試。

兩年後,當測試失敗時,您可能需要首先嘗試在錯誤跟踪器中找到BUG-123來確定測試的意圖。


測試一切

我不敢相信這直到現在還沒有被提及,但測試不應該違反單一責任原則

我遇到過這麼多次,打破這個規則的測試在定義上是一個噩夢來維護。


當地英雄

測試用例依賴於為了運行而編寫的開發環境特定的某些內容。 結果是開發框中的測試通過,但是當有人試圖在別處運行它時失敗。

隱藏的依賴

與當地英雄密切相關,單元測試需要在測試運行之前將某些現有數據填充到某處。 如果這些數據沒有填充,測試將會失敗,並且不會給開發人員什麼想要的東西,或者為什麼......迫使他們挖掘大量代碼來找出它所使用的數據應該來自哪裡。

很遺憾,古代的.dll太多次了,而這些依賴於任何生產系統上不斷同步的模糊不清的.ini文件,更別說現存在你的機器上,沒有與三個負責這些DLL的開發人員進行廣泛的協商。 嘆。


當我看到一些閃爍的GUI時,我會相信它
一個不健康的注意力/痴迷於通過GUI來測試應用程序“就像真正的用戶一樣”

通過GUI測試業務規則是一種可怕的耦合形式。 如果通過GUI編寫數千個測試,然後更改GUI,則會有數千個測試中斷。
相反,只需通過GUI測試GUI,並在運行這些測試時將GUI耦合到虛擬系統而不是真實係統。 通過不涉及GUI的API測試業務規則。 - 鮑勃馬丁

“你必須明白,眼見為實,但也知道眼見為實。” - 丹尼斯·維特利


秘密守望者 - 弗蘭克卡弗
由於缺乏斷言,乍一看似乎沒有進行測試。 但是“魔鬼在細節中”..測試真的依賴於拋出的異常,期待測試框架捕獲異常並將其作為失敗報告給用戶。

[Test]
public void ShouldNotThrow()
{
   DoSomethingThatShouldNotThrowAnException();
}

第二類公民 - 測試代碼不像生產代碼那樣重構,包含大量重複代碼,因此難以維護測試。


線擊球員

在第一次測試中,測試覆蓋了所有內容,代碼覆蓋率工具以100%來確認它,但實際上測試只是在沒有任何輸出分析的情況下執行代碼。

coverage-vs-reachable-code


肛門探針

一個必須使用瘋狂,非法或不健康的方式來執行其任務的測試,例如:使用Java的setAccessible(true)讀取私有字段,或者擴展一個類以訪問受保護的字段/方法,或者必須將測試放入特定的包中才能訪問打包全局字段/方法。

如果您看到這種模式,則被測試的類會使用太多的數據隱藏。

這與Inspector之間的區別在於被測試的類試圖隱藏你需要測試的東西。 所以你的目標不是要達到100%的測試覆蓋率,而是要能夠測試任何東西。 想想一個只有私有字段的類,一個沒有參數且沒有getter的run()方法。 沒有違規的情況下無法測試。

Michael Borgwardt評論道: 這不是真正的測試反模式,它是處理被測代碼缺陷的實用主義。 當然,最好修復這些缺陷,但在第三方庫的情況下這可能是不可能的。

Aaron Digulla:我很同意。 也許這個條目更適合於“JUnit HOWTO”wiki而不是反模式。 註釋?


過度安置 - 詹姆斯卡爾
為了開始測試,需要進行巨大設置的測試。 有時使用幾百行代碼來為一次測試準備環境,涉及多個對象,由於所有設置的“噪聲”正在進行,所以很難真正確定所測試的內容。 (Src: James Carr的帖子


閃爍測試 (來源:Romilly Cocking)

一個只是偶爾失敗的測試,而不是在特定的時間,通常是由於測試中的競爭條件。 通常在測試異步的東西時發生,比如JMS。

可能是超級設置為' 等待和看見 '反模式和' The Sleeper '反模式。

構建失敗,噢,再次運行構建。 - 匿名開發者





anti-patterns