最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用JaCoCo分析java單元測(cè)試覆蓋率

 更新時(shí)間:2019年06月12日 08:48:44   作者:王 群峰  
在做單元測(cè)試時(shí),代碼覆蓋率常常被拿來作為衡量測(cè)試好壞的指標(biāo),甚至,用代碼覆蓋率來考核測(cè)試任務(wù)完成情況,比如,代碼覆蓋率必須達(dá)到80%或 90%。于是乎,測(cè)試人員費(fèi)盡心思設(shè)計(jì)案例覆蓋代碼。下面我們來學(xué)習(xí)一下吧

前言

隨著敏捷開發(fā)的流行,編寫單元測(cè)試已經(jīng)成為業(yè)界共識(shí)。但如何來衡量單元測(cè)試的質(zhì)量呢?有些管理者片面追求單元測(cè)試的數(shù)量,導(dǎo)致底下的開發(fā)人員投機(jī)取巧,編寫出大量的重復(fù)測(cè)試,數(shù)量上去了,質(zhì)量卻依然原地踏步。相比單純追求單元測(cè)試的數(shù)量,分析單元測(cè)試的代碼覆蓋率是一種更為可行的方式。

JaCoCo(Java Code Coverage)就是一種分析單元測(cè)試覆蓋率的工具,使用它運(yùn)行單元測(cè)試后,可以給出代碼中哪些部分被單元測(cè)試測(cè)到,哪些部分沒有沒測(cè)到,并且給出整個(gè)項(xiàng)目的單元測(cè)試覆蓋情況百分比,看上去一目了然。

EclEmma 是基于 JaCoCo 的一個(gè) Eclipse 插件,開發(fā)人員可以方便的和其交互。因此,本文先從 EclEmma 入手,給讀者一個(gè)直觀的體驗(yàn)。

使用 EclEmma 在 Eclipse 中查看單元測(cè)試覆蓋率

EclEmma 是基于 JaCoCo 的 Eclipse 插件,使用它,開發(fā)人員可以直觀地看到單元測(cè)試的覆蓋情況。

安裝 EclEmma

打開 Eclipse 的軟件市場(chǎng),在其中搜索 EclEmma,找到后完成安裝,如下圖所示:


圖 1. 安裝 EclEmma

安裝完成后,Eclipse 的工具條里會(huì)多出下面這樣一個(gè)圖標(biāo):

圖 2. Coverage 圖標(biāo)

分析單元測(cè)試覆蓋率

成功安裝 EclEmma 后,就可以試著用它來分析項(xiàng)目的單元測(cè)試覆蓋率了。為了方便演示,我們使用 Eclipse 創(chuàng)建了一個(gè)標(biāo)準(zhǔn) Java 工程。其中包含一個(gè)數(shù)學(xué)工具類,用來計(jì)算三個(gè)數(shù)中的最大值,代碼如下:

清單 1. 數(shù)學(xué)工具類

package com.dw.math;
public class MathUtil {
public static int max(int a, int b, int c){
if(a > b){
if(a > c){
return a;
}else{
return c;
}
}else{
if(b > c){
return b;
}else{
return c;
}
}
}
}

可以看到,這里的算法稍微有點(diǎn)復(fù)雜,使用到了多個(gè)條件判斷分支,因此,特別適合為其編寫單元測(cè)試。第一個(gè)版本的單元測(cè)試如下:

清單 2. 第一個(gè)版本的單元測(cè)試

package com.dw.math;
import static org.junit.Assert.*;
import org.junit.Test;
public class MathUtilTest {
@Test
public void test_max_1_2_3() {
assertEquals(3, MathUtil.max(1, 2, 3));
}
}

試著運(yùn)行一下單元測(cè)試覆蓋率分析工具:40.0%!似乎不太理想。展開分析報(bào)告,雙擊后在編輯器里可以看到覆蓋情況被不同的顏色標(biāo)識(shí)出來,其中綠顏色表示代碼被單元測(cè)試覆蓋到,黃色表示部分覆蓋,紅色則表示完全沒有覆蓋到,如下圖所示:


