1. 程式人生 > >AVA 程式碼覆蓋率工具 JaCoCo-實踐篇

AVA 程式碼覆蓋率工具 JaCoCo-實踐篇

一、覆蓋率專案中使用介紹

本節開始詳細介紹下專案中的JaCoCo實戰經驗。

下圖是覆蓋率在實際在專案中的主要實施點:


分別詳細介紹下:

1.1 確定插樁方式

Android專案只能使用JaCoCo的離線插樁方式。

為什麼?主要是因為Android覆蓋率的特殊性:

一般執行在伺服器java程式的插樁可以在載入class檔案進行,運用java Agent的機制,可以理解成"實時插樁"。JaCoCo提供了自己的Agent,完成插樁的同時,還提供了豐富的dump輸出機制,如File,Tcp Server,Tcp Client。覆蓋率資訊可以通過檔案或是Tcp的形式輸出。這樣外部程式可很方便隨時拿到被測程式的覆蓋率。

但是Android系統破壞了JaCoCo這種便利性,原因有兩個:

(1)Android虛擬機器不同與伺服器上的JVM,它所支援的位元組碼必須經過處理支援Android Dalvik等專用虛擬機器,所以插樁必須在處理之前完成,即離線插樁模式。

(2)Android虛擬機器沒有配置JVM 配置項的機制,所以應用啟動時沒有機會直接配置dump輸出方式。

1.2 分析專案打包流程

專案目前還是已build方式打包,屬於Apache Ant方式。

插樁前先熟悉下專案build內容。

專案主要有幾個build檔案:

存放在根目錄下的build.xml檔案,這個是專案構建的組織檔案

  • ant目錄下的build_common.xml,這個是構建時target內容

  • ant目錄下的build_option.xml,定義的屬性檔案。

  • ant目錄下的build_plugins.xml,外掛檔案。

在插樁前,應該對專案構建過程做一個總體的熟悉,瞭解下每個target的作用,這樣才能確定不會影響各個插樁點,不會遺漏,否則會在打包的過程中出現各種各樣的問題。

1.3 程式碼插樁

裡面簡單介紹了其支援的task型別,包括:
Task coverage、Task agent、Task merge、Task report、Task instrument、Task dump

具體怎麼使用可以參考裡面的例子。

各Task實際呼叫的類,看一下JaCoCo的antlib.xml就知道了



專案根據自己的情況暫時只用到了Task instrument,其他dump、merge、report是通過其他方式使用的,具體後面有說明。

為什麼沒有用到dump、merge、report?

這種情況比較適合一個帶有自動化測試的構建:打包、自動化測試、dump、merge、report。

專案部分功能需要手工測試,因此,上述幾個步驟需要後面再另外處理。
OK,簡單瞭解了JaCoCo的ant方式,下面開始對專案進行插樁打包。

專案的插樁修改步驟:

主要修改了build-common.xml和build-plugins.xml兩個檔案: 
以下是build-common.xml的修改,build-plugins.xml的修改就不累述了,原理一樣。

(1)檔案開頭的名稱空間加入
xmlns:JaCoCo="antlib:org.JaCoCo.ant"

(2)引入 JaCoCo 的 jar 和相關定義

`

`

(3)重新定義 class 檔案生成路徑
<property name="classes_instr" value="${temp}/classes_instr" />

