天天看點

Spock代碼講解 - if esle 分支場景測試

這是Spock系列的第四篇文章,在第二篇講單元測試開發成本和效率問題時,提到了如何測試複雜的if else場景,分别使用Junit和Spock的實作,以及Spock的優勢在哪裡,這一篇會詳細講解Spock代碼的文法

如果業務比較複雜,對應的代碼實作會有不同的分支邏輯,類似下面的僞代碼:

這樣的 if else 嵌套代碼因為業務的原因很難避免,如果要測試這樣的代碼,保證覆寫到每一個分支邏輯的話,使用傳統的Junit單元測試代碼寫起來會很痛苦和繁瑣,雖然可以使用Junit的@parametered參數化注解或者dataprovider的方式,但還是不夠直覺,調試起來也不友善

下面就結合具體業務代碼講解Spock如何解決這種問題,還是先看下業務代碼邏輯:

根據輸入的身份證号碼識别出生日期、性别、年齡等資訊,邏輯不複雜,就是分支多,我們來看下Spock代碼是如何測試這種情況:

在測試方法體的第一行使用了expect标簽,它的作用是when + then标簽的組合,即 "什麼時候做什麼 + 然後驗證什麼結果" 組合起來

即當調用IDNumberUtils.getBirAgeSex(idNo) 方法時,驗證結果是result,result如何驗證對應的就是where裡的result一列的資料,當輸入參數idNo是"310168199809187333"時,傳回結果是: ["birthday": "1998-09-18", "sex": "男", "age": "22"]

expect可以單獨使用,可以不需要where,隻是在這個場景需要

@Unroll注解表示展開where标簽下面的每一行測試,作為單獨的case跑,再加上方法體"身份證号:#idNo 的生日,性别,年齡是:#result",使用了groovy的字面量特性,動态替換字元串變量,這樣每次跑的單測結果展示也很容易區分,友善了解,如下:

Spock代碼講解 - if esle 分支場景測試

每個測試結果對應where标簽裡的一行

另外在intellij idea裡可以run with coverage的運作方式檢視單測覆寫率情況:

Spock代碼講解 - if esle 分支場景測試
Spock代碼講解 - if esle 分支場景測試

左邊圈出的綠色柱子表示單測已覆寫的代碼,紅色柱子是單測還沒有覆寫到的分支,如果需要進一步提高覆寫率,隻需在where表格中再添加一行測試條件即可

Jacoco是統計單元測試覆寫率的一種工具,當然Spock也自帶了覆寫率統計的功能,這裡使用第三方Jacoco的原因主要是國内公司使用的比較多一些,包括我們公司現在使用的也是Jacoco,是以為了相容就以Jacoco來檢視單測覆寫率

當然你也可以使用Spock自帶的單測覆寫率工具,在後面的文章裡會介紹具體如何配置,本篇主要說下如何通過Jacoco确認分支是否完全覆寫到

在pom檔案裡引用jacoco的插件: jacoco-maven-plugin, 然後執行mvn test 指令,成功後會在target目錄下生成單元測試覆寫率的報告:

Spock代碼講解 - if esle 分支場景測試

(具體生成路徑可以設定)

使用浏覽器打開index.html,就能看到所有的單測覆寫率統計名額:

Spock代碼講解 - if esle 分支場景測試

點選包名找到我們剛才測試的IDNumberUtils類,打開後可以看到具體的覆寫情況:

Spock代碼講解 - if esle 分支場景測試

綠色背景表示完全覆寫,黃色是部分覆寫,紅色沒有覆寫到

比如第45行黃色背景的else if() 判斷,提示有4分之2的分支缺失,雖然它下面的代碼也被覆寫了(顯示為綠色),但是因為我們的單測代碼沒有測試flag為false,以及certificateNo.length()!=18的場景,是以隻能算覆寫了一半(2/4)

講這個的原因是因為如果公司設定的分支覆寫率要求大于50%,那麼你就要在單元測試代碼裡額外增加這種情況的測試,即使業務代碼裡沒有這樣例外情況的處理

這種情況跟具體使用哪種單測架構沒關系,因為這隻是分支覆寫率統計的規則,隻不過使用Spock的話,解決起來會更簡單,隻需在where下增加一行針對的測試資料即可

(完整的源碼在公衆号裡回複spock擷取)

下一篇文章講下如何測試代碼中抛異常的情況

END -