圖 3. 單元測(cè)試覆蓋率報(bào)告

讓我們嘗試多加一些單元測(cè)試,來改善這種情況,請(qǐng)看下面第二個(gè)版本的單元測(cè)試:

清單 3. 第二個(gè)版本的單元測(cè)試

package com.dw.math;
import static org.junit.Assert.*;
import org.junit.Test;
public class MathUtilTest {
@Test
public void test_max_1_2_3() {
assertEquals(3, MathUtil.max(1, 2, 3));
}
@Test
public void test_max_10_20_30() {
assertEquals(30, MathUtil.max(10, 20, 30));
}
@Test
public void test_max_100_200_300() {
assertEquals(300, MathUtil.max(100, 200, 300));
}
}

測(cè)試覆蓋率還是 40.0%!雖然我們額外再加了兩個(gè)測(cè)試,但覆蓋率沒有半點(diǎn)提升,這些單元測(cè)試其實(shí)是重復(fù)的,它們?cè)谥貜?fù)測(cè)試同一段代碼。如果單純追求單元測(cè)試的數(shù)量,那么這無疑會(huì)給管理者造成錯(cuò)覺,他們覺得單元測(cè)試的數(shù)量增加了,軟件的質(zhì)量更有保證了;而對(duì)于那些喜歡偷懶的程序員,也蒙混過關(guān),但卻給軟件質(zhì)量埋下了隱患。讓我們刪掉這些重復(fù)的單元測(cè)試,重新思考一下怎么測(cè)試這個(gè)方法。

首先我們要測(cè)試正常情況,這其中又包含 3 種情況:第一個(gè)參數(shù)最大,第二個(gè)參數(shù)最大,以及最后一個(gè)參數(shù)最大。然后我們還需測(cè)試幾種特殊情況,比如三個(gè)參數(shù)相同,三個(gè)參數(shù)中,其中兩個(gè)相同。讓我們照此思路重新編寫單元測(cè)試:

清單 4. 第三個(gè)版本的單元測(cè)試

package com.dw.math;
import static org.junit.Assert.*;
import org.junit.Test;
public class MathUtilTest {
@Test
public void test_max_1_2_3() {
assertEquals(3, MathUtil.max(1, 2, 3));
}
@Test
public void test_max_1_3_2() {
assertEquals(3, MathUtil.max(1, 3, 2));
}
@Test
public void test_max_3_2_1() {
assertEquals(3, MathUtil.max(3, 2, 1));
}
@Test
public void test_max_0_0_0(){
assertEquals(0, MathUtil.max(0, 0, 0));
}
@Test
public void test_max_0_1_0(){
assertEquals(1, MathUtil.max(0, 1, 0));
}
}

再次運(yùn)行單元測(cè)試分析工具:75.0%!這次比以前有了很大提升,但是結(jié)果還不能令人滿意,打開分析報(bào)告可以看到,有一個(gè)分支還是沒有覆蓋到,如圖所示:


圖 4. 單元測(cè)試覆蓋率報(bào)告

閱讀代碼可以看出,這種情況是指第一個(gè)參數(shù)大于第二個(gè)參數(shù),卻小于第三個(gè)參數(shù),因此我們?cè)僭黾右粋€(gè)單元測(cè)試:

清單 5. 再增加一個(gè)單元測(cè)試

@Test
public void test_max_2_1_3() {
assertEquals(3, MathUtil.max(2, 1, 3));
}

再運(yùn)行一遍單元測(cè)試分析工具:100.0%!終于我們的單元測(cè)試達(dá)到了全覆蓋,這樣我們對(duì)自己開發(fā)的代碼更有信心了。當(dāng)然,我們?cè)谶@里并不是為了單純的追求這個(gè)數(shù)字,在增加單元測(cè)試覆蓋率的誘導(dǎo)下,我們重新理清了測(cè)試的步驟,寫出了更有意義、更全面的單元測(cè)試。而且根據(jù)單元測(cè)試分析工具給的反饋,我們還發(fā)現(xiàn)了先前沒有想到的情形。因此,單元測(cè)試的覆蓋率并不只是一個(gè)為了取悅管理者的數(shù)據(jù),它實(shí)實(shí)在在地幫助我們改善了代碼的質(zhì)量,增加了我們對(duì)所編寫代碼的信心。

