JAVA程式碼涵蓋範圍工具JaCoCo-原理簡單分析__持續整合CI

來源:互聯網
上載者:User

作為一個測試人員,保證產品的軟體品質是其工作首要目標,為了這個目標,測試人員常常會通過很多手段或工具來加以保證,覆蓋率就是其中一環比較重要的環節。

我們通常會將測試覆蓋率分為兩個部分,即“需求覆蓋率”和“程式碼涵蓋範圍”。

需求覆蓋:指的是測試人員對需求的瞭解程度,根據需求的可測試性來拆分成各個子需求點,來編寫相應的測試案例,最終建立一個需求和用例的映射關係,以用例的測試結果來驗證需求的實現,可以理解為黑盒覆蓋。

代碼覆蓋:為了更加全面的覆蓋,我們可能還需要理解被測程式的邏輯,需要考慮到每個函數的輸入與輸出,邏輯分支代碼的執行情況,這個時候我們的測試執行情況就以程式碼涵蓋範圍來衡量,可以理解為白盒覆蓋。

以上兩者完全可以相輔相成,用代碼覆蓋結果反向的檢查需求覆蓋(用例)的測試是否充分完整。

如果做覆蓋率測試。我們可以藉助一些網上流行的各種覆蓋率工具,本章主要介紹JaCoCo這個工具。

EMMA與JaCoco比較分析:

市場上java主要程式碼涵蓋範圍工具:EMMA、JaCoCo

總結一下個人對JaCoCo優勢的理解:

(1)JaCoCo支援分支覆蓋、引入了Agent模式。

(2)EMMA官網已經不維護了,JaCoCo是其團隊開發的,可以理解為一個升級版。

(3)JaCoCo社區比較活躍,官網也在不斷的維護更新。

