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

  • 2019 年 10 月 3 日
  • 筆記

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即可

報告一般在appbuildreports目錄

 

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