給管理者的單元測(cè)試覆蓋率報(bào)告

管理者天生喜歡閱讀報(bào)告。他們不會(huì)屈尊坐在你的辦公桌前,讓你向他展示 Eclipse 中這一片花花綠綠的東西。而且這份報(bào)告對(duì)他們至關(guān)重要,他們需要用它向上級(jí)匯報(bào);年底回顧時(shí),他們也可以興奮地宣稱產(chǎn)品的單元測(cè)試覆蓋率增加了多少。作為一名開發(fā)人員,我們很大一部分工作量就在于滿足管理者的這種需求。因此,本節(jié)我們討論如何將 JaCoCo 集成到 Ant 腳本中,生成漂亮的單元測(cè)試覆蓋率報(bào)告。

準(zhǔn)備工作

在集成 JaCoCo 前,必須先確保你的 Java 工程有一個(gè)可執(zhí)行的 Ant 構(gòu)建腳本。一個(gè)簡(jiǎn)單的 Ant 構(gòu)建腳本一般會(huì)執(zhí)行如下任務(wù):編譯(包括編譯工程代碼和測(cè)試代碼)、打包和執(zhí)行單元測(cè)試。下面是本文示例 Java 項(xiàng)目所用的 Ant 構(gòu)建腳本,讀者可結(jié)合自己的項(xiàng)目及文件路徑,在此基礎(chǔ)之上進(jìn)行修改。

清單 6. build.xml

<project name="math" basedir="." default="junit">
<!--預(yù)定義的屬性和 classpath -->
<property name="src.dir" value="src" />
<property name="test.dir" value="test" />
<property name="build.dir" value="build" />
<property name="classes.dir" value="${build.dir}/classes" />
<property name="tests.dir" value="${build.dir}/tests" />
<property name="jar.dir" value="${build.dir}/jar" />
<property name="lib.dir" value="lib" />
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar" />
</path>
<!--清除上次構(gòu)建 -->
<target name="clean">
<delete dir="${build.dir}" />
</target>
<!--編譯代碼,包括單元測(cè)試 -->
<target name="compile" depends="clean">
<mkdir dir="${classes.dir}" />
<mkdir dir="${tests.dir}" />
<javac srcdir="${src.dir}" destdir="${classes.dir}" />
<javac srcdir="${test.dir}" destdir="${tests.dir}">
<classpath>
<path refid="classpath" />
<path location="${classes.dir}" />
</classpath>
</javac>
</target>
<!--打包 -->
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}" />
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
</jar>
</target>
<!--運(yùn)行單元測(cè)試 -->
<target name="junit" depends="jar">
<junit printsummary="yes">
<classpath>
<path refid="classpath"/>
<path location="${classes.dir}" />
<path location="${tests.dir}" />
</classpath>
<batchtest fork="yes">
<fileset dir="${test.dir}" includes="**/*Test.java"/>
</batchtest>
</junit>
</target>
</project>

集成 JaCoCo

首先需要從 然后就是使用 JaCoCo 官網(wǎng)下載 需要的版本,然后將下載得到的壓縮文件解壓,將其中的 jacocoant.jar 拷貝至 Java 工程下存放第三方 jar 包的目錄,在示例工程里,我有一個(gè)和 src 平級(jí)的 lib 目錄,jacocoant.jar 就放到了這個(gè)目錄底下,讀者可根據(jù)自己的項(xiàng)目組織結(jié)構(gòu)做相應(yīng)調(diào)整。然后我們需要在 Ant 構(gòu)建腳本中定義新的任務(wù):

清單 7. 定義新的構(gòu)建任務(wù)

<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath refid="classpath" />
</taskdef>

現(xiàn)在就可以在 Ant 構(gòu)建腳本中使用 JaCoCo 了。需要注意的是,為了避免命名沖突,需要給 Ant 構(gòu)建腳本加入新的 XML 命名空間:

清單 8. 加入新的 JaCoCo 命名空間

