注意:此文譯自JaCoCo官方介紹文檔启妹,如有出錯(cuò)之處靶擦,煩請(qǐng)指出再膳,不勝感激挺勿。點(diǎn)擊此處,查看原文
覆蓋率計(jì)數(shù)器
JaCoCo使用一組不同的計(jì)數(shù)器來計(jì)算覆蓋率指標(biāo)喂柒。這些計(jì)數(shù)器根據(jù)Java類文件包含的信息(基本上是Java字節(jié)碼指令和調(diào)試信息有選擇地嵌入類文件)被分成不同種類不瓶。因此禾嫉,即使在沒有源碼的情況下,這種方法也允許高效的動(dòng)態(tài)測(cè)量和分析應(yīng)用程序湃番。
在大多數(shù)情況下,收集到的信息可以被映射回源代碼吭露,然后可視化成行級(jí)別的覆蓋率報(bào)告吠撮。然而,這種方法也有局限性讲竿。調(diào)試信息必須被編譯到類文件泥兰,以便計(jì)算行粒度覆蓋率,并提供源代碼高亮顯示题禀。并不是所有的Java語言結(jié)構(gòu)都可以直接編譯成字節(jié)碼鞋诗,在這種情況下,Java編譯器創(chuàng)建所謂的合成代碼有時(shí)會(huì)導(dǎo)致意想不到的代碼覆蓋率結(jié)果。
指令(C0 Coverage)
最小單元JaCoCo計(jì)數(shù)是單個(gè)Java字節(jié)碼指令迈嘹,指令覆蓋提供了被執(zhí)行或未被執(zhí)行的代碼量信息削彬。這個(gè)指標(biāo)是完全獨(dú)立于源格式的, 即使在沒有調(diào)試信息的類文件秀仲,也是可用的,融痛。
分支(C1 Coverage)
JaCoCo也計(jì)算所有if和switch語句的分支覆蓋率。這個(gè)指標(biāo)項(xiàng)計(jì)算在一個(gè)方法中的總分支數(shù),并決定了已執(zhí)行和未執(zhí)行分支的數(shù)量神僵。即使在沒有調(diào)試信息的類文件雁刷,分支覆蓋也總是可用的。注意保礼,在此計(jì)數(shù)器的定義中沛励,異常處理并不屬于分支。
如果類文件被編譯了調(diào)式信息決策點(diǎn)炮障,就能夠被相應(yīng)地映射回源碼行以及高亮顯示:
- 未覆蓋:所有分支行都未被執(zhí)行(紅色鉆石)
- 部分覆蓋:只有一部分行分支被執(zhí)行(黃色鉆石)
- 全覆蓋:所有的行分支都已被執(zhí)行(綠色鉆石)
圈復(fù)雜度
JaCoCo也為每個(gè)非抽象方法計(jì)算圈復(fù)雜度目派,總結(jié)類、包和組的復(fù)雜性胁赢。根據(jù)McCabe1996的定義址貌,圈復(fù)雜度是,在(線性)組合徘键,通過一個(gè)方法來生成所有可能的路徑中的最小數(shù)量路徑练对。因此,復(fù)雜性值可以作為單元測(cè)試用例的數(shù)量完全覆蓋一個(gè)軟件某一塊的指標(biāo)吹害。即使在沒有調(diào)試信息的類文件螟凭,復(fù)雜度也通常都是可計(jì)算的。
圈復(fù)雜度的正式定義v(G)是基于方法的控制流圖表示的有向圖:
v(G) = E - N + 2
E表示邊緣數(shù)它呀,N表示節(jié)點(diǎn)數(shù)螺男。JaCoCo通過以基于分支數(shù)(B)和決策點(diǎn)(D)的等效方程來計(jì)算一個(gè)方法的圈復(fù)雜度:
v(G) = B - D + 1
根據(jù)每個(gè)分支的覆蓋率情況棒厘,JaCoCo還為每個(gè)方法計(jì)算已覆蓋和未覆蓋的復(fù)雜性,未覆蓋復(fù)雜度又為完全覆蓋一個(gè)模塊所缺失的測(cè)試用例數(shù)提供了指標(biāo)下隧。注意,JaCoCo并不考慮異常處理分支奢人,try / catch塊也不會(huì)增加復(fù)雜性。
行
對(duì)所有已編譯調(diào)試信息的類文件,每一行的覆蓋率信息也可以計(jì)算淆院。當(dāng)至少一條指令被分配到某一源碼行時(shí)何乎,該源碼行被認(rèn)為已經(jīng)執(zhí)行。
由于一行通常 編譯多個(gè)字節(jié)碼指令土辩,每一行包含的源代碼高亮顯示有三種不同的狀態(tài):
- 未覆蓋:該行沒有指令被執(zhí)行(紅色背景)
- 部分覆蓋:該行只有部分指令被執(zhí)行(黃色背景)
- 全覆蓋:該行包含的所有指令都被執(zhí)行(綠色背景)
根據(jù)源格式支救,一行源代碼可能指定了多個(gè)方法或多個(gè)類。因此拷淘,方法的行計(jì)數(shù)各墨,不能簡(jiǎn)單地添加到獲得包含類的總數(shù)。這同樣適用于在一個(gè)源文件的多個(gè)類启涯。JaCoCo基于實(shí)際的源代碼行覆蓋來計(jì)算類和源文件的覆蓋率贬堵。
方法##
每個(gè)非抽象方法至少包含一條指令。當(dāng)方法至少一條指令被執(zhí)行结洼,則被認(rèn)為該方法被執(zhí)行過扁瓢。因?yàn)镴aCoCo是基于字節(jié)碼級(jí)別的,構(gòu)造函數(shù)和靜態(tài)初始化也被當(dāng)作方法計(jì)算补君。 其中有些方法引几,如隱式,從而生成默認(rèn)構(gòu)造函數(shù)或常量初始值設(shè)定,可能沒有直接對(duì)應(yīng)到Java源代碼中挽铁。
類
當(dāng)一個(gè)類至少有一個(gè)方法被執(zhí)行過伟桅,則認(rèn)為該類被執(zhí)行過。注意叽掘,JaCoCo 將構(gòu)造方法和靜態(tài)初始化方法也當(dāng)作被執(zhí)行過的方法楣铁。包含靜態(tài)初始化方法的Java接口類型,也被當(dāng)作已執(zhí)行的類更扁。