淺談軟件單元測(cè)試中的“斷言” (assert) -- 從石器時(shí)代進(jìn)步到黃金時(shí)代

大家都知道祭往,在軟件測(cè)試特別是在單元測(cè)試時(shí),必用的一個(gè)功能就是“斷言”(Assert)伦意,可能有些人覺得不就一個(gè)Assert語(yǔ)句,沒啥花頭硼补,也有很多人用起來(lái)也是懵懵懂懂驮肉,認(rèn)為只要是Assert開頭的方法,拿過(guò)來(lái)就用已骇。一個(gè)偶然的機(jī)會(huì)跟人聊到此功能离钝,覺得還是有必要在此整理一下如何使用以及對(duì)“斷言”的理解。希望可以幫助大家對(duì)此有一個(gè)系統(tǒng)的理解褪储,也趁機(jī)聊聊“斷言”發(fā)展一路過(guò)來(lái)的心路歷程卵渴。

基礎(chǔ)知識(shí)

首先稍微介紹一下斷言相關(guān)知識(shí),對(duì)于有經(jīng)驗(yàn)的程序員請(qǐng)移步到下面的“斷言”進(jìn)化史部分鲤竹。

什么是斷言

在單元測(cè)試時(shí)浪读,程序員預(yù)計(jì)在程序運(yùn)行到某個(gè)節(jié)點(diǎn)位置,需要判斷某些邏輯條件必須滿足辛藻,這樣下面的一些業(yè)務(wù)邏輯才可以進(jìn)行下去碘橘,如果不滿足,程序就會(huì)"報(bào)錯(cuò)"甚至是"崩潰"揩尸。比如說(shuō)蛹屿,一段程序是負(fù)責(zé)“轉(zhuǎn)賬”,在真正開始轉(zhuǎn)賬操作前首先需要“斷言”這個(gè)賬戶是一個(gè)“合法”的賬戶岩榆,比如賬戶不是null错负。當(dāng)出現(xiàn)些狀況時(shí)坟瓢,程序開發(fā)人員就可以在第一時(shí)間知道這個(gè)問(wèn)題,可以去debug除錯(cuò)犹撒,而非等到交付給用戶后才發(fā)現(xiàn)問(wèn)題折联。其實(shí)這個(gè)功能是TDD (Test Driven Develop)的基石之一。

“斷言” vs "異常"或者錯(cuò)誤识颊, 即 Assert vs. Exception/Error

  • “斷言”通常是給程序開發(fā)人員自己使用诚镰,并且在開發(fā)測(cè)試期間使用。而異常等在程序運(yùn)行期間觸發(fā)
  • 通诚榭睿“斷言”觸發(fā)后程序“崩潰”退出清笨,不需要從錯(cuò)誤中恢復(fù)。而“異橙絮耍”通常會(huì)使用try/catch等結(jié)構(gòu)從錯(cuò)誤中恢復(fù)并繼續(xù)運(yùn)行程序抠艾。

“斷言”進(jìn)化史

“石器時(shí)代”

一開始的一些單元測(cè)試框架(比如JUnit)提供的斷言語(yǔ)句,這樣在程序某個(gè)地方確保某個(gè)邏輯關(guān)系肯定返回是true,如果不是true,這個(gè)單元測(cè)試就是沒有測(cè)試通過(guò)桨昙。如下就是一個(gè)例子,如果程序運(yùn)行到此行時(shí)返回false程序就會(huì)拋出一個(gè)錯(cuò)誤(如下圖一)并停止運(yùn)行检号,開發(fā)人員可以去檢查下為什么出現(xiàn)此問(wèn)題。非常的簡(jiǎn)單粗爆蛙酪。

assert(x=y);
blog_assert_1.png

“青銅時(shí)代”

上面這種斷言除了簡(jiǎn)單之外齐苛,是有一個(gè)問(wèn)題,就是當(dāng)斷言被觸發(fā)時(shí)顯示出來(lái)的錯(cuò)誤消息不是很友好桂塞。如上圖一凹蜂,只是知道出錯(cuò)了,但是并沒有太多有用的信息藐俺,比如最好是能顯示出x與y的值來(lái)炊甲,這樣好更快的理解為啥出錯(cuò)。后來(lái)欲芹,支持?jǐn)嘌缘膯卧獪y(cè)試框架升級(jí)版本出現(xiàn)了卿啡,它們提供了一系列的高級(jí)”斷言“語(yǔ)句,添加了一些更加友好的程序接口菱父,同時(shí)還提供比較親民的錯(cuò)誤消息颈娜,比如下面的例子使用了兩個(gè)單獨(dú)的斷言語(yǔ)句。

int x=111;
int y=222;      
assertEquals(x, y);
assertNotEquals(x, y);

執(zhí)行的結(jié)果如下圖二浙宜,你可以看到這個(gè)錯(cuò)誤結(jié)果相對(duì)于上面“石器時(shí)代”已經(jīng)包括了不少有用的信息官辽,比如除了知道斷言失敗外還顯示了期望的值以及實(shí)際值

blog_assert_2.jpg

“黃金時(shí)代”

