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