JaCoCo是一個開源的覆蓋率工具(官網地址:http://www.eclemma.org/JaCoCo/),它針對的開發語言是java,其使用方法很靈活,可以嵌入到Ant、Maven中;可以作為Eclipse外掛程式,可以使用其JavaAgent技術監控Java程式等等。

##############################如果你不瞭解什麼是java agent,下面接著有介紹,否則直接跳過####################################

JavaAgent 是JDK 1.5 以後引入的,也可以叫做Java代理。

JavaAgent 是運行在 main方法之前的攔截器,它內定的方法名叫 premain ,也就是說先執行 premain 方法然後再執行 main 方法。

那麼如何?一個 JavaAgent 呢。很簡單,只需要增加 premain 方法即可。

看下面的代碼和代碼中的注釋說明:

package com.shanhy.demo.agent;import java.lang.instrument.Instrumentation;/** * 我的Java代理 * * @author   單紅宇(365384722) * @myblog  http://blog.csdn.net/catoop/ * @create    2016年3月30日 */public class MyAgent {    /**     * 該方法在main方法之前運行,與main方法運行在同一個JVM中     * 並被同一個System ClassLoader裝載     * 被統一的安全性原則(security policy)和上下文(context)管理     *     * @param agentOps     * @param inst     * @author SHANHY     * @create  2016年3月30日     */    public static void premain(String agentOps, Instrumentation inst) {        System.out.println("=========premain方法執行========");        System.out.println(agentOps);    }    /**     * 如果不存在 premain(String agentOps, Instrumentation inst)      * 則會執行 premain(String agentOps)     *     * @param agentOps     * @author SHANHY     * @create  2016年3月30日     */    public static void premain(String agentOps) {        System.out.println("=========premain方法執行2========");        System.out.println(agentOps);    }}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

寫完這個類後,我們還需要做一步配置工作。

在 src 目錄下添加 META-INF/MANIFEST.MF 檔案,內容按如下定義:

Manifest-Version: 1.0Premain-Class: com.shanhy.demo.agent.MyAgentCan-Redefine-Classes: true
1 2 3 4 1 2 3 4

要特別注意,一共是四行,第四行是空行,還有就是冒號後面的一個空格,如下截圖: 

然後我們打包代碼為 myagent.jar

注意打包的時候選擇我們自己定義的 MANIFEST.MF 

接著我們在建立一個帶有main方法的主程式工程,截圖如下: 

然後將該主程式打包為 myapp.jar

如何執行 myagent.jar 。我們通過 -javaagent 參數來指定我們的Java代理包,值得一說的是 -javaagent 這個參數的個數是不限的,如果指定了多個,則會按指定的先後執行,執行完各個 agent 後,才會執行主程式的 main 方法。

命令如下:

java -javaagent:G:\myagent.jar=Hello1 -javaagent:G:\myagent.jar=Hello2 -javaagent:G:\myagent.jar=Hello3 -jar myapp.jar
1 1

輸出結果:

G:\>java -javaagent:G:\myagent.jar=Hello1 -javaagent:G:\myagent.jar=Hello2 -javaagent:G:\myagent.jar=Hello3 -jar myapp.jar=========premain方法執行========Hello1=========premain方法執行========Hello2=========premain方法執行========Hello3=========main方法執行========
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

特別提醒:如果你把 -javaagent 放在 -jar 後面,則不會生效。也就是說,放在主程式後面的 agent 是無效的。

比如執行:

java -javaagent:G:\myagent.jar=Hello1 -javaagent:G:\myagent.jar=Hello2 -jar myapp.jar -javaagent:G:\myagent.jar=Hello3
1 1

只會有前個生效,第三個是無效的。 
輸出結果:

G:\>java -javaagent:G:\myagent.jar=Hello1 -javaagent:G:\myagent.jar=Hello2 -jar myapp.jar -javaagent:G:\myagent.jar=Hello3=========premain方法執行========Hello1=========premain方法執行========Hello2=========main方法執行========
1 2 3 4 5 6 1 2 3 4 5 6

命令中的Hello1為我們傳遞給 premain 方法的字串參數。

至此,我們會使用 javaagent 了,但是單單看這樣啟動並執行效果,好像沒有什麼實際意義嘛。

我們可以用 javaagent 做什麼呢。下篇文章我們來介紹如何在項目中應用 javaagent。

最後說一下,還有一種,在main方法執行後再執行代理的方法,因為不常用,而且主程式需要配置 Agent-Class,所以不常用,如果需要自行瞭解下 agentmain(String agentArgs, Instrumentation inst) 方法。

#################################################### java agent介紹結束 #####################################################


很多第三方的工具提供了對JaCoCo的整合,如sonar、Jenkins等。
JaCoCo包含了多種尺度的覆蓋率計數器,包含指令級覆蓋(Instructions,C0coverage),分支(Branches,C1coverage)、循環複雜度(CyclomaticComplexity)、行覆蓋(Lines)、方法覆蓋(non-abstract methods)、類覆蓋(classes)。

行覆蓋率:度量被測程式的每行代碼是否被執行,判斷標準行中是否至少有一個指令被執行。

類覆蓋率:度量計算class類檔案是否被執行。

分支覆蓋率:度量if和switch語句的分支覆蓋情況,計算一個方法裡面的

總分支數,確定執行和不執行的 分支數量。

方法覆蓋率:度量被測程式的方法執行情況,是否執行取決於方法中是否有至少一個指令被執行。

指令覆蓋:計數單元是單個java二進位代碼指令,指令覆蓋率提供了代碼是否被執行的資訊,度量完全 獨立源碼格式。

循環複雜度:在(線性)組合中,計算在一個方法裡面所有可能路徑的最小數目,缺失的複雜度同樣表示測 試案例沒有完全覆蓋到這個模組。


jacoco原理:

1. 注入方式介紹

這個圖包含了幾種不同的收集覆蓋率資訊的方法,每種方法的實現方法都不一樣,帶顏色的部分是JaCoCo比較有特色的地方。

上面各個名次含義(帶顏色的為JaCoCo支援):

上表JaCoCo支援的部分,再詳細的解釋下:

(1)JaCoCo在Byte Code時使用的ASM技術修改位元組碼方法,可以修改Jar檔案、class檔案位元組碼檔案。

(2)JaCoCo同時支援on-the-fly和offline的兩種插樁模式。 On-the-fly插樁:

JVM中通過-javaagent參數指定特定的jar檔案啟動Instrumentation的代理程式,代理程式在通過Class Loader裝載一個class前判斷是否轉換修改class檔案,將統計代碼插入class,測試覆蓋率分析可以在JVM執行測試代碼的過程中完成。 Offline模式:

在測試前先對檔案進行插樁,然後產生插過樁的class或jar包,測試插過樁 的class和jar包後,會產生動態覆蓋資訊到檔案,最後統一對覆蓋資訊進行處理,並產生報告。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.