但是上面這種方式有一個(gè)弊端粟瞬,就是需要大量的預(yù)置斷言方法(比如判斷相等一個(gè)方法同仆,判斷不相等一個(gè)方法等),去支持各種場(chǎng)景裙品。接下來(lái)又出現(xiàn)了新的解決方案俗批,其中的明星就是Hamcrest (其實(shí)這個(gè)詞是使用一種叫做angram的文字游戲俗或,即把一個(gè)原來(lái)單詞中的字母順序改變,這個(gè)Hamcrest就是從Matchers的變形)框架岁忘。是使用一種assertThat組合上Matcher來(lái)使用辛慰。

這個(gè)有多個(gè)好處,

  • 首先是支持了在Java8中才遲遲引入的流式編程(Stream)干像,即每個(gè)Matcher執(zhí)行完后會(huì)再返回一個(gè)Matcher帅腌,這樣可以一個(gè)套一個(gè)組成一個(gè)Matcher鏈
  • 另外Hamcrest還使用了非常接近于人類自然語(yǔ)言以及使用and/or/not等邏輯判斷的方式來(lái)寫測(cè)試方法,比如當(dāng)你看到下面的測(cè)試語(yǔ)句肯定會(huì)一目了然:
assertThat(actual, is(not(equalTo(expected)));
  • 還有一個(gè)好處是輸出的斷言消息更加易讀麻汰。
  • 另外還有一個(gè)好處即Hamcrest框架支持泛型TypeSafe速客,即在編譯時(shí)就會(huì)找到類型不匹配的錯(cuò)誤。比如下面第一個(gè)是傳統(tǒng)的斷言什乙,在編譯期不會(huì)報(bào)錯(cuò)挽封,但是運(yùn)行時(shí)會(huì)失敗,而第二個(gè)會(huì)在編譯時(shí)報(bào)錯(cuò)臣镣,就不用等到運(yùn)行期。
assertEquals("abc", 123); // 1
assertThat(123, is("abc")); // 2
blog_assert_3.jpg
  • 使用Hamcrest的最后一個(gè)好處是對(duì)測(cè)試框架的“解耦合”智亮,即忆某,使用此框架你可以現(xiàn)在使用Junit后面可以轉(zhuǎn)到TestNG。甚至你自己去擴(kuò)展自己實(shí)現(xiàn)阔蛉。

總結(jié)

上面說(shuō)了這么多弃舒,是不是感覺平時(shí)經(jīng)常使用的一個(gè)看似簡(jiǎn)簡(jiǎn)單單的Assert還有不少的東西可以深挖一下滴。這個(gè)只是拋磚引玉状原,如果大家還有什么點(diǎn)子或建議請(qǐng)使用下面的方式聋呢。

聯(lián)系我:

Reference:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颠区,一起剝皮案震驚了整個(gè)濱河市削锰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毕莱,老刑警劉巖器贩,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異朋截,居然都是意外死亡蛹稍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門部服,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)唆姐,“玉大人,你說(shuō)我怎么就攤上這事廓八》盥” “怎么了胆描?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)仗阅。 經(jīng)常有香客問(wèn)我昌讲,道長(zhǎng),這世上最難降的妖魔是什么减噪? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任短绸,我火速辦了婚禮,結(jié)果婚禮上筹裕,老公的妹妹穿的比我還像新娘醋闭。我一直安慰自己,他們只是感情好朝卒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布证逻。 她就那樣靜靜地躺著,像睡著了一般抗斤。 火紅的嫁衣襯著肌膚如雪囚企。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天瑞眼,我揣著相機(jī)與錄音龙宏,去河邊找鬼。 笑死伤疙,一個(gè)胖子當(dāng)著我的面吹牛银酗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播徒像,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼黍特,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了锯蛀?” 一聲冷哼從身側(cè)響起灭衷,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谬墙,沒想到半個(gè)月后今布,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拭抬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年部默,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片造虎。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡傅蹂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情份蝴,我是刑警寧澤犁功,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站婚夫,受9級(jí)特大地震影響浸卦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜案糙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一限嫌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧时捌,春花似錦怒医、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至拿诸,卻和暖如春扒袖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佳镜。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工僚稿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蟀伸。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像缅刽,于是被迫代替她去往敵國(guó)和親啊掏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理衰猛,服務(wù)發(fā)現(xiàn)迟蜜,斷路器,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • 什么是單元測(cè)試 在計(jì)算機(jī)編程中啡省,單元測(cè)試(Unit Testing)又稱為模塊測(cè)試, 是針對(duì)程序模塊(軟件設(shè)計(jì)的最...
    HelloCsl閱讀 10,942評(píng)論 1 46
  • 簡(jiǎn)介 測(cè)試 在軟件開發(fā)中是一個(gè)很重要的方面娜睛,良好的測(cè)試可以在很大程度決定一個(gè)應(yīng)用的命運(yùn)。軟件測(cè)試中卦睹,主要有3大種類...
    Whyn閱讀 5,729評(píng)論 0 2
  • Instrumentation介紹 Instrumentation是個(gè)什么東西畦戒? Instrumentation測(cè)...
    打不死的小強(qiáng)qz閱讀 7,765評(píng)論 2 39
  • 大部分人都知道,執(zhí)行力很重要结序,但是執(zhí)行力是什么障斋?又如何培養(yǎng)執(zhí)行力呢?人類的知識(shí)本質(zhì)上是一套邏輯系統(tǒng),只有自洽...
    浮云狒閱讀 305評(píng)論 0 1