(4)修改compile編譯節點,插樁注入 
`

(5)修改打包package節點,主要是指定 JaCoCo 編譯後的類路徑 
<jar basedir="${classes_instr}" destfile="temp.jar" />

(6)修改混淆obfuscate節點,增加混淆所需要的

<arg value="-libraryjars ${lib}/JaCoCoagent.jar" />
將delete、mkdir、unzip操作指向classes_instr

(7)修改分包splitClasses節點,指向classes_instr

<arg value="${classes_instr}" />

(8)修改熱補丁注入injectPatchCode節點,指向classes_instr

<YYBInjectPatchCode inputDir="${classes_instr}"

(9)修改dex節點,指向classes_instr

 <arg path="${classes_instr}"

(10)修改dex-sub節點,指向classes-instr,同時在excludes中加入jacocoagent.jar
<arg path="${classes_instr}"
fileset dir="${lib}" excludes="tmdownloadsdk.jar,tmapkpatch.jar,.....,jacocoagent.jar" />

將上面的操作,做成全自動修改,打包成autoinsertxml.jar,放到打包伺服器後臺指定的目錄下。

Jar包裡詳細內容如下:

  • 修改AndroidManifest.xml檔案,增加一個覆蓋率生成服務(這個後續的覆蓋率生成工具用到)

  • 修改build_common.xml檔案,實現主幹程式碼插樁修改

  • 修改build_plugins.xml檔案,實現外掛程式碼的插樁修改

1.4 打覆蓋率包

Jekin上已經配置好了jacoco_package任務


按描述輸入後,直接點選開始構建就行了,打包後的結果:

包括:未插樁的主幹類檔案、未插樁的外掛類檔案、三種方式的覆蓋率包、mapping檔案等等。


jacoco_package任務裡面的具體內容做了什麼?一起看看吧。

(1)配置了引數化構建的內容,如


(2)配置了構建描述

(3)配置了專案ID和建立精準入庫任務

(4)Check out程式碼

(5)插樁

(6)編譯打包

(7)備份class

(8)儲存存檔檔案

1.5 執行測試,收集覆蓋率結果檔案

覆蓋率檔案生成現在支援兩種方式:

1、覆蓋率生成工具:一個專門用來生成覆蓋率檔案的APK。

2、定時器的方式:在專案裡新建一個定時器JOB任務,定時去收集生成覆蓋率檔案。

目前我們主要用第一種方式,下面都詳細介紹下。

1.5.1 AndroidManifest檔案的修改

增加了兩個服務:

ResultManagerService:執行生成覆蓋率資料。

ReSetManagerService:執行清理覆蓋率資料。

1.5.2 生成覆蓋率的apk工具和jacoco-cov-sdk.jar包

工具總共有三個功能:

(1)生成ec檔案

(2)啟動定時器,按指定的時間生成ec檔案

(3)清除覆蓋率,會清除記憶體記錄並且會刪除sd卡存在的ec檔案

工具原理:

(1)生成ec檔案

當觸發這個操作的時候,其實會去啟動專案中我們新增的ResultManagerService服務,它具體做的事情就是dump覆蓋率資料,如下:在ResultManagerService啟動時呼叫jacoco-cov-sdk.jar包中的ResultManager.dumpCoverageJacoco(true,filename)方法:

其主要功能就是反射呼叫jaCoCo的dump方法,來生成覆蓋率資料,核心程式碼如下:
`//Get AgentOptions class
Class classAgentOptions = Class.forName("org.jacoco.agent.rt.internal_b0d6a23.core.runtime.AgentOptions");

//Get setDestfile method in AgentOptions class
Method methodSetDestFile = classAgentOptions.getMethod("setDestfile",String.class);

//Get FileOutput class
Class classFileOutput = Class.forName("org.jacoco.agent.rt.internal_b0d6a23.output.FileOutput");

//Get field "File destFile" in FileOutput class

Field fieldFile = classFileOutput.getDeclaredField("destFile");

fieldFile.setAccessible(true);

//Get Agent singleton by getAgent method in RT class
Class<?> RT = Class.forName("org.jacoco.agent.rt.RT");

Method methodGetAgent = RT.getMethod("getAgent");

Object objAgent = methodGetAgent.invoke(null);

//Get Agent Class

Class classAgent = Class.forName("org.jacoco.agent.rt.internal_b0d6a23.Agent");

//Get field "AgentOptions options" and "FileOutput output" in Agent Class

Field fieldOptions = classAgent.getDeclaredField("options");

