第2.2節 Android Jacoco插件覆蓋率采集

? ? ? ? JaCoCo(Java Code Coverage)是一款開源的代碼覆蓋率分析工具,適用于Java和Android項目。它通過插樁技術統計測試過程中代碼的執行情況,生成可視化報告,幫助開發者評估測試用例的有效性。在github上開源的項目: GitHub - jacoco/jacoco: :microscope: Java Code Coverage Library ,是針對服務端的,而移動端的jacoco插件暫時沒有開源,可以參考: The JaCoCo Plugin ,使用最多的版本是0.8.7,你也可以嘗試使用最新版本。

2.2.1 Jacoco插件的接入

將要接入Jacoco插件的一個Android應用,或是從github上下載一個Demo來進行測試,不過網上的Demo可能因為gradle或是其他包的版本不兼容最新的版本,需要先進行處理一下,能打包后再進行接入jacoco插件。現在我以一個簡單的Android計算器的Demo做一個jacoco接入的演示,早期github上的項目地址是 https://github.com/FlamingJay/AndroidCalculator.git,后來被刪除了,后面我將上傳到我的github上供大家學習。
  • build.gradle中添加jacoco插件
在app下的build.gradle文件中添加對jacoco的引用,如下所示:
plugins {id 'com.android.application'id 'jacoco'
}jacoco {toolVersion = "0.8.7" // 選擇合適的版本
}

注意:此處使用的是0.8.7版本,這個版本比較穩定,你也可以使用最新版本。

  • 打開覆蓋率采集開關
  • android {...buildTypes {release {minifyEnabled falsetestCoverageEnabled = trueproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}debug {testCoverageEnabled = true}}...}
  • 一般在debug包下進行覆蓋率的測試,打開testCoverageEnabled = true, 構建項目的時候就能對代碼進行插樁,采集覆蓋率數據。
  • release包有代碼混淆,覆蓋率報告渲染的時候,無法正確對應到類的源碼,所以要對release包進行測試時,需要關掉代碼混淆。
通過上面的配置,打包后的App就可以采集覆蓋率數據,記錄用戶的具體操作覆蓋。注意:此時的覆蓋率數據存在于內存中,要想拿到覆蓋率數據,必須人為地將覆蓋率數據寫入到文件中。

2.2.2 覆蓋率數據采集