<project name="math" basedir="." xmlns:jacoco="antlib:org.jacoco.ant" default="junit">

我們主要使用 JaCoCo 的兩個(gè)任務(wù):首先是jacoco:coverage,用來生成單元測(cè)試覆蓋率數(shù)據(jù),這是一個(gè)二進(jìn)制文件,為了生成從該文件生成報(bào)表,我們還要調(diào)用另外一個(gè)任務(wù)jacoco:report,它的輸入為jacoco:coverage生成的二進(jìn)制文件,輸出報(bào)表。報(bào)表有多種格式可選,可以是 HTML、XML、CSV 等。具體的腳本如下:

清單 9. 使用 JaCoCo 生成測(cè)試覆蓋率和報(bào)表

<jacoco:coverage destfile="${build.dir}/jacoco.exec">
<junit fork="true" forkmode="once" printsummary="yes">
<classpath>
<path refid="classpath" />
<path location="${classes.dir}" />
<path location="${tests.dir}" />
</classpath>
<batchtest fork="yes">
<fileset dir="${test.dir}" includes="**/*Test.java"/>
</batchtest>
</junit>
</jacoco:coverage>
<jacoco:report>
<executiondata>
<file file="${build.dir}/jacoco.exec"/>
</executiondata>
<structure name="dw demo">
<classfiles>
<fileset dir="${classes.dir}"/>
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="${src.dir}"/>
</sourcefiles>
</structure>
<html destdir="${build.dir}"/>
</jacoco:report>

JaCoCo 的任務(wù)定義非常清晰,在這里略作說明。首先需要將原來的junit任務(wù)嵌入jacoco:coverage,而且需要指定fork="true",代表單元測(cè)試需要另起一個(gè) JVM 執(zhí)行,否則 JaCoCo 就會(huì)執(zhí)行失敗。destfile="${build.dir}/jacoco.exec"指定生成的測(cè)試覆蓋率文件輸出到什么地方,后面生成報(bào)告的時(shí)候需要輸入該文件的地址。

然后就是使用 jacoco:report 生成報(bào)告,指定前面任務(wù)生成的單元測(cè)試覆蓋率文件、編譯好的類文件以及源代碼,最后選擇一種格式,這里使用 html,生成報(bào)告。打開報(bào)告的存放路徑,就可以看到如下所示的單元測(cè)試覆蓋率報(bào)告:

圖 5. HTML 版的單元測(cè)試覆蓋率報(bào)告

和同類產(chǎn)品比較

市面上流行的單元測(cè)試覆蓋率工具還有 Clover 和 Cobertura。和它們相比,JaCoCo 有如下優(yōu)勢(shì):

JaCoCo 擁有友好的授權(quán)形式。JaCoCo 使用了 Eclipse Public License,方便個(gè)人用戶和商業(yè)用戶使用。而 Clover 對(duì)于商業(yè)用戶是收費(fèi)的。

JaCoCo 被良好地集成進(jìn)各種工具中。在 Java 社區(qū)里,很多流行的工具都可以集成 JaCoCo,比如 SonarQube、Jenkins、Netbeans、Eclipse、IntelliJ IDEA、Gradle 等。

JaCoCo 社區(qū)非常活躍,它是目前唯一支持 Java 8 的單元測(cè)試覆蓋率工具。而且關(guān)于 JaCoCo 的文檔相對(duì)較多,降低了學(xué)習(xí)門檻。

結(jié)束語