Field fieldOutput = classAgent.getDeclaredField("output");

fieldOptions.setAccessible(true);

fieldOutput.setAccessible(true);

//Get options/output object referenced by Agent singleton

Object objOptions = fieldOptions.get(objAgent);

Object objOutput = fieldOutput.get(objAgent);

//change destFile attribute in options object by setDestfile method

methodSetDestFile.invoke(objOptions,absFilePath);

//change field "File destFile" in output object

File destFile = new File(absFilePath).getAbsoluteFile();

fieldFile.set(objOutput,destFile);

//dump

Method methodDump = classAgent.getMethod

("dump",boolean.class);

methodDump.invoke(objAgent,reset);`

(2)啟動定時器,按指定的時間生成ec檔案

這個就是一個Timer,按指定的時間週期去dump覆蓋率資料

(3)清除覆蓋率,會清除記憶體記錄並且會刪除sd卡存在的ec檔案

當觸發這個操作的時候,其實會去啟動專案中我們新增的ReSetManagerService服務,它具體做的事情就是reset覆蓋率資料,如下:

在ReSetManagerService啟動時呼叫jacoco-cov-sdk.jar包中的ResultManager.reSetCoverageJacoco()方法:

其主要功能就是反射呼叫jaCoCo的reset方法,來清理覆蓋率資料,核心程式碼如下:

Class<?> RT = Class.forName("org.jacoco.agent.rt.RT");
Method methodGetAgent = RT.getMethod("getAgent");
Object objAgent = methodGetAgent.invoke(null); 
//Get Agent Class
Class classAgent = Class.forName("org.jacoco.agent.rt.internal_b0d6a23.Agent");
//reset
Method methodDump = classAgent.getMethod("reset");
methodDump.invoke(objAgent,null);

1.6 生成覆蓋率報告

通過編寫report的build方式來生成報告結果。

這裡寫了一個生成報告的模版,使用者只需要copy到 本機上,按下面的說明修改、生成報告即可,下面詳細介紹下這個模版的使用方法。

1.6.1 模版目錄介紹

(1)libs存放幾個jar包,分別為ant-contrib.jar、jacocoagent.jar、jacocoant.jar;

(2)result_xml目錄會自動生成xml格式的報告;

(3)src目錄是存放原始碼的,如果沒這個,生成的覆蓋率只有資料,看不到程式碼實際覆蓋的內容;

(4)build檔案,ant的執行內容,build_group或者是build_only的copy。

檔案內容如下:

<project xmlns:jacoco="antlib:org.jacoco.ant" name="Example Ant Build with JaCoCo Offline Instrumentation" default="build_all">

說明:指定xmlns:jacoco、name和預設的執行task

<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="./libs/ant-contrib.jar"/>
</classpath>
</taskdef>

說明:引入了ant的jar包,放入到classpath中
<import file="build_property.xml"/>

說明:import了屬性檔案

<property name="result.dir" location="."/>
<property name="src.dir" location="./src"/>
<property name="result.classes.dir" location="${result.dir}/classes/classes"/>
<property name="result.report.dir" location="${result.dir}/report"/>
<property name="result.report.xml" location="${result.dir}/result_xml"/>

說明:定義了一下屬性:原始碼路徑、類路徑、報告目錄、xml目錄

<!-- Step 1: Import JaCoCo Ant tasks -->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="./libs/jacocoant.jar"/>
</taskdef>

說明:引入jacocoant.jar,指定了ant的操作對映檔案

<target name="build_all">
<foreach list="${ec_list}" target="report" param="ec_name" delimiter=","/>
</target>

說明:build_all任務的內容,迴圈遍歷ec_list,作為report的輸入

`


/jacoco:merge
jacoco:report

<!--file file="${result.dir}/${ec_name}.ec"/-->







<!--fileset dir="${result.dir}/src/libs">



















