文通過(guò)理論分析和詳細(xì)例子向讀者闡述 JUnit 4.4 所帶來(lái)的新特性,讀者通過(guò)本文的學(xué)習(xí),可以輕松掌握使用 JUnit 4.4 的新特性。
隨著當(dāng)前 Java 開發(fā)的越發(fā)成熟,Agile 和 TDD 的越發(fā)流行,自動(dòng)化測(cè)試的呼聲也越來(lái)越高。若想將單元測(cè)試變得自動(dòng)化,自然 JUnit 這把利器必不可少,這也是 JUnit 自 1997 年誕生以來(lái)在 Java 開發(fā)業(yè)界一直相當(dāng)流行的原因。
JUnit 是針對(duì) Java 語(yǔ)言的一個(gè)單元測(cè)試框架,它被認(rèn)為是迄今為止所開發(fā)的重要的第三方 Java 庫(kù)。 JUnit 的優(yōu)點(diǎn)是整個(gè)測(cè)試過(guò)程無(wú)需人的參與,無(wú)需分析和判斷終測(cè)試結(jié)果是否正確,而且可以很容易地一次性運(yùn)行多個(gè)測(cè)試。 JUnit 的出現(xiàn)促進(jìn)了測(cè)試的盛行,它使得 Java 代碼更健壯,更可靠,Bug 比以前更少。
JUnit 自從問(wèn)世以來(lái)一直在不停的推出新版本,目前新的版本是 2007 年 7 月發(fā)布的 JUnit 4.4,它是繼 JUnit4 以來(lái)大的發(fā)行版,提供了很多有用的新特性。本文將假設(shè)讀者已經(jīng)具有 JUnit 4 的使用經(jīng)驗(yàn)。
JUnit 4.4 概述
JUnit 設(shè)計(jì)的目的是有效地抓住編程人員寫代碼的意圖,然后快速檢查他們的代碼是否與他們的意圖相匹配。 JUnit 發(fā)展至今,版本不停的翻新,但是所有版本都一致致力于解決一個(gè)問(wèn)題,那是如何發(fā)現(xiàn)編程人員的代碼意圖,并且如何使得編程人員更加容易地表達(dá)他們的代碼意圖。JUnit 4.4 也是為了如何能夠更好的達(dá)到這個(gè)目的而出現(xiàn)的。
JUnit 4.4 主要提供了以下三個(gè)大方面的新特性來(lái)更好的抓住編程人員的代碼意圖:
提供了新的斷言語(yǔ)法(Assertion syntax)——assertThat
提供了假設(shè)機(jī)制(Assumption)
提供了理論機(jī)制(Theory)
新的斷言語(yǔ)法(Assertion syntax)—— assertThat
JUnit 4.4 學(xué)習(xí) JMock,引入了 Hamcrest 匹配機(jī)制,使得程序員在編寫單元測(cè)試的 assert 語(yǔ)句時(shí),可以具有更強(qiáng)的可讀性,而且也更加靈活。
Hamcrest 是一個(gè)測(cè)試的框架,它提供了一套通用的匹配符 Matcher,靈活使用這些匹配符定義的規(guī)則,程序員可以更加精確的表達(dá)自己的測(cè)試思想,指定所想設(shè)定的測(cè)試條件。比如,有時(shí)候定義的測(cè)試數(shù)據(jù)范圍太精確,往往是若干個(gè)固定的確定值,這時(shí)會(huì)導(dǎo)致測(cè)試非常脆弱,因?yàn)榻酉聛?lái)的測(cè)試數(shù)據(jù)只要稍稍有變化,可能導(dǎo)致測(cè)試失。ū热 assertEquals( x, 10 ); 只能判斷 x 是否等于 10,如果 x 不等于 10,測(cè)試失敗);有時(shí)候指定的測(cè)試數(shù)據(jù)范圍又不夠太精確,這時(shí)有可能會(huì)造成某些本該會(huì)導(dǎo)致測(cè)試不通過(guò)的數(shù)據(jù),仍然會(huì)通過(guò)接下來(lái)的測(cè)試,這樣會(huì)降低測(cè)試的價(jià)值。 Hamcrest 的出現(xiàn),給程序員編寫測(cè)試用例提供了一套規(guī)則和方法,使用其可以更加精確的表達(dá)程序員所期望的測(cè)試的行為。(具體 Hamcrest 的使用,請(qǐng)參閱 參考資料)
JUnit 4.4 結(jié)合 Hamcrest 提供了一個(gè)全新的斷言語(yǔ)法——assertThat.程序員可以只使用 assertThat 一個(gè)斷言語(yǔ)句,結(jié)合 Hamcrest 提供的匹配符,可以表達(dá)全部的測(cè)試思想。
assertThat 的基本語(yǔ)法如下:
清單 1 assertThat 基本語(yǔ)法
assertThat( [value], [matcher statement] );
value 是接下來(lái)想要測(cè)試的變量值; matcher statement 是使用 Hamcrest 匹配符來(lái)表達(dá)的對(duì)前面變量所期望的值的聲明,如果 value 值與 matcher statement 所表達(dá)的期望值相符,則測(cè)試成功,否則測(cè)試失敗。
assertThat 的優(yōu)點(diǎn)
優(yōu)點(diǎn) 1:以前 JUnit 提供了很多的 assertion 語(yǔ)句,如:assertEquals,assertNotSame,assertFalse,assertTrue,assertNotNull,assertNull 等,現(xiàn)在有了 JUnit 4.4,一條 assertThat 即可以替代所有的 assertion 語(yǔ)句,這樣可以在所有的單元測(cè)試中只使用一個(gè)斷言方法,使得編寫測(cè)試用例變得簡(jiǎn)單,代碼風(fēng)格變得統(tǒng)一,測(cè)試代碼也更容易維護(hù)。
優(yōu)點(diǎn) 2:assertThat 使用了 Hamcrest 的 Matcher 匹配符,用戶可以使用匹配符規(guī)定的匹配準(zhǔn)則精確的指定一些想設(shè)定滿足的條件,具有很強(qiáng)的易讀性,而且使用起來(lái)更加靈活。如清單 2 所示:
清單2使用匹配符 Matcher 和不使用之間的比較
// 想判斷某個(gè)字符串 s 是否含有子字符串 "developer" 或 "Works" 中間的一個(gè)
// JUnit 4.4 以前的版本:assertTrue(s.indexOf("developer")>-1||s.indexOf("Works")>-1 );
// JUnit 4.4:
assertThat(s, anyOf(containsString("developer"), containsString("Works")));
// 匹配符 anyOf 表示任何一個(gè)條件滿足則成立,類似于邏輯或 "||", 匹配符 containsString 表示是否含有參數(shù)子
// 字符串,文章接下來(lái)會(huì)對(duì)匹配符進(jìn)行具體介紹
優(yōu)點(diǎn) 3:assertThat 不再像 assertEquals 那樣,使用比較難懂的“謂賓主”語(yǔ)法模式(如:assertEquals(3, x);),相反,assertThat 使用了類似于“主謂賓”的易讀語(yǔ)法模式(如:assertThat(x,is(3));),使得代碼更加直觀、易讀。