1. 程式人生 > >JaCoCo 程式碼覆蓋率測試工具整合

JaCoCo 程式碼覆蓋率測試工具整合

對於JaCoCo的介紹就不多說了,網上多的是介紹,不行也可以去官網檢視一下就行了。相信大家也很不喜歡這類部落格——開頭不寫怎麼解決問題,而是給你講背景、講歷史,講了一堆。終於到解決問題的方法了,發現還不適用自己的情況。真是XXXX了。

所以,我先給出JaCoCo的官網,大家可以自行檢視,相信看到官方給出的例子後,會覺得豁然開朗。

官網(包括下載資源):https://www.jacoco.org/

1.概要

首先,這篇部落格主要是講使用JaCoCo(主角) + Ant(編譯以及測試報告生成) + Tomcat(部署專案的容器) + Linux(執行環境)整合後,啟動Tomcat,對專案進行用例測試後,生成程式碼覆蓋率測試報告的過程。

2.所需工具

各種環境(jdk、ant、tomcat等)就不多說了,這裡主要使用到兩個jar包:jacocoagent.jar + jacocoant.jar 與兩個配置檔案。

3.修改點

A. 下載上述兩個jar包到linux伺服器,我是放在/home/lys/jacoco/下面。
B. 在Tomcat的catalina.sh中加入配置:

JAVA_OPTS="-javaagent:/home/lys/jacoco/jacocoagent.jar=output=tcpserver,address=localhost"

C.建立build.xml,如下:

<?xml version="1.0" ?>
<project name="louys" xmlns:jacoco="antlib:org.jacoco.ant" default="jacoco">
    <!--Jacoco的安裝路徑-->
  <property name="jacocoantPath" value="/home/lys/jacoco/jacocoant.jar"/>
  <!--最終生成.exec檔案的路徑,裡面有覆蓋率資料,Jacoco就是根據這個檔案生成最終的報告的-->
  <property name="jacocoexecPath" value="/home/lys/jacoco/report/jacoco.exec"/>
    <!--生成覆蓋率報告的路徑-->
  <property name="reportfolderPath" value="/lys/tomcat8.5.28/webapps/jacoco/"/>
  <!--服務的ip地址-->
  <property name="server_ip" value="localhost"/>
  <!--前面配置的服務開啟的埠,要跟jacocoagent一樣-->
  <property name="server_port" value="6300"/>
  <!--原始碼路徑-->
  <property name="checkOrderSrcpath" value="/lys/trunk/tyrcb/src/com" />
  <!--.class檔案路徑-->
  <property name="checkOrderClasspath" value="/lys/tomcat8.5.28/webapps/tyrcb/WEB-INF/classes/com" />
  <!--讓ant知道去哪兒找Jacoco-->
  <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
      <classpath path="${jacocoantPath}" />
  </taskdef>
  <!--dump任務:
      根據前面配置的ip地址,和埠號,
      訪問目標tomcat服務,並生成.exec檔案。-->
  <target name="dump">
      <jacoco:dump address="${server_ip}" reset="false" destfile="${jacocoexecPath}" port="${server_port}" append="true"/>
  </target>

  <!--jacoco任務:
      根據前面配置的原始碼路徑和.class檔案路徑,
      根據dump後,生成的.exec檔案,生成最終的html覆蓋率報告。-->
  <target name="report">
      <delete dir="${reportfolderPath}" />
      <mkdir dir="${reportfolderPath}" />

      <jacoco:report>
          <executiondata>
              <file file="${jacocoexecPath}" />
          </executiondata>

          <structure name="JaCoCo Report">
              <group name="Check Order related">          
                  <classfiles>
                      <fileset dir="${checkOrderClasspath}" />
                  </classfiles>
                  <sourcefiles encoding="utf-8">
                      <fileset dir="${checkOrderSrcpath}" />
                  </sourcefiles>
              </group>
          </structure>
          <html destdir="${reportfolderPath}" encoding="utf-8" />        
      </jacoco:report>
  </target>
</project>

D.重啟Tomcat後,就可以盡情你的測試用例了。
E.生成報告:
在你新建build.xml的目錄下執行命令:

	ant dump
	ant report

最後就可以在配置檔案中所配置的目錄中生成測試報告了。
這裡寫圖片描述

-----------------------------------------我------是------分------割------線 ----------------------------------------
簡單說一下配置:
jacocoagent.jar看包名有個關鍵詞“agent”代理!代理JVM進行JVM的監控與記錄程式碼覆蓋。
jacocoant.jar是通過ant命令進行報告生成使用。

catalina.sh配置引數:

JAVA_OPTS="-javaagent:/home/lys/jacoco/jacocoagent.jar=output=tcpserver,address=localhost"

首先指明代理是jacocoagent.jar,需要配置你的jar目錄。output是覆蓋資料(coverage data)輸出的方式,有三個可配置的值:
**1.file:**當虛擬機器關閉時,會把資料寫入配置的檔案中。所以該配置是不支援動態分析的,即服務必須停掉才能看到測試結果。
**2.tcpserver:**服務啟動後,監聽配置的address+port(這裡沒有配置,使用預設6300埠)TCP埠,即被當做伺服器(tcpserver)
3.tcpclient:服務啟動時會連線配置的埠號,此時可以理解為是客戶端(tcpclient)
4.none不做任何輸出。
這樣就容易理解了。
還剩下
build.xml
,其實該配置檔案裡面已經描述的很清楚了。
僅說明一下報告的輸出路徑,我是直接輸出到tomcat的weapps裡面了,這樣可以直接在瀏覽器中進行訪問檢視。

總結

其實,剛開始做這個任務的時候,上級是讓使用Emma的,當時對這些測試工具完全不知道。查了一下這貨的jarbk自從2010年就沒有做維護了。等我自己配置的差不多了,啟動時報錯:

java.lang.ClassFormatError: Illegal local variable table length 403 in method ....

發現Emma不再支援jdk1.7或者說不能完美支援。這才發現Emma團隊已經放棄Emma的維護了,重新開啟了JaCoCo(Java Code Coverage)專案。所以建議大家使用最新的JaCoCo,如果遇到什麼問題或有什麼獨到的見解,希望能與我分享討論。謝謝!
-----------------------------------------我------是------分------割------線 ----------------------------------------
遇到的bug:
只提示:

BUILD FAILED
/usr/local/jacoco/build.xml:35: Error while creating report

而35行是jacoco:report標籤那一行。
問題原因:
應該是原始碼與編譯的class檔案不一致導致,重新編譯即可。