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

SusSoper 8年前發布 | 27K 次閱讀 Java Java開發

一、覆蓋率踩過的坑

在項目中使用JaCoCo覆蓋率的時候,也遇到過各種奇葩的問題,在這里列出來分享下,問題和實際的項目關系密切,希望對有遇到過相似問題的童鞋有所啟發。

1.1 覆蓋率包在部分手機6.0上安裝失敗

事情起因:在測試新功能時,用打的覆蓋率包,外包反饋部分手機6.0上安裝不了。

問題重現:試了在自己的手機,華為mate8的6.0系統上安裝正常,屬于部分機型問題。

將問題小米手機借來后,發現用豌豆莢或者應用寶確實安裝失敗,提示“該應用簽名有問題,無法安裝。”通過adb install安裝,提示INSTALL_PARSE_FAILED_NO_CERTIFICATES

懷疑是部分廠商對簽名的校驗級別比較高。

問題排解:

(1)網上有種說法,jdk1.7以后變更了默認的加密算法,而簽名程序沒有,所以需要在簽名時用參數指定。

具體方法:在簽名命令后加入-digestalg SHA1 -sigalg MD5withRSA

會不會這種情況導致:查了應用寶的打包腳本,簽名部分已經增加。

此種情況排除

(2)會不會簽名文件有問題?

重新排查了打包過程的簽名,密鑰和口令都和RDM打包一樣,對ANDROIDR.RSA、ANDROIDR.SF、MANIFEST.MF,清除掉簽名,重新進行簽名,問題仍然存在。

此種情況排除

(3)JaCoCo的jar包重新簽名

和RDM打包,也就增加了JaCoCo部分,會不會是JaCoCo的兩個jar包jacocoagent.jar和jacocoagent.jar出的問題?

這兩個jar包已經是簽名過的,會不會需要用應用寶的簽名進行重新簽?

使用jarsigner重新對這兩個jar包用應用寶的密鑰進行簽名,打包安裝,問題仍然存在。

此種情況排除

到這里,網上的各種方法基本都試過了,沒任何效果,問題糾結在這里了。

靜下心來,網上的方法沒任何效果,還是回到項目中,重新一步一步的對比RDM打包和覆蓋率打包的區別,逐步排查吧。

(4)RDM打包和覆蓋率打包逐一對比

….(這里省略一萬字,都是排查)

簽名部分的日志對比:

我們還是回到打包簽名的target:sign_obfuscated

逐行對比RDM和我們覆蓋率打包的日志:

發現了一個不同的點:

RDM的:

我們打包的:

大家看出差別了沒(紅色部分)

紅色部分為jacocoagent.jar包里的非class文件,signer對這兩個文件也進行了簽名。

到這里都不是問題。

問題還是應用寶腳本本身(┬_┬哭~)

簽名后做compress和zipalign,據說是極限壓縮,減少包的大小。

Compress會調用compress_yingyongbao.sh腳本,這里列出了所有要壓縮的文件

看到沒,看到沒,它重新按這里的文件列表壓縮打包,丟掉了上面JaCoCo里面的兩個文件

應用在打包后,簽名文件是存在JaCoCo這兩個文件的,但打包后找不到這兩個文件,因此安裝時有的手機提示簽名有問題。

解決方法:

JaCoCo這兩個文件,一個是屬性文件,一個是生成xml的dtd文件,對我們生成覆蓋率沒多大作用,我們把這兩個從jar包里刪除,在重新打包,這兩個文件不存在了,也就不用簽名了,問題就解決了。

1.2 覆蓋率包在部分4.X版本手機上生成ec文件失敗

事情起因:在測試新功能時,用打的覆蓋率包,外包反饋部分4.X手機生成不了ec文件

問題重現:試了在自己的手機,華為mate8的6.0系統上生成正常,屬于部分機型問題。

將問題手機借來后,生成ec文件提示失敗。

問題排解:

查看logcat日志:

還有一段:

反射RT類的getAgent() 方法是提示

(1)反射在其他手機是正常的,按道理不應該在部分問題手機會失敗,但也做一下排查

報錯的代碼行:

網上有說InvocationTargetException問題可能是沒有設置可見就訪問私有

先看看RT的這個方法

在看看Agent類的這個方法:

嘗試把私有字段可見,在去調用

結果問題仍然存在,此種情況排除

(2)那我們就回到第一個錯誤, Class resolved by unexpected DEX

Agent出了兩個地址。

我們在回過頭來看應用寶的打包腳本,看看dex干了什么。

調用dex,輸入classes,輸出dex,下面對excludes里面的jar進行了排除

調用dex_sub,輸入subclasses,輸出second_dex,下面對excludes里面的jar進行了排除

回過頭來在看看我們的插樁腳本,對dex、dex_sub這塊只改了classes為classes_instr(用插樁后的打dex)

應用寶這個分包的邏輯,會分別打兩個dex。

問題就找到了,因為沒有改excludes部分,jacocoagent.jar是放在應用寶libs目錄下的,默認dex和dex_sub都把jacocoagent.jar打了進去,運行時就會出現新的dex想要替換之前校驗過的dex,也就出現agent有兩個地址的緣故。

解決方法:

覆蓋率打包的腳本,對dex_sub的excludes中加入jacocoagent.jar,這樣兩次dex只打一次jacocoagent.jar。

重新打包,ec文件正常生成。

1.3 覆蓋率報告生成后看不到源碼覆蓋情況

源碼和類文件都正確指定了,為什么生成的報告看不到源碼覆蓋?

解決方法:

(1)編譯的時候debug=”true” 這個一定要設置,比如

(2)如果1沒有錯誤,那就要看看你的源碼和class文件路徑指定正確沒,JaCoCo是按照包名去搜索的,這個一定要確定好,很多項目會自建代碼目錄的。

二、覆蓋率一些需要注意的地方

由于Android不能通過JVM停止后自動dump覆蓋率數據,因此當Android應用進程不存在或停止的時候,覆蓋率數據不會生成。

也就有了如下需要注意的地方

(1)沒有啟動應用進程,生成覆蓋率數據會失敗。

(2)覆蓋率生成工具進程殺不殺掉,不影響覆蓋率生成結果。

(3)測試過程中,殺掉應用進程,內存中的覆蓋率數據會丟失。

(4)覆蓋率數據是可以追加記錄的,但最好在殺掉應用進程前先備份。

建議養成良好的操作習慣,定期生成覆蓋率文件。

如果有殺掉應用進程的需求操作,請在操作前生成一次,這樣之前的數據就有所保留了。

一次測試前,一定要保證先清理掉以前覆蓋率的數據,否則以現有追加文件的方式的形式,會導致舊新的覆蓋率柔和在一起,有可能merge時候會失敗。

 

來自:http://tmq.qq.com/2016/08/java-code-coverage-tools-jacoco-hit-the-pit/

 

 本文由用戶 SusSoper 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!