關於JAVA代碼覆蓋率工具JaCoCo,做者會經過三篇來介紹,分別爲原理篇、實踐篇和踩坑篇,先從原理篇開始介紹~html
1、覆蓋率定義java
做爲一個測試人員,保證產品的軟件質量是其工做首要目標,爲了這個目標,測試人員經常會經過不少手段或工具來加以保證,覆蓋率就是其中一環比較重要的環節。數組
咱們一般會將測試覆蓋率分爲兩個部分,即「需求覆蓋率」和「代碼覆蓋率」。jvm
需求覆蓋:指的是測試人員對需求的瞭解程度,根據需求的可測試性來拆分紅各個子需求點,來編寫相應的測試用例,最終創建一個需求和用例的映射關係,以用例的測試結果來驗證需求的實現,能夠理解爲黑盒覆蓋。maven
代碼覆蓋:爲了更加全面的覆蓋,咱們可能還須要理解被測程序的邏輯,須要考慮到每一個函數的輸入與輸出,邏輯分支代碼的執行狀況,這個時候咱們的測試執行狀況就以代碼覆蓋率來衡量,能夠理解爲白盒覆蓋。函數
以上二者徹底能夠相輔相成,用代碼覆蓋結果反向的檢查需求覆蓋(用例)的測試是否充分完整。工具
若是作覆蓋率測試?咱們能夠藉助一些網上流行的各類覆蓋率工具,本章主要介紹JaCoCo這個工具。學習
2、JAVA覆蓋率工具介紹測試
市場上java主要代碼覆蓋率工具:EMMA、JaCoCo。ui
總結一下我的對JaCoCo優點的理解:
(1) JaCoCo支持分支覆蓋、引入了Agent模式。
(2) EMMA官網已經不維護了,JaCoCo是其團隊開發的,能夠理解爲一個升級版。
(3) JaCoCo社區比較活躍,官網也在不斷的維護更新。
咱們前期使用的EMMA,也作了全量、差別覆蓋率,和精準耦合也結合在了一塊兒,但後來考慮到JaCoCo的優點,也就所有切換了過來。
2.1 JaCoCo簡述
JaCoCo是一個開源的覆蓋率工具(官網地址:http://www.eclemma.org/JaCoCo/),它針對的開發語言是java,其使用方法很靈活,能夠嵌入到Ant、Maven中;能夠做爲Eclipse插件,可使用其JavaAgent技術監控Java程序等等。
不少第三方的工具提供了對JaCoCo的集成,如sonar、Jenkins等。
JaCoCo包含了多種尺度的覆蓋率計數器,包含指令級覆蓋(Instructions,C0coverage),分支(Branches,C1coverage)、圈複雜度(CyclomaticComplexity)、行覆蓋(Lines)、方法覆蓋(non-abstract methods)、類覆蓋(classes),後面會一一介紹。
咱們先看看其覆蓋率結果展示以下圖1-1所示,方便讀者先有一個大概的瞭解。
圖1-1 覆蓋率報告結果部分截圖
標示綠色的爲行覆蓋充分,標紅色的爲未覆蓋的行,黃色菱形的爲分支部分覆蓋,綠色菱形爲分支徹底覆蓋。
經過這個報告的結果就能夠知道代碼真實的執行狀況,便於咱們分析評估結果。
2.2 JaCoCo基本概念
行覆蓋率:度量被測程序的每行代碼是否被執行,判斷標準行中是否至少有一個指令被執行。
類覆蓋率:度量計算class類文件是否被執行。
分支覆蓋率:度量if和switch語句的分支覆蓋狀況,計算一個方法裏面的總分支數,肯定執行和不執行的 分支數量。
方法覆蓋率:度量被測程序的方法執行狀況,是否執行取決於方法中是否有至少一個指令被執行。
指令覆蓋:計數單元是單個java二進制代碼指令,指令覆蓋率提供了代碼是否被執行的信息,度量徹底 獨立源碼格式。
圈複雜度:在(線性)組合中,計算在一個方法裏面全部可能路徑的最小數目,缺失的複雜度一樣表示測 試案例沒有徹底覆蓋到這個模塊。
2.3 JaCoCo 原理
一、注入方式介紹
這個圖包含了幾種不一樣的收集覆蓋率信息的方法,每種方法的實現方法都不同,帶顏色的部分是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包後,會生成動態覆蓋信息到文件,最後統一對覆蓋信息進行處理,並生成報告。
On-the-fly和offline比較:
On-the-fly模式更方便簡單進行代碼覆蓋分析,無需提早進行字節碼插樁,無需考慮classpath 的設置。
存在以下狀況不適合on-the-fly,須要採用offline提早對字節碼插樁:
(1) 運行環境不支持java agent。
(2) 部署環境不容許設置JVM參數。
(3) 字節碼須要被轉換成其餘的虛擬機如Android Dalvik VM。
(4) 動態修改字節碼過程當中和其餘agent衝突。
(5) 沒法自定義用戶加載類。
二、JaCoCo執行最小的java版本
最小須要Java1.5
三、字節碼處理方式
JaCoCo經過注入來修改和生成java字節碼,使用的是ASM庫。
四、java方法控制流分析
JaCoCo是如何在字節碼注入的?
咱們帶着疑問來看下面的內容:
先舉個實例,有個java方法:
編譯後轉換成字節碼後,內容以下:
咱們知道JaCoCo是字節碼注入方式,它是經過一個Probe探針的方式來注入的,具體以下:
探針是字節指令集插入到java方法中,程序執行後能夠被記錄,它不會改變原有代碼的行爲。
咱們看看探針先後插入比較:
顏色的部分就是探針注入的地方。
JaCoCo是根據控制流Type來採用不一樣的探針插入策略的。
一個用java字節碼定義的java方法的控制流圖可能有如下的type,每個type鏈接一個源指令與目標指令,type不一樣探針的注入策略也會不一樣,以下是type定義:
探針不改變該方法的行爲,但記錄他們已被執行的事實,從理論上講,能夠在控制流圖的每個邊插入一個探針,做爲探針實現自己須要多個字節碼指令,這將增長几倍的類文件的大小和執行速度。
事實上,只須要一個幾個探頭,根據每一個方法的控制流的方法,下面說明了如何在不一樣的邊緣類型的狀況下添加額外的指令:
一個instrumented class能夠用如下代碼檢索其探針數組實例:
JaCoCo是用一個布爾數組來實現探針,每一個探針對應於該數組中的項。當如下四個字節碼指令觸發時探針進行輸入設置爲true:
JaCoCo對行探針是這樣處理的,添加兩行指令之間的一個額外的探針時,後續行至少包含一個方法調用。
以上是JaCoCo插樁原理,若是想深刻了解,能夠去看看它的源碼實現。
3、JaCoCo使用方式
使用方式有不少,這裏貼出了相應的參考連接,根據項目的不一樣能夠靈活供有須要的讀者去學習。
3.1 Apache Ant方式
參見 http://eclemma.org/jacoco/trunk/doc/ant.html
主要有如下幾種,具體使用就不介紹了,應用寶是用的這種方式,後續有介紹。
Task coverage、Task agent、Task dump、Task merge、Task report、Task instrument
3.2 命令行方式
參見 http://www.eclemma.org/jacoco/trunk/doc/agent.html
使用方式說明:
主要放在JAVA_OPTS中,好比:
由AgentOptions的getVMArgument方法加載,各參數入AgentOptions的對應參數,爲後續操做作爲輸入。
下面是官網的全部參數說明:
系統在jvm中止的時候會dump覆蓋率信息。
關鍵的核心代碼在這裏,Agent.java在有一段代碼
Runtime.getRuntime().addShutdownHook這個方法的意思就是在jvm中增長一個關閉的鉤子,當jvm關閉的時候,會執行系統中已經設置的全部經過方法addShutdownHook添加的鉤子,當系統執行完這些鉤子後,jvm纔會關閉。因此這些鉤子能夠在jvm關閉的時候進行內存清理、對象銷燬等操做。
也就是在JVM關閉的時候調用agent.shutdown(),也就是寫覆蓋率數據。
3.3 Apache Maven方式
參見 http://www.eclemma.org/jacoco/trunk/doc/maven.html
這種方式適合Maven的項目。
下面簡單說下調用方式原理:
就拿官方的Offline Example來講吧,其部份內容以下:
注意藍色的部分,上面的配置主要作了如下幾個事情:
(1) 項目已jar包方式打包,引入junit和jacoco。
(2) Build時執行instrument、report、check。
(3) 覆蓋率生成到target/jacoco.exec
咱們看看他是怎麼觸發調用的。
在jacoco源碼中:jacoco-maven-plugin\target\classes\META-INF\maven\org.jacoco\jacoco-maven-plugin目錄下有個plugin-help.xml文件,它裏面標明瞭具體的調用方式。
截出instrument這段,關鍵地方就是下面藍色部分。
官網上關於參數的說明:
給出一個整理後的表格:
再給一個jacoco的maven部分的代碼目錄:
到這裏,你們應該清楚其調用的方式了吧。
3.4 Eclipse EclDmma Plugin方式
具體步驟以下:
(1) 在Eclipse菜單中選擇Help → Install New Software...
(2) 在安裝彈框中輸入http://update.eclemma.org/,勾選出現的版本。
(3) 覈對版本,點擊Next。
(4) 根據嚮導完成安裝。
(5) 使用就不說了。
3.5 與Jekins集成
(1) 先要在jenkins上安裝JaCoCo的插件,安裝完成以後在job的配置項中能夠增長這個選項(如圖1-2):
圖1-2
(2) 選擇後出現(圖1-3):
圖1-3
第一個錄入框是你的覆蓋率文件(exec),第二個是class文件目錄,第三個是源代碼文件目錄。
(3) 配置好了以後進行構建,構建完成以後job首頁就會出現覆蓋率的趨勢圖(圖1-4),鼠標點擊趨勢圖能夠看到覆蓋率詳情(圖1-5) ,包括具體覆蓋率數據和源碼的覆蓋率狀況:
圖1-4 趨勢圖
圖1-5 覆蓋率詳情
未完待續 :
JaCoCo原理篇就介紹到這裏了,後續還有項目實踐篇和踩坑篇,實踐篇主要介紹下JaCoCo在實際業務中的使用狀況,踩坑篇裏面包含了幾個當時遇到的比較棘手的問題的解決思路,有興趣的童鞋請關注。