JAVA代碼覆蓋率工具JaCoCo-踩坑篇
一、覆蓋率踩過的坑
在項目中使用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/