由于覆蓋率數據內容存在于手機內存中,當App退出后,內存中的數據將被清空。而我們要進行覆蓋率測試的時候,必須要拿到覆蓋率數據文件,下面我們將借助于jacoco將覆蓋率數據從內容寫入到文件中,代碼如下:
package com.example.calculator.utils;import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;public class GenerateECFile {public static String TAG = "GenerateECFile:";private static String DEFAULT_COVERAGE_FILE_PATH = "/mnt/sdcard/coverage.ec";private static String partStr="coverage";public static List<File> getDeletePath(Context context) {List<File> files = new ArrayList<>();File sdDir = new File(context.getFilesDir().getPath());String[] list = sdDir.list();if (list != null) {for(int i=0;i<list.length;i++){if(list[i].contains(partStr)){files.add(new File(sdDir.getPath() + "/" + list[i]));}}}return files;}/*** 刪除覆率數據文件* @param context*/public static void deleteCoverageFiles(Context context){List<File> files = getDeletePath(context);if (files!= null && files.size() > 0) {for(File file:files){Log.d(TAG, "JacocoUtils_generateEcFile: 清除舊的ec文件path:+"+ file.getPath());// FileUtils.deleteFile(file);boolean result = file.delete();if (!result && file.exists()) {try{throw new IOException("Failed to delete " + file.getAbsolutePath());}catch(IOException e){e.printStackTrace();}}}}}public static void onJacocoCreate(Context context) {Log.d(TAG, "onJacocoCreate");SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");Calendar cal = Calendar.getInstance();String create_time = format.format(cal.getTime()).substring(0,19);// 獲取packagemanager的實例PackageManager packageManager = context.getPackageManager();// getPackageName()是你當前類的包名,0代表是獲取版本信息try{//刪除原來的覆蓋率數據文件deleteCoverageFiles(context);//生成新覆蓋率數據文件名PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(),0);String app_version = packInfo.versionName;DEFAULT_COVERAGE_FILE_PATH = context.getFilesDir().getPath() + "/coverage"+"-"+app_version+"-"+create_time+".ec";}catch(PackageManager.NameNotFoundException e){e.printStackTrace();Log.d(TAG,"找不到包名"+e);}}/*** 生成覆蓋率數據文件* @param context*/public static void generateCoverageFile(Context context) {OutputStream out = null;try {//如果文件不存在,創建覆蓋率數據文件File file = new File(DEFAULT_COVERAGE_FILE_PATH);if(!file.exists()){try{file.createNewFile();}catch (IOException e){Log.d(TAG,"新建文件異常:"+e);e.printStackTrace();}}//將內存中的覆蓋率數據寫入到文件中out = new FileOutputStream(DEFAULT_COVERAGE_FILE_PATH, true);Object agent = Class.forName("org.jacoco.agent.rt.RT").getMethod("getAgent", new Class[0]).invoke(null);out.write((byte[]) agent.getClass().getMethod("getExecutionData", boolean.class).invoke(agent, false));Log.d(TAG, "生成覆蓋率數據文件:"+DEFAULT_COVERAGE_FILE_PATH);} catch (Exception e) {Log.d(TAG, e.toString(), e);} finally {if (out != null) {try {out.close();} catch (IOException e) {e.printStackTrace();}}}}
}

說明:

  • 本代碼借助于jacoco.agent將手機內存中的覆蓋率數據文件寫入到文件中;
  • 默認文件路徑是本應用的files文件夾,由于現在高版本的android系統不允許訪問手機存儲,只能存儲到App的本身空間中,所以在AndroidManifest.xml文件中要添加:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 代碼中有初始化,清除原來覆蓋率文件的函數,也有生成覆蓋率文件的函數,只要在適合的時機調用即可。
  • 文件命名:coverage-app版本號-日期-時間.ec 如:coverage-1.0-2025-02-11-10_50_03.ec。

2.2.3 何時生成覆蓋率文件?

通過專門的類,可以將手機中的覆蓋率數據寫入到應用的空間中,保存成覆蓋率文件。現在存在一個問題,什么時候保存覆蓋率數據文件?由于覆蓋率數據存在于內存中,一旦應用退出 ,數據將被清除。分析一下app的生命周期,不難發現:
  • 在app進入前端時,清除原來的覆蓋率數據文件,開始采集覆蓋率數據;
  • 在app進入后臺時,生成覆蓋率數據文件。
這樣交互進行比較合適。如果你的應用中有生命周期控制類,在相應的函數中引用上面的覆蓋率生成函數即可,如果沒有,請按如下方法,在MainActivity中的onCreate函數中添加生命周期控制函數,如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);.....// 注冊LifecycleObserverProcessLifecycleOwner.get().getLifecycle().addObserver(new LifecycleObserver() {@OnLifecycleEvent(Lifecycle.Event.ON_START)public void onMoveToForeground() {//清除原來的覆蓋率數據文件GenerateECFile.onJacocoCreate(MainActivity.this);// 應用從后臺移動到前臺時調用Log.i(TAG,"App moved to foreground");}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void onMoveToBackground() {//開始生成覆蓋率數據文件GenerateECFile.generateCoverageFile(MainActivity.this);// 應用從前臺移動到后臺時調用Log.i(TAG,"App moved to background");}});....}

?添加了以上操作,就可以在App的生命周期中采集覆蓋率數據,并寫入到文件中。

將通過上面修改的app打包,安裝到手機上進行測試。打開計算器,隨便進行一些操作或是執行一些測試用例,然后再將app置于后臺,注意不要殺死App。此時會將前面操作的覆蓋率數據寫入數據文件,置到后臺一會兒后,再殺死應用,就可以拿覆蓋率數據文件了。

2.2.4 下載覆蓋率數據文件

根據設置覆蓋率數據文件會生成在手機下面的位置:/data/data/應用包名/files,但是正常的手機系統由于安全設置,是無法下載下來的:
此時,在Android Studio點擊右側的Device Manager,找到連接的手機設備,單擊設備最右側的按鈕,選擇"Open in Device Explorer",就可以打開手機的文件系統,如下所示:
找到對應的覆蓋率數據文件的位置,如:/data/data/com.example.calculator/files/,就可以看到覆蓋率數據文件,右擊文件,選擇"save as..".將覆蓋率數據文件下載到本地目錄。
下載到覆蓋率數據文件后,就可以根據需要生成全量和增量覆蓋率報告,檢測測試情況,排查漏測問題補充測試用例。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73251.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73251.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73251.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

特征工程自動化(FeatureTools實戰)

目錄 特征工程自動化(FeatureTools實戰)1. 引言2. 項目背景與意義2.1 特征工程的重要性2.2 自動化特征工程的優勢2.3 工業級數據處理需求3. 數據集生成與介紹3.1 數據集構成3.2 數據生成方法4. 自動化特征工程理論基礎4.1 特征工程的基本概念4.2 FeatureTools庫簡介4.3 關鍵公…

Scikit-learn模型評估全流程解析:從數據劃分到交叉驗證優化

模型評估的步驟、scikit-learn函數及實例說明 1. 數據劃分&#xff08;Train-Test Split&#xff09; 函數&#xff1a;train_test_split使用場景&#xff1a;將數據分為訓練集和測試集&#xff0c;避免模型過擬合。作用&#xff1a;確保模型在未見過的數據上驗證性能。示例&…

Spring AI相關的面試題

以下是150道Spring AI相關的面試題目及答案&#xff1a; ### Spring AI基礎概念類 **1. 什么是Spring AI&#xff1f;** Spring AI是Spring框架的擴展&#xff0c;旨在簡化人工智能模型在Java應用中的集成與使用&#xff0c;提供與Spring生態無縫銜接的工具和抽象&#xff0c…

C++ 學習筆記(四)—— 類和對象

1、this指針 class Date { public&#xff1a;void Init(Date* this, int year, int month, int day){this->_year year;this->_month month;this->_day day;this->Print();// 這就是this指針&#xff0c;是編譯器自己加的&#xff0c;是用來讓成員函數找到成…

SpringMVC全局異常處理機制

異常處理機制 異常處理的兩種方式&#xff1a; 編程式異常處理&#xff1a;是指在代碼中顯式地編寫處理異常的邏輯。它通常涉及到對異常類型的檢測及其處理&#xff0c;例如使用 try-catch 塊來捕獲異常&#xff0c;然后在 catch 塊中編寫特定的處理代碼&#xff0c;或者在 f…

深入LangChain:LLM交互機制與RAG集成的技術

本文將聚焦于 LangChain 如何集成檢索增強生成&#xff08;RAG&#xff09;&#xff0c;了解其架構、主要組件&#xff0c;以及與 LLM 的交互 LangChain 架構概覽 1、基礎層 這是與各類 LLM 對接的 “橋梁”。LangChain 支持多種流行的 LLM&#xff0c;如 OpenAI 的系列模型、H…

本地部署 LangManus

本地部署 LangManus 0. 引言1. 部署 LangManus2. 部署 LangManus Web UI 0. 引言 LangManus 是一個社區驅動的 AI 自動化框架&#xff0c;它建立在開源社區的卓越工作基礎之上。我們的目標是將語言模型與專業工具&#xff08;如網絡搜索、爬蟲和 Python 代碼執行&#xff09;相…

SQL注入(SQL Injection)攻擊原理與防御措施

SQL是一種代碼注入技術&#xff0c;可使攻擊者修改應用程序向數據庫提供的查詢。 迄今為止&#xff0c;最常見和最嚴重的應用 程序安全威脅總是隱藏在與數據庫有某些連接的網絡應用 程序中。 通過這種 SQL 注入&#xff0c;攻擊者可以繞過登錄程序&#xff0c;獲取、更改甚至更…

【算法】十大排序算法(含時間復雜度、核心思想)

以下是 **十大經典排序算法** 的時間復雜度、空間復雜度及穩定性總結&#xff0c;適用于面試快速回顧&#xff1a;排序算法對比表 排序算法最佳時間復雜度平均時間復雜度最差時間復雜度空間復雜度穩定性核心思想冒泡排序O(n)O(n)O(n)O(1)穩定相鄰元素交換&#xff0c;大數沉底…

LVS的 NAT 模式實現 3 臺RS的輪詢訪問

使用LVS的 NAT 模式實現 3 臺RS的輪詢訪問 1.配置 RS&#xff08;NAT模式&#xff09;2. 配置 LVS 主機&#xff08;僅主機、NAT模式&#xff09;2.1 配置僅主機網卡&#xff08;192.168.66.150/24 VIP &#xff09;2.2 配置 NAT 網卡&#xff08;192.168.88.6/24 DIP&#xff…

一、MySQL8的my.ini文件

MySQL8.0.11的安裝版本my.ini配置文件默認存放在&#xff1a;C:/Program Files/MySQL/MySQL Server 8.0/ 目錄下&#xff1b;而MySQL8.0.11綠色免安裝版本是沒有my.ini配置文件&#xff0c;用戶可以自行構建后&#xff0c;再通過my.ini進行數據庫的相關配置 一、MySQL8.0.11默…

微調這件小事:訓練集中的輸入數據該作為instruction還是input?從LLaMA-Factory的源碼中尋找答案吧~

在之前的博文中,我們已經了解了LLaMA-Factory框架執行各類任務的流程。今天,我們將深入探討SFT微調過程中關于數據集的兩個關鍵問題: 數據集中的instruction和input是如何結合起來生成大模型可以理解的輸入的?instruction是不是就是system prompt呢?(之所以會問這個問題,…

nacos-actuator漏洞

1、nacos配置文件添加以下配置 vim application.properties# 添加以下配置項 management.endpoints.enabled-by-defaultfalse management.server.port-12、重啟Nacos systemctl restart nacos3、驗證 打開地址http://ip:port/nacos/actuator查看是否有敏感信息輸出&#xff0…

extern關鍵字的用法

目錄 總述 一、聲明外部變量 二、聲明外部函數 三、實現模塊化編程 四、與"C" 連用&#xff0c;實現C和C的混合編程 五、注意事項 六、疑點補充&#xff08;你可能會有和我一樣的疑問&#xff1f;&#xff09; 總述 在C和C中&#xff0c;extern關鍵字用于聲明外…

Jboss漏洞再現

一、CVE-2015-7501 1、開環境 2、訪問地址 / invoker/JMXInvokerServlet 出現了讓下載的頁面&#xff0c;說明有漏洞 3、下載ysoserial工具進行漏洞利用 4、在cmd運行 看到可以成功運行&#xff0c;接下來去base64編碼我們反彈shell的命令 5、執行命令 java -jar ysoserial-…

Android平臺毫秒級低延遲HTTP-FLV直播播放器技術探究與實現

一、前言 在移動互聯網蓬勃發展的今天&#xff0c;視頻播放功能已成為眾多Android應用的核心特性之一。面對多樣化的視頻格式和傳輸協議&#xff0c;開發一款高效、穩定的視頻播放器是許多開發者追求的目標。FLV&#xff08;Flash Video&#xff09;格式&#xff0c;盡管隨著H…

BUAA XCPC 2025 Spring Training 2

C \color{green}{\texttt{C}} C [Problem Discription] \color{blue}{\texttt{[Problem Discription]}} [Problem Discription] 給定一棵以 1 1 1 為根的樹&#xff0c;記 a i a_{i} ai? 表示節點 i i i 的權值&#xff0c; lca( i , j ) \text{lca(}i,j) lca(i,j) 表示節…

MySQL 中,分庫分表機制和分表分庫策略

在 MySQL 中,分庫分表是一種常見的數據庫水平擴展方案,用于解決單庫單表數據量過大導致的性能瓶頸問題。通過將數據分散到多個數據庫或表中,可以提高系統的并發處理能力、降低單點故障風險,并提升查詢性能。 一、分庫分表的作用 提升性能: 分散數據存儲和查詢壓力,避免單…

組件日志——etcd

目錄 一、簡介 二、安裝【Ubuntu】 安裝etcd 安裝CAPI 三、寫一個示例 3.0寫一個示例代碼 3.1獲取一個etcd服務 3.2獲取租約(寫端操作) 3.3使用租約(寫端操作) 3.4銷毀租約(寫端操作) 3.5獲取etcd服務中的服務列表(讀端操作) 3.6監聽狀態變化(讀端操作) 一、簡介 Et…

python網絡爬蟲開發實戰之網頁數據的解析提取

目錄 1 XPath的使用 1.1 XPath概覽 1.2 XPath常用規則 1.3 準備工作 1.4 實例引入 1.5 所有節點 1.6 節點 1.7 父節點 1.8 屬性匹配 1.9 文本獲取 1.10 屬性獲取 1.11 屬性多值匹配 1.12 多屬性匹配 1.13 按序選擇 1.14 節點軸選擇 2 Beautiful Soup 2.1 簡介…