本文為大家介紹了如何使用 JaCoCo 分析項(xiàng)目的單元測(cè)試覆蓋率,文章先從 JaCoCo 的 Eclipse 插件 EclEmma 開始,直觀地介紹了如何一步步提高單元測(cè)試質(zhì)量,最終達(dá)到對(duì)代碼的全覆蓋;然后為大家介紹了如何將 JaCoCo 集成到 Ant 構(gòu)建腳本中,生成漂亮的單元測(cè)試覆蓋率報(bào)告。但是使用 JaCoCo 只是第一步,重要的是開發(fā)人員能夠根據(jù)工具所給的反饋,不斷改進(jìn)自己的單元測(cè)試,寫出高質(zhì)量的代碼。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Boot使用FastJson解析JSON數(shù)據(jù)的方法

    Spring Boot使用FastJson解析JSON數(shù)據(jù)的方法

    本篇文章主要介紹了Spring Boot使用FastJson解析JSON數(shù)據(jù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • 淺談spring中isolation和propagation的用法

    淺談spring中isolation和propagation的用法

    這篇文章主要介紹了淺談spring中isolation 和propagation的用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 如何把spring boot項(xiàng)目部署到tomcat容器中

    如何把spring boot項(xiàng)目部署到tomcat容器中

    本文給大家分享如何把spring boot項(xiàng)目部署到tomcat容器中,本文給大家介紹的非常詳細(xì),需要的朋友參考下
    2017-04-04
  • IntelliJ IDEA2021.1 配置大全(超詳細(xì)教程)

    IntelliJ IDEA2021.1 配置大全(超詳細(xì)教程)

    這篇文章主要介紹了IntelliJ IDEA2021.1 配置大全(超詳細(xì)教程),需要的朋友可以參考下
    2021-04-04
  • java使用http實(shí)現(xiàn)文件下載學(xué)習(xí)示例

    java使用http實(shí)現(xiàn)文件下載學(xué)習(xí)示例

    這篇文章主要介紹了java使用http實(shí)現(xiàn)文件下載學(xué)習(xí)示例,需要的朋友可以參考下
    2014-04-04
  • Spring中的@Transactional事務(wù)失效場(chǎng)景解讀

    Spring中的@Transactional事務(wù)失效場(chǎng)景解讀

    這篇文章主要介紹了Spring中的@Transactional事務(wù)失效場(chǎng)景解讀,如果Transactional注解應(yīng)用在非public 修飾的方法上,Transactional將會(huì)失效此方法會(huì)檢查目標(biāo)方法的修飾符是否為 public,不是 public則不會(huì)獲取@Transactional 的屬性配置信息,需要的朋友可以參考下
    2023-12-12
  • Spring Dao層@Repository與@Mapper的使用

    Spring Dao層@Repository與@Mapper的使用

    這篇文章主要介紹了Spring Dao層@Repository與@Mapper的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 如何在java中正確使用注釋

    如何在java中正確使用注釋

    在編寫程序時(shí),經(jīng)常需要添加一些注釋,用以描述某段代碼的作用。 一般來說,對(duì)于一份規(guī)范的程序源代碼而言,注釋應(yīng)該占到源代碼的 1/3 以上。下面我們來詳細(xì)了解一下吧
    2019-06-06
  • Java并發(fā)編程之線程中斷

    Java并發(fā)編程之線程中斷

    這篇文章主要介紹了Java并發(fā)編程線程中斷,java線程中斷是一種線程間的協(xié)作模式,通過設(shè)置線程的中斷標(biāo)志并不能直接終止該線程的運(yùn)行,而是被中斷的線程根據(jù)中斷狀態(tài)自行處理,需要的朋友可以參考一下
    2021-09-09
  • Java?HashMap中除了死循環(huán)之外的那些問題

    Java?HashMap中除了死循環(huán)之外的那些問題

    這篇文章主要介紹了Java?HashMap中除了死循環(huán)之外的那些問題,這些問題大致可以分為兩類,程序問題和業(yè)務(wù)問題,下面文章我們一個(gè)一個(gè)來看,需要的小伙伴可以參考一下
    2022-05-05

最新評(píng)論

贺兰县| 应城市| 大英县| 临漳县| 翁源县| 宁德市| 衡南县| 道孚县| 长春市| 兴义市| 炉霍县| 岳阳县| 和林格尔县| 琼中| 甘肃省| 七台河市| 繁昌县| 万全县| 海晏县| 孝昌县| 岢岚县| 报价| 得荣县| 磴口县| 历史| 平塘县| 富阳市| 农安县| 丰都县| 井冈山市| 繁峙县| 尼木县| 宜丰县| 珲春市| 江城| 广汉市| 大兴区| 辉县市| 兴义市| 温宿县| 集安市|