/jacoco:report
`

說明:report任務的內容,指定merge、指定ec檔案、結果已YYB組顯示、指定classes檔案、指定src檔案列表、指定html、csv、xml屬性。
</project>

說明:這個build檔案需要根據實際的專案修改,修改一次以後基本不用變動。

(1)build_group檔案,指定組生成的build檔案,適合結果按組顯示。

(2)build_only檔案,沒組的概念。

(3)build_property檔案,存放的是ec列表檔名稱。

1.6.2 實際操作舉例

一、安裝Apache Ant

網上下載或直接copy其他人機器上的就OK,設定下環境變數ANT_HOME和把bin目錄放到path中,我用的是apache-ant-1.9.6-bin,有需要可以直接找我要。

二、取上面的模版目錄放到你本機上(PC),有需要可以直接找我要。

三、生成報告,按以下步驟操作

比如拿到測試結果的ec檔案有三個,分別是yyb1.ec、yyb2.ec、yyb3.ec

1、將覆蓋率打包結果中的classes.zip丟到模版根目錄中並解壓。

2、根據打包時的svn地址和版本號,取下原始碼放如到src目錄。

3、將ec檔案(yyb1.ec、yyb2.ec、yyb3.ec)全部丟到模版根目錄中

4、修改build_property檔案,名稱寫如到value中(去掉ec字尾的)

5、build檔案,如無路徑變化,基本不用修改
省電管理除了主幹程式碼,還有外掛部分,因此build檔案取的build_group,分別為

<group name="YYB">、<group name="plugin_power_save">

6、執行ant,report目錄就會生成。

7、report目錄生成後,進去執行index就看到覆蓋率報告。
省電管理的覆蓋率生成結果:

開啟index後的結果,按build檔案指定的分組生成了:


進入到實際程式碼中的結果:

這裡有個注意的地方,如果想看到實際程式碼的覆蓋率,編譯的時候debug="true" 這個一定要設定。

###1.7 分析覆蓋率結果
網上關於JaCoCo覆蓋率報告的分析有不少的文章可以學習。

這裡闡明幾個自己的觀點:

根據專案的不同,在分析結果前先應該明確幾個事情,包括

(1)確定改動點的範圍,根據這個範圍才會有針對性的做分析。

(2)改動點是否影響功能邏輯,如果不影響可以忽略。

(3)改動點和其他功能是否存在耦合,如果存在,耦合的部分也要做分析。

我們主要從上面幾點來分析覆蓋率,查漏補缺,這些改動點大部分已經覆蓋到了,基本認為應用的主要功能覆蓋完全,當然也不是完全絕對,在測試過程中結合FreeTest、探索性測試等手段也是一種不錯的選擇,切記不要盲目的為了覆蓋率而覆蓋,覆蓋率高不代表你真的覆蓋完全了。

分析過程很多人覺得是比較痛苦的,不妨可以把這個過程當作是一種鍛鍊,前面的一切都只是一個鋪墊,最最關鍵的在於分析階段,一個出色的分析結果可以達到事半功倍的效果。

我們的方法是任務已tapd提單的方式建立,按照模版,附上需求連結地址、svn地址和改動範圍、附件接受未插樁的class檔案、測試後的ec檔案等,分析出結果需要有分析過程、測試補充建議、分析耗時等等。


主要列出未覆蓋場景、冗餘方法、測試補充建議等等。

舉個分析的例子:

需求: 訊息盒子增量測試完成,進行覆蓋率分析。
####1.7.1 熟悉需求用例


1、確認程式碼範圍


2、覆蓋率報告分析

3、確認未覆蓋原因

4、輸出測試策略

5、補充測試驗證

二、覆蓋率與BVT測試結合

通過兩者的結合,可以得到每個BVT的用例的覆蓋率資料,可以得出幾個緯度的結果:

(1)用例和程式碼的對應關係

用例和程式碼的動態對映關係,可能會存在對映到的函式比較多,作者建議根據功能有針對的篩選出重點函式來做對映。

(2)上面對映關係彙總後,可以按方法的呼叫頻繁度來優化我們的程式碼,
優化呼叫頻繁度高的程式碼,找出冗餘程式碼等等。

下面介紹下整個過程:

相關推薦

AVA 程式碼覆蓋率工具 JaCoCo-實踐篇

一、覆蓋率專案中使用介紹本節開始詳細介紹下專案中的JaCoCo實戰經驗。下圖是覆蓋率在實際在專案中的主要實施點:分別詳細介紹下:1.1 確定插樁方式Android專案只能使用JaCoCo的離線插樁方式。為什麼?主要是因為Android覆蓋率的特殊性:一般執行在伺服器java程

JAVA程式碼覆蓋率工具JaCoCo-實踐篇

一、覆蓋率專案中使用介紹 本節開始詳細介紹下專案中的JaCoCo實戰經驗。 下圖是覆蓋率在實際在專案中的主要實施點: 分別詳細介紹下: 1.1 確定插樁方式 Android專案只能使用JaCoCo的離線插樁方式。 為什麼?主要是因為Android覆蓋率的特殊性

JAVA程式碼覆蓋率工具JaCoCo-踩坑篇

一、覆蓋率踩過的坑 在專案中使用JaCoCo覆蓋率的時候,也遇到過各種奇葩的問題,在這裡列出來分享下,問題和實際的專案關係密切,希望對有遇到過相似問題的童鞋有所啟發。 1.1 覆蓋率包在部分手機6.0上安裝失敗 事情起因:在測試新功能時,用打的覆蓋率包,外包反饋部分手機6.0上安裝不了。 問題重現:

JAVA程式碼覆蓋率工具JaCoCo-原理簡單分析

作為一個測試人員,保證產品的軟體質量是其工作首要目標,為了這個目標,測試人員常常會通過很多手段或工具來加以保證,覆蓋率就是其中一環比較重要的環節。 我們通常會將測試覆蓋率分為兩個部分,即“需求覆蓋率”和“程式碼覆蓋率”。 需求覆蓋:指的是測試人員對需求的瞭解程度,根據

【騰訊TMQ】JAVA程式碼覆蓋率工具JaCoCo-踩坑篇

作者:劉洋 一、覆蓋率踩過的坑 在專案中使用JaCoCo覆蓋率的時候,也遇到過各種奇葩的問題,在這裡列出來分享下,問題和實際的專案關係密切,希望對有遇到過相似問題的童鞋有所啟發。 1.1 覆蓋率包在部分手機6.0上安裝失敗 事情起因:在測試新功

JAVA 程式碼覆蓋率工具 JaCoCo-原理篇

一、 覆蓋率定義 作為一個測試人員,保證產品的軟體質量是其工作首要目標,為了這個目標,測試人員常常會通過很多手段或工具來加以保證,覆蓋率就是其中一環比較重要的環節。 我們通常會將測試覆蓋率分為兩個部分,即“需求覆蓋率”和“程式碼覆蓋率”。 需求覆蓋:指的是測試人

JAVA 程式碼覆蓋率工具 JaCoCo-踩坑篇

一、覆蓋率踩過的坑在專案中使用JaCoCo覆蓋率的時候,也遇到過各種奇葩的問題,在這裡列出來分享下,問題和實際的專案關係密切,希望對有遇到過相似問題的童鞋有所啟發。1.1 覆蓋率包在部分手機6.0上安裝失敗事情起因:在測試新功能時,用打的覆蓋率包,外包反饋部分手機6.0上安裝

JaCoCo 程式碼覆蓋率工具(基於Maven+TestNG)

JaCoco是一個程式碼覆蓋率庫。 安裝:  以 Maven(http://www.testclass.net/maven/) 安裝為例: <dependencies> <dependency> <gro

JaCoCo 程式碼覆蓋率工具(基於Maven+TestNG)

JaCoco是一個程式碼覆蓋率庫。 安裝: 以 Maven(http://www.testclass.net/maven/) 安裝為例: <dependencies> <dependency> <groupId>org.test

各種程式語言的程式碼覆蓋率工具彙總

對於Linux下的C/C++程式碼,可以在gcc/g++工具編譯程式碼時加上“–coverage”選項來生成可用於覆蓋率分析的二進位制檔案,然後用gcov命令來生成覆蓋率統計情況,也可用lcov工具來生成html版本的可讀性很好的程式碼覆蓋率報告。 下面列舉一下各種程式語言的程式碼覆蓋率工具吧。c/c+

程式碼覆蓋率工具大全

Kind of Tool Code Coverage Analyzer for C++/C Organization Software Description BullseyeCoverage is a full-featured code covera

c程式碼覆蓋率工具

 C/C++程式的程式碼覆蓋率統計工具非常少,與JAVA相比開源免費的工具更是寥寥無幾,好用又開源的簡直是鳳毛麟角。左挑右選最後看中了基於GCOV的LCOV作為NGINX測試的覆蓋率統計工具。選擇LCOV的原因很簡單:一是適合GCOV是GCC配套的測試覆蓋率工具;二是NGI

各種程式語言的程式碼覆蓋率工具彙總---重要

源地址: 最近兩年在做Linux虛擬化開源專案,由於專案程式碼龐大且開發人員分散在世界各個角落,我們對其測試的方法和實踐中,對單元測試等做得並不多(KVM的kvm-unit-tests可以算一個吧),對單元測試程式碼覆蓋率等也沒有做過多的要求。不過以前做電子商務測試

Linux下程式碼覆蓋率工具:gcov

 Linux下程式碼覆蓋率工具:gcov 對於C/C++軟體開發,常常需要通過程式碼覆蓋率報告來了解測試用例的場景覆蓋情況,對於測試用例未覆蓋的程式碼分支流程,需要補充用例,以保證測試用例的全

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

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

Jacoco覆蓋率工具使用

blank 類型 9.1 位置 get gin count 結束 用例 Jacoco介紹 Jacoco是一個開源的覆蓋率工具。Jacoco可以嵌入到Ant 、Maven中,並提供了EclEmma Eclipse插件,也可以使用JavaAgent技術監控Java程序。很多

Python 程式碼覆蓋率統計工具 coverage.py

coverage.py是一個用來統計python程式程式碼覆蓋率的工具。它使用起來非常簡單,並且支援最終生成介面友好的html報告。在最新版本中,還提供了分支覆蓋的功能。 官方網站: http://nedbatchelder.com/code/coverage/  win32版

IntelliJ IDEA找不到單元測試程式碼覆蓋率預設工具,沒有Coverage選項卡

1、我們使用Java開發工具IntelliJ IDEA,有時候使用單元測試工具Junit後,要進行程式碼覆蓋率報告輸出,可使用IDEA自帶的程式碼覆蓋率工具,直接測試類名右鍵Run ‘MyClassTest’ with Coverage或工具欄上的選項執行特定模式的測試,如下 2、但是發現

iOS 覆蓋率檢測原理與增量程式碼測試覆蓋率工具實現

背景 對蘋果開發者而言,由於平臺稽核週期較長,客戶端程式碼導致的線上問題影響時間往往比較久。如果在開發、測試階段能夠提前暴露問題,就有助於避免線上事故的發生。程式碼覆蓋率檢測正是幫助開發、測試同學提前發現問題,保證程式碼質量的好幫手。 對於開發者而言,程式碼覆蓋率可以反饋兩方面資訊: 自測的充分程

通過jacoco檢查自動化程式碼覆蓋率和報告分析

背景: 雖然jacoco出來也有一段時間了,文章也有,但是網上的文章都是新建的一個測試工程,照著跑下來,到處都是坑…所以還是自己再研究一下吧,並且起碼比他們的詳細。 環境: android studio 2.1.1 + gradle 2.10 搭建