什么是單元測試覆蓋率
關于其定義,先來看一下維基百科上的一段描述:
代碼覆蓋(Code coverage)是軟件測試中的一種度量,描述程序中源代碼被測試的比例和程度,所得比例稱為代碼覆蓋率。
簡單來理解,就是單元測試中代碼執行量與代碼總量之間的比率。
以一個最簡單的例子來直觀感受一下:
Service服務類:
public class NumToStringServiceImpl implements NumToStringService {@Overridepublic String num2Str(Integer i) {String str = "";switch (i) {case 1:str = "one";break;case 2:str = "two";break;default:str = "none";}return str;}
}
單元測試類:
public class NumToStringServiceTest {@AutowiredNumToStringService numToStringService;@Testvoid testNum2Str() {String str1 = numToStringService.num2Str(1);assertThat(str1, is("one"));String str2 = numToStringService.num2Str(2);assertThat(str2, is("two"));}
}
從上面的代碼中能看出,單元測試方法testNum2Str
能夠覆蓋到服務類num2Str
方法的case 1
和case 2
兩個分支,覆蓋不到default
分支。那么覆蓋率就是num2Str
方法case 1
和case 2
分支的代碼量除以方法的總代碼量。
單元測試覆蓋率框架
單元測試覆蓋率常用的框架有JaCoCo、EMMA和Cobertura。我們目前(在Jenkins中)使用的是JaCoCo。
JaCoCo可以統計的指標有:
- 指令(C0 Coverage):JaCoCo計數的最小單元是單一的Java字節碼指令。指令覆蓋率提供了關于字節碼執行數量、未執行數量的信息。
- 分支(C1 Coverage):對所有的
if
和switch
語句計算分支覆蓋率。統計在方法中分支執行數量、未執行數量的信息。但要注意,異常處理不在此計算范圍內。 - 圈復雜度(Cyclomatic Complexity):對非抽象方法計算圈復雜度,并匯總類、包和組的(圈)復雜度。這個值可以做為單元測試用例是否完全覆蓋的參考。
- 行(Lines):一行可能包含一條或多條指令,如果至少有一條指令被執行了,那么該行就算作是被執行了。
- 方法(Methods):每個非抽象方法至少包含一條指令。如果至少有一條指令被執行了,那么該方法就算作是被執行了。
- 類(Classes):如果類中至少有一個方法被執行了,那么該類就算作是被執行了。
注:個人認為,最需要關注的指標是行(Lines)和分支(C1 Coverage),其次是方法(Methods)和類(Classes),指令(C0 Coverage)和圈復雜度(Cyclomatic Complexity)可以不用關注,因為跟行(Lines)和分支(C1 Coverage)其實是差不多的,只不過多了一種參考維度。
查看單元測試覆蓋率
在IntelliJ IDEA中已經內置了JaCoCo插件,因此研發可以在本機運行單元測試來查看覆蓋率:
1、點擊IDE右上側的"Edit Configurations...":
2、在"Choose coverage runner"中選擇JaCoCo:
?
3、點擊"Run ... with Coverage"運行:
?
?4、運行完成后會展示分支(C1 Coverage)、行(Lines)、方法(Methods)、類(Classes)這四個指標:
?5、點擊"Generate Coverage Report"可以生成一份html版的所有指標的報告:
?
JaCoCo與持續集成
1、需要在項目的<plugins>
中加入JaCoCo插件:
<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.5</version><executions><execution><id>default-prepare-agent</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>default-report</id><goals><goal>report</goal></goals></execution></executions>
</plugin>
目前發現如果項目中不加以上配置,而是在Jenkinsfile中
?以命令的方式去應用JaCoCo,會導致不能生成jacoco.exec
,進而無法運行覆蓋率測試。
2、在Jenkinsfile中加入
?
exclusionPattern: '**/controller/*.class', sourceExclusionPattern: '**/controller/*.java'
可以過濾掉controller層的檢測。因為目前我們的單元測試主要是針對service層的,如果把controller層的類引入進來,會使單元測試覆蓋率的值變低。
3、可以在Jenkins(http://${ip}:${port}/job/${your_project}/lastBuild/jacoco/)中查看生成的單元測試覆蓋率報告:
?
該報告與IntelliJ IDEA中的報告都是JaCoCo原生的,是準確的。
目前發現SonarQube中的報告一是不準,二是指標不全,建議不要查看SonarQube的報告。
題外話
覆蓋率作為衡量單元測試質量的唯一標準是不合理的。比如下面這個例子:
public double cal(double a, double b) {if (b != 0) {return a / b;}
}
僅一個測試用例就可以做到100%的覆蓋率,比如cal(10.0, 2.0),但并不代表測試足夠全面了,還需要考慮當除數等于0的情況下,代碼執行是否符合預期。
---------------------
作者:谷隱凡二
來源:CSDN
原文:https://blog.csdn.net/m0_37570494/article/details/125440949
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件