正确设置JUnit测试名称
尋找好名字是手工軟件的挑戰之一。 您需要隨時隨地找到它們-類,方法,變量,僅舉幾例。 但是,什么使名字成為好名字呢? 引用Oncle Bob的話:“三件事:可讀性,可讀性和可讀性!” 他后來通過表達的清晰,簡單和密度1對其進行了定義 。
盡管這對我來說很有意義,但是我發現自己尤其在測試方法方面有些掙扎。 為了更好地理解我在說什么,需要知道我編寫了代碼測試驅動程序 。 做了一段時間之后,我逐漸將工作重點從被測單元轉移到了測試本身。 這可能是因為我喜歡將一個測試用例視為一個完整的規范和質量保證,因此它非常重要2 。
因此,只要測試失敗,理想情況下,我就能一眼就能知道哪個規范被破壞以及為什么。 實現此目的的最佳方法似乎是找到一個表達性的測試名稱,因為這是報告視圖中顯示的第一條信息:
從這個角度來看,我并不總是對這種觀點所顯示的內容感到滿意,因此我花了一些時間進行研究,以了解哪些思想流派可能會有所幫助。 不幸的是,我發現的大多數結果都有些過時,并且-不足為奇-關于該主題的意見分歧。 這篇文章基于這些發現和一些個人經驗,代表了我的看法。
根據方法或行為測試名稱進行測試?
每種方法的測試形式通常都是由工具提供的,例如,在事后生成單個測試存根。 如果您的類Foo帶有方法bar則生成的方法將稱為testBar 。 我一直對這種開發風格或命名約定的有用性持懷疑態度,并且會像舊的JavaRanch線程中的引文一樣爭論:“您根本不應該將其視為測試方法,而應該將其視為測試行為。班上的 因此,我喜歡我的測試方法名稱來傳達預期的行為3 。
有趣的是,我將對那一點改變看法。 如上所述,傳達“行為”的想法要求找到一個簡明的名稱來全面表達該“行為”。 但是隨后,術語行為表示由一個動作從一個狀態過渡到另一種狀態,或者用BDD術語表示,例如“時給定”模式。 老實說,我認為將所有這些信息放在一個單一的名字中通常不是一個好主意4 :
@Test public voidgivenIsVisibleAndEnabledWhenClickThenListenerIsNotified() {} @Test public voidgivenIsVisibleAndNotEnabledWhenClickThenListenerIsNotNotified() {} @Test public voidgivenIsNotVisibleAndEnabledWhenClickThenListenerIsNotNotified() {}也許這只是一個口味問題,但是根據我的經驗,無論我選擇哪種格式樣式,由于缺乏簡單性和/或清晰度,這種方法通常缺乏可讀性。 此外,這樣的重載名稱往往與注釋具有相同的問題–隨著內容的發展,這些名稱很容易過時。 因此,我想改用BUILD-OPERATE-CHECK 5模式。 這將允許將階段拆分為單獨的子方法名稱,并將其放置在單個測試中:
@Test public void testNameHasStillToBeFound() {// do what is needed to match preconditiongivenIsVisibleAndEnabled();// execute the transitionwhenClick();// verify the expected outcomethenListenerIsNotified(); }不幸的是,這導致我們進入了起點。 但是,如果仔細看一下上面的示例,所有方法都圍繞著一個共同的分母。 它們都屬于觸發轉換的同一動作。 在我們的例子中,點擊事件。 考慮到從開發過程的角度來看,我認為一個測試用例比被測試的單元更為重要,因此可以將其解釋為一種符號,以在開發中的單元中以適當的方法名稱來反映操作6 。
因此,出于示例的考慮,假設我們有一個環繞UI控件的ClickAction 。 鑒于上述情況,引入一種稱為ClickAction#execute()的方法對我們來說似乎很合適。 為簡單起見,我們可以將該名稱也用于表示從ClickAction默認狀態到通過ClickAction#execute()控件構造的轉換的測試方法:
class ClickActionTest {@Testpublic void execute() {Control control = mock( Control.class );ClickAction clickAction = new ClickAction( control );clickAction.execute();verify( control ).notifyListeners(...)} }為了簡單起見,下一個測試名稱可能只提及重要的狀態信息,因為它不同于默認值并導致另一個結果:
class ClickActionTest {[...]@Testpublic void executeOnDisabledControl() {Control control = mock( Control.class );when( control.isEnabled() ).thenReturn( false );ClickAction clickAction = new ClickAction( control );clickAction.execute();verify( control, never() ).notifyListeners(...)}@Testpublic void executeOnInvisibleControl() {[...] }如您所見,這種方法產生了一組測試名稱,從技術上講,它們代表各種“每種方法的測試”模式-但并非出于我認為完全出于不利的原因。 考慮到上下文,我認為這種命名模式很簡單,清晰并且可以表達:
仍未提及預期的測試結果。 乍一看,這似乎并不令人滿意,但是從我目前的觀點來看,我愿意接受這一點,這是一種合理的權衡。 尤其是在JUnit報告視圖中通常還會顯示測試失敗的原因。 因此,可以通過提供有意義的測試失敗7來解決該問題。
結論
實際上,我一段時間以來正在使用上述測試命名模式。 到目前為止,效果還不錯。 特別是在像我通常使用的非常小的單元上工作時,幾乎沒有錯誤解釋的空間。 但是,這種方法并不適合所有情況,有時候感覺更好,并且可讀性足以提及結果。 我不會在這里談論原則,也許我弄錯了。 因此,對于任何您可能會意識到可以擴大我的觀點的更詳細方法的指示,我都會感到高興。
翻譯自: https://www.javacodegeeks.com/2014/03/getting-junit-test-names-right.html
總結
以上是生活随笔為你收集整理的正确设置JUnit测试名称的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Java的常见误解
- 下一篇: 劳务备案需要什么手续和证件(劳务备案需要