程式碼涵蓋範圍的作用主要是用來查看測試案例執行完畢後,有哪些代碼尚未覆蓋到,未覆蓋到的代碼通常意味著未覆蓋到的功能或情境,對於Andriod程式來說,好像國內聊到這個領域的文章不多,這裡記錄下來供大家參考。
因為Andriod程式實際上就是Java程式,這裡先不談Andriod native C程式的程式碼涵蓋範圍收集(後面的文章會講到,其實就是用gcov做的),Java程式的程式碼涵蓋範圍統計可以使用一個開源軟體Emma,Emma並不需要源碼就可以統計程式碼涵蓋範圍 。這是因為統計程式碼涵蓋範圍的做法有兩種(參看以前的文章:):
1、修改程式原始碼,添加統計程式碼涵蓋範圍的代碼,例如gcov採用的就是這種做法。
2、修改最終程式,比如Emma就是修改Java class的位元組碼Oolong代碼。為了能夠將統計到的程式碼涵蓋範圍結果追溯到原始碼,一般是將Java編譯成調試(Debug)版,做法是:Emma在每個Oolong跳轉代碼前加入統計覆蓋率的代碼,而調試版的class,裡面會有.source, .line. .var這些指令,告訴調試器位元組碼與Java原始碼、Java變數與Oolong變數的數字引用的映射關係,這種做法的好處是,只要你的程式最終會產生Java位元組碼,例如Scala之類的程式,產生的調試版都可以用Emma修改,達到統計程式碼涵蓋範圍的目的。Java虛擬機器對調試的支援,請參考書籍《Programming for the Java Virtual Machine》第7章裡的描述。
因為Andriod程式在部署到裝置之前,會有個程式(dx)將Java位元組碼翻譯成Andriod虛擬機器裡的位元組碼,所以可以在翻譯之前使用Emma修改class檔案,再打包。
實際上Andriod提供了一個ant的 build檔案,裡面就封裝了這個功能,我這裡將這個指令碼做的事情挖了出來,解釋一下各步驟。在解釋之前,先看看如何用ant編譯一個覆蓋率統計版:
1、從eclipse的andriod工程裡產生一個ant的build檔案,andriod-app就是工程名:
android update project -p android-app
2、將eclipse的andriod測試工程也轉換成ant工程,-m選項指定了測試工程對應的主andriod工程的位置,而android-test就是測試工程名:
android update test-project -m ../android-app -p android-test
3、執行下面的命令,編譯、執行單元測試、收集覆蓋率:
ant clean emma debug install test
4、在裝置上,/data/data/<package name>/目錄裡,有一個files檔案夾裡有coverage.ec檔案,即記錄了程式碼涵蓋範圍資訊,但這個資訊還需要跟源碼做一次映射才能看到哪些程式碼已覆蓋。
5、將上面coverage.ec檔案拷貝到andriod主工程的bin檔案夾裡,這個檔案夾裡有一個檔案名稱coverage.em,裡面記錄了修改過的位元組碼與原始碼的映射關係。
6、要查看程式碼涵蓋範圍時,執行下面的命令(andriod SDK裡以及內建了emma.jar),下面命令裡的sp參數即指定了 原始碼的位置:
java -cp ~/android-sdk/tools/lib/emma.jar emma report -r html -in coverage.em -in coverage.ec -sp ~/<andriod-app>/src/
這裡我們把ant命令分解(假設已經將andriod eclipse工程轉換成ant工程了),實際上執行下面幾個命令就可以了,下例中~/research/multiplatformdemoproject就是andriod的主工程路徑:
cd ~/research/multiplatformdemoproject/
# 編譯成調試版
ant debug
# 在打包成dex檔案之前,修改class位元組碼
cd bin
java -cp ~/android-sdk/tools/lib/emma.jar emma instr -ip classes -d instrumented
# 將修改成覆蓋率統計版的class位元組碼打包成andriod虛擬機器檔案
~/android-sdk/platform-tools/dx --dex --debug --no-optimize --output=classes.dex instrumented
~/android-sdk/platform-tools/aapt package -v -f -M /home/shiyimin/research/multiplatformdemoproject/AndroidManifest.xml -S /home/shiyimin/research/multiplatformdemoproject/res -I /home/shiyimin/android-sdk/platforms/android-8/android.jar -F multiplatformdemoproject.unsigned.apk /home/shiyimin/research/multiplatformdemoproject/bin/
# 簽名
jarsigner -keystore ~/.android/debug.keystore -storepass android -keypass android -signedjar multiplatformdemoproject.signed.apk multiplatformdemoproject.unsigned.apk androiddebugkey
~/android-sdk/tools/zipalign 4 multiplatformdemoproject.signed.apk multiplatformdemoproject.apk
# 部署主程式到裝置上
~/android-sdk/platform-tools/adb install multiplatformdemoproject.apk
# 編譯測試案例
cd tests
ant debug
# 部署並且執行測試案例
~/android-sdk/platform-tools/adb install multiplatformdemoproject.test-debug.apk
~/android-sdk/platform-tools/adb shell am instrument -w -e coverage true cc.iqa.studio.demo.test/android.test.InstrumentationTestRunner
# 查看程式碼涵蓋範圍結果報告
cd http://www.cnblogs.com/bin/
~/android-sdk/platform-tools/adb pull /data/data/cc.iqa.studio.demo/files/coverage.ec .
java -cp ~/android-sdk/tools/lib/emma.jar emma report -r html -in coverage.em -in coverage.ec -sp ~/research/multiplatformdemoproject/src/
下面是幾個: