1. 程式人生 > >Android自動化測試探索(五)程式碼覆蓋率統計

Android自動化測試探索(五)程式碼覆蓋率統計

Android 程式碼覆蓋率統計

 

本週開始準備統計Android自動化用例的程式碼覆蓋率,將最終使用的方法記錄下來。

 

覆蓋率監測的原理

覆蓋率監測的原理跟iOS上的原理差不多,大致的思路參考下吧,

iOS自動化探索(十)程式碼覆蓋率統計

Android使用的是JaCoCO覆蓋率統計工具  jacoco 原理篇

 

必要知識儲備或條件: 

  • 專案原始碼
  • Android Studio開發環境
  • 基本瞭解Android專案結構
  • 基礎adb操作

同樣如果以上說的幾個都不懂也行, 讓開發幫忙做這些然後編個程式碼覆蓋率統計的包給你測試, 測完把手機給開發取資料生成報告。 注意每次測試完先返回手機桌面把程式退到後臺等幾秒讓app自己生成日誌檔案

下面開始講步驟

 

步驟1:拉取專案程式碼

git clone XXXXXXXXXXX

 

步驟2:使用Android Studio開啟專案

 

步驟3:配置build.gradle

apply plugin: 'com.android.application'
apply plugin: 'jacoco' //載入程式碼覆蓋庫jacoco

jacoco {
    toolVersion = "0.7.9" //程式碼覆蓋庫jacoco版本號
}

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.whh.initmvp"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            testCoverageEnabled = true //實現程式碼覆蓋率
            minifyEnabled false //獲取程式碼覆蓋率需要設為false (**如果混餚檔案配置完畢,設為true也可**)
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            testCoverageEnabled = true //實現程式碼覆蓋率
            minifyEnabled false //獲取程式碼覆蓋率需要設為false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'

   //.....(此處忽略若干依賴庫)

    //程式碼覆蓋率jacoco(可不引入)
//    compile 'org.jacoco:org.jacoco.core:0.7.9'

}

//程式碼覆蓋率相關配置 start
def coverageSourceDirs = [
        '../app/src/main/java'
]

task jacocoTestReport(type: JacocoReport) {
    group = "Reporting"
    description = "Generate Jacoco coverage reports after running tests."

    reports {
        xml.enabled = true
        html.enabled = true
    }

    classDirectories = fileTree(
            //檢測覆蓋率的class所在目錄(以專案class所在目錄為準)
            dir: './build/intermediates/classes/debug', //gradle2.3 class所在目錄
            //gradle3.2 class所在目錄 dir: './build/intermediates/javac/debug/compileDebugJavaWithJavac/classes',
            //增加以上目錄中不需要檢測的檔案列表
            excludes: ['**/R*.class',
                       '**/*$InjectAdapter.class',
                       '**/*$ModuleAdapter.class',
                       '**/*$ViewInjector*.class'
            ]
    )

    sourceDirectories = files(coverageSourceDirs) //設定需要檢測覆蓋率的目錄
    executionData = files("$buildDir/outputs/code-coverage/connected/code_coverage.ec") //儲存APP執行時產生報告的路徑
}
//程式碼覆蓋率相關配置 end

 

注意事項:

  • compile 'org.jacoco:org.jacoco.core:0.7.9' 庫包可不新增依賴;
  • classDirectories的設定應以專案編譯後生成的class檔案目錄為準,比如:gradle2.3 class所在目錄:dir: './build/intermediates/classes/debug',  gradle3.2 class所在目錄: dir: './build/intermediates/javac/debug/compileDebugJavaWithJavac/classes'
  • executionData的設定,自定義生成的報告的路徑及報告名稱,既然設定,在指定目錄下需要有這樣的檔案,資料夾及檔名稱都要一一對應,不可粗心輸錯;
  • 注意以上註釋的位置,每一個配置務必加上以保證檢測程式碼覆蓋率的實現;

 

步驟4:確認APP有開啟檔案讀寫許可權

在AndroidManifest.xml中新增

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

 

步驟5:在專案的BaseActivity Class中新增以下程式碼:

這裡不一定都叫BaseActivity檔案, 具體要找到自己專案的底層Activity在裡面新增

//生成報告的所在SDcard目錄
    public static String DEFAULT_COVERAGE_FILE_PATH = Environment.getExternalStorageDirectory()+"/";
    private static final String TAG = "MainActivity";

    @Override
    protected void onStop() {
        generateCoverageFile();
        super.onStop();

    }

 /**
     * 生成executionData
     */
    public void generateCoverageFile() {

        OutputStream out = null;


        try {
            out = new FileOutputStream(DEFAULT_COVERAGE_FILE_PATH + "/code_coverage.ec", false); //在SDcard根目錄下生產檢測報告,檔名自定義
            Object agent = Class.forName("org.jacoco.agent.rt.RT").getMethod("getAgent").invoke(null);
            // 這裡之下就統計不到了
            out.write((byte[]) agent.getClass().getMethod("getExecutionData", boolean.class).invoke(agent, false));

            Log.i("whh", "GenerateCoverageFile success");
        } catch (Exception e) {
            Log.i("whh", "GenerateCoverageFile Exception:" + e.toString());

        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

 

步驟6:同步Gradle

點選Sync Now, 完成後找到Gradle視窗

 

步驟7:安裝APP到手機

連線上手機後, 點選上面的installDebug. (注意: 這裡不同的專案可能install目錄下的名稱不一樣, 選擇自己需要的安裝指令碼)

 

步驟8:執行自動化測試用例或手工用例

注意沒執行完一個case需要把手機返回桌面等幾秒,不要殺掉APP程序

並在手機檔案根目錄下找到code_coverage.ec檔案, 這個就是覆蓋率資料

如果沒有的話重新開啟一次APP試試, 還是沒有的話檢查下上面的步驟是不是哪裡漏掉了

 

步驟9:獲取覆蓋率資料

adb pull /sdcard/code_coverage.ec

 

步驟10: 拷貝覆蓋率資料

把上面獲取到的覆蓋率資料複製到專案的app/build/outputs/code-coverage/connected/目錄下,如果沒有該目錄,可手動建立

注意這裡的路徑要跟上面build.gradle裡面寫的一致

executionData = files("$buildDir/outputs/code-coverage/connected/code_coverage.ec")

 

步驟11:生成覆蓋率報告

點選Gradle視窗中的jacocoTestReport即可

報告一般在app\build\reports目錄

 

開啟裡面的index.html就是我們要的報告了

&n