JaCoCo使用一組不一樣的計數器來計算覆蓋率指標。全部這些計數器都是從Java類文件裏獲取信息,這些類文件包含Java 字節碼指令和調試信息。即便沒有可用源代碼狀況下,這種方法能夠實時有效的對應用程序進行檢測和分析。在大多數狀況下,收集的信息能夠映射回源代碼,並可視化到每一行代碼的粒度。然而,這種方法也有侷限性。這些類文件必須使用調試信息編譯,這樣才能夠計算行的覆蓋率並讓源碼高亮顯示。並非全部的Java語言的結構均可以直接編譯成相應的字節碼。在這種狀況下,Java編譯器建立所謂的「合成」代碼,有時會致使未預料到的代碼覆蓋結果。html
JaCoCo最小的計數單元是單個Java字節代碼指令。指令覆蓋率提供了代碼是否被執行的信息。這個度量是徹底獨立於源格式而且常常可用,即便在類文件缺失調試信息的狀況下。函數
JaCoCo還計算全部的 if 和 switch 語句的分支覆蓋率。這個度量計算一個方法裏的總分支數並肯定執行或未執行的分支數。分支覆蓋率老是可用的,即便類文件裏缺失調試信息的狀況下。請注意異常處理是不在分支度量裏面統計的。單元測試
若是類文件使用調試信息編譯,產生的覆蓋率能夠映射到源碼行而且高亮顯示:測試
JaCoCo一樣能夠爲每個非抽象方法計算圈複雜度,最終計算出類、包、組的複雜度。根據McCabe1996圈複雜度的定義是,在線性組合中,計算在一個方法裏面全部可能路徑的最小數量。所以,複雜度的值能夠做爲表示單元測試用例是否有徹底覆蓋全部場景的一個依據。複雜度數字即便在類文件缺失調試信息的狀況下也能夠計算。調試
圈複雜度 v(G) 的正式定義基於方法的控制流程圖做爲有向圖的表示:htm
v(G) = E - N + 2接口
其中,E表明邊界的數量,N表示節點的數量。JaCoCo經過下面基於分支數量(B)和決策點數量(D)的等價方程來計算方法的圈複雜度:get
v(G) = B - D + 1編譯器
基於每一個分支的被覆蓋狀況,JaCoCo也爲每一個方法計算覆蓋率和缺失的複雜度。缺失的複雜度一樣表示測試用例沒有徹底覆蓋到這個模塊。值得注意的是JaCoCo並不會將異常處理做爲分支, try/catch 塊也一樣不會增長複雜度。源碼
全部的類文件使用調試信息編譯以後,就能夠計算行的覆蓋率信息。一行源代碼是否被執行,要看這一行中是否至少有一個指令被執行。因爲單一行代碼一般被編譯爲多個字節碼指令,這樣源碼在高亮顯示時,會顯示成3種不一樣的狀態:
根據源代碼格式的不一樣,源代碼的單行可能引用多個方法或多個類。所以,不能簡單地添加方法的行計數來獲取包含類的總數。同一個源文件中多個類的行也是如此。Jacoco根據覆蓋的實際源行計算類和源文件的行覆蓋率。
每一個非抽象方法至少包含一個指令。一個方法是否執行取決於方法中是否至少有一個指令被執行。當Jacoco在字節代碼級別上工做時,構造器和靜態初始化一樣會像方法同樣統計。其中一些方法可能沒有能夠直接對應的Java源碼,好比默認構造器或常量的初始化命令。
一個類是否執行取決於類中是否至少有一個方法被執行。值得注意的是JaCoCo認爲構造函數和靜態初始化都是方法。Java的接口通常包含靜態初始化,因此接口也一樣被認爲是可執行的類。