首页 > 其他分享 >Jacoco 手动测试覆盖率检查

Jacoco 手动测试覆盖率检查

时间:2024-06-02 21:30:50浏览次数:18  
标签:staging 覆盖率 app 手动 目录 jacoco activity android Jacoco


团队中目前还没有自动化测试的覆盖,所以测试 team 想了解下手动测试的覆盖率。于是才有了本片文章的产生。网上有很多文章是利用 Android 的 instrument 测试框架,然后通过命令来启动app来进行测试。而且报告生产的时间点是在启动的 activity 结束以后,在复杂场景下,是没有办法来捕捉到所有页面的函数调用的。


本文中的方案是对一个新的 build type  来重载 Application 代码,只在手动测试时候使用,对原来的代码不会产生任何影响。希望可以帮到你。

1、在你的工程目录的 buildscripts 下,新建一个jacoco.gradle 的文件,添加如下代码

图片

2、在 app 目录下的 build.gradle 中添加代码,来启用脚本

图片

3、执行 testDebugUnitTest 后,会在app/build/jococo/ 下看到 testDebugUnitTest.exec。记住这个文件 我们会在后面用这个文件来生产报告。

图片

4、创建jacoco 任务

Android gradle plugin 会生成不同的 variant, 所以我们要对不用的variant生成不用的任务来生产报告。

project.afterEvaluate {
   android.applicationVariants.all { variant ->
       def variantName = variant.name        def testTaskName = "test${variantName.capitalize()}UnitTest"
       tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: "$testTaskName") {
         // TODO 后面实现        }
   }}

点击Sync Gradle后,gradle task 会增加两个任务 testDebugUnitTestCoverage,testReleaseUnitTestCoverage,接下来我们增加实现报告生成的任务。

5、使用一下代码替换上一个步骤中的TODO

group = "Reporting"
   description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build."
       // 设置报告格式
   reports {
       html.enabled = true
       xml.enabled = true
   }

    // 排除不需要统计的类
   def excludes = [
           '**/R.class',
           '**/R$*.class',
           '**/BuildConfig.*',
           '**/Manifest*.*',
           '**/*Test*.*',
           'android/**/*.*',
             'androidx/**/*.*'
   ]
     // Java 类文件
   def javaClasses = fileTree(dir: variant.javaCompiler.destinationDir, excludes: excludes)
     // Kotlin 文件
   def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: excludes)
   classDirectories = files([javaClasses, kotlinClasses])
     // 源文件
   sourceDirectories = files([
           "$project.projectDir/src/main/java",
           "$project.projectDir/src/${variantName}/java",
           "$project.projectDir/src/main/kotlin",
           "$project.projectDir/src/${variantName}/kotlin"
   ])
   // 最开始我们生成的文件
   executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")

6、执行一下 testDebugUnitTestCoverage 任务,我们就会在build 目录下看到报告了

图片

经过以上步骤我们完成了一个jacoco 报告的生成过程。

关键步骤来了,如何在打包的app中开启jacoco呢?

1、新建一个staging的build type

图片

2、在src目录下,与 main 通级,新建 staging 目录

3、staging 目录下新建 java目录,并在 com.example.staging 包下新建 StagingApp.kt文件,代码如下:

package com.example.stagingimport android.Manifestimport android.app.Activityimport android.app.Applicationimport android.os.Bundleimport android.os.Environmentimport android.util.Logimport android.widget.Toastimport androidx.fragment.app.FragmentActivityimport com.tbruyelle.rxpermissions2.RxPermissionsimport java.io.Fileimport java.io.FileOutputStreamimport java.io.IOExceptionclass StagingApp : Application() {
   override fun onCreate() {
       super.onCreate()
       Log.d(TAG, "StagingApp")
       registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
           var activitySize = 0
           override fun onActivityPaused(activity: Activity?) {
           }

           override fun onActivityResumed(activity: Activity?) {
               // 第一个activity 请求 SD card 目录访问权限
               if (activitySize == 1) {
                   (activity as? FragmentActivity)?.let {
                       val rxPerm = RxPermissions(it)
                       rxPerm.request(Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe({ result ->
                           if (!result) {
                               Toast.makeText(
                                   it,
                                   "You have to grant the permission to save coverage file",
                                   Toast.LENGTH_SHORT                                ).show()
                           }
                       }, { e ->
                           e.printStackTrace()
                       })
                   }
               }
           }

           override fun onActivityStarted(activity: Activity?) {
           }

           override fun onActivityDestroyed(activity: Activity?) {
               activitySize -= 1

               if (activitySize <= 0) {
                 //所有activity被销毁后,生产报告文件
                   generateCoverageReport(createFile())
               }
           }

           override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
           }

           override fun onActivityStopped(activity: Activity?) {
           }

           override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
               activitySize += 1
           }

       })

   }

   private fun generateCoverageReport(file: File) {
       Log.d(TAG, "generateCoverageReport():${file.absolutePath}")
       FileOutputStream(file, false).use {
           val agent = Class.forName("org.jacoco.agent.rt.RT")
               .getMethod("getAgent")
               .invoke(null)

           Log.d(TAG, agent.toString())
           it.write(
               agent.javaClass.getMethod("getExecutionData", Boolean::class.javaPrimitiveType)
                   .invoke(agent, false) as ByteArray            )
       }
   }

   fun createFile(): File {
       // SD card 下面
       val file = File(Environment.getExternalStorageDirectory(), "jacoco/$DEFAULT_COVERAGE_FILE_PATH")
       if (!file.exists()) {
           try {
               file.parentFile?.mkdirs()
               file.createNewFile()
           } catch (e: IOException) {
               Log.d(TAG, "异常 : $e")
               e.printStackTrace()
           }
       }
       return file    }

   companion object {
       const val DEFAULT_COVERAGE_FILE_PATH = "jacoco-coverage.ec"
       const val TAG = "StagingApp"
   }}

4、staging 目录中新建一个 AndroidManifest.xml 文件,内容如下

<?xml version="1.0" encoding="utf-8"?><manifest
       xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.jacocomanual">
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
   <application android:name="com.example.staging.StagingApp"/></manifest>

5、IDE Build Variants 下选择 staging

图片

6、运行app并安装到设备或者模拟器,操作一下,然后按返回键关闭所有的页面,这时候会在 SD 卡目录下的生成 jacoco/jacoco-coverage.ec 文件。

图片

7、复制 jacoco-coverage.ec 文件到项目根目录下的 jacoco 文件夹

8、我们来修改jacoco的任务来生成最后的报告

图片

9、运行 testStagingUnitTest 这样就可以看到报告了

图片

 

标签:staging,覆盖率,app,手动,目录,jacoco,activity,android,Jacoco
From: https://blog.csdn.net/m0_58552717/article/details/139322066

相关文章

  • 手动Ghost还原报错 25002
    1、错误截图如下:2、原因分析:GHOST11(及以上版本)默认是不认识动态磁区的。3、解决方案:为Ghost程序使用-ntexact参数运行。这个参数-ntexact的意思是试图用与源分卷相同的方式对齐还原后的NTFS分卷。4、操作步骤右键“手动运行Ghost”,打开属性,复制所在目录,我的是“......
  • 记一次手动将LATEX数学公式转换为微信公众号支持的svg过程
    前言今日发公众号转载别人的某篇文章。本来是个很简单的活,但文章里有几个公式排版炸了。虽然可以无视,但抱着挑战的心态,我还是试着去修了下。百度,不出所料,基本都是推广,不过还是有一些有用的信息。本着和微信较劲以及绝不注册新账号的精神,我决定尝试手动将LATEX公式转svg。由于这......
  • 痞子衡嵌入式:从JLink V7.62开始优化了手动增加新MCU型号支持方法
    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是JLink7.62优化了手动增加新MCU型号支持方法。JLink工具可以说是搞单片机开发的必备神器,JLink包括一个硬件仿真器(分不同用途的EDU/BASE/PLUS/WIFI/ULTRA+/PRO)和PC机上的驱动软件(从有迹可循的2006年......
  • 【Linux】Deepin安装Anaconda后手动配置环境变量
    配置环境变量如果安装完毕后,重新打开终端,输入conda表示没找到这个命令说明没有配置环境变量那么我们首先第一件事,就是找到我们的conda安装到哪里了例如我的是安装到主目录的(默认在这的,安装的时候我没有修改安装路径)然后进入这个文件夹,进入bin,在bin下运行终端,输入pwd然后......
  • mongodb数据库:手动释放磁盘空间
    平台:阿里云mongoDB云数据库版本:Mongodb4.2数据库集群方案:一主二从三分片需求:手动释放过剩磁盘空间从文档解析可知:delete数据或者做分片数据迁移,并不会释放磁盘空间,而是将这些空间标记为reuse可重用状态,后续新写入的数据会重用这部分空间。需求是手动释放这些空间,使用compact......
  • 无需手动操作:利用 Playwright 自动上传文件
    前言Playwright是一个由Microsoft开发的自动化测试工具,它提供了跨浏览器的自动化测试能力,包括Chrome、Firefox和Safari。除了测试之外,Playwright还可以用于执行浏览器操作,例如模拟用户行为来实现文件上传功能。在本文中,我们将使用Playwright和Python实现自动上传文件......
  • 手动执行SQL触发器id自增报错处理方式
      一、查询出触发器创建的sqlSELECTdbms_metadata.get_ddl('TRIGGER','TRI_XXX_STORAGE','XSY')AStrigger_sql FROMdual; 二、删除触发器DROPTRIGGERXSY.TRI_XSY_STORAGE;三、创建触发器CREATEORREPLACETRIGGERTRI_XSY_STORAGEBE......
  • 详解Redis持久化(持久化高危漏洞利用与多种对抗方案、RDB、AOF、同步手动持久化、异步
    谨防持久化+未授权访问漏洞入侵服务器CVE编号找不到,CNVD有一个:CNVD-2015-07557(国家信息安全漏洞共享平台漏洞编号)。这是我之前写过的文章,漏洞成因、影响范围、POC与对抗方案有详解:谨防利用Redis未授权访问漏洞入侵服务器RDB(RedisDatabase、全量保存,默认方式)极简概括:通过符......
  • gcov - 标准c/c++代码覆盖率测试工具+lcov - GCC测试覆盖率的前端图形展示工具+gprof
    1、advent-calendar-of-circuits-2020-一个月每天用KiCad设计一个PCB项目GregoryDavill是来自澳大利亚的一个技术牛人,在开源硬件领域非常有名且活跃。他在2020年12月坚持每一天设计一个电路板,用KiCad完成电路设计到PCB的布局布线完成,这便是advent-calendar-of-circuits-......
  • 探讨:ARC(Automatic Reference Counting)与手动内存管理的区别及工作原理
    在iOS和macOS开发中,内存管理是一个至关重要的话题。在过去,手动内存管理是一项繁琐且容易出错的任务,而引入了ARC(AutomaticReferenceCounting,自动引用计数)之后,内存管理变得更加简单和安全。本文将详细讨论ARC和手动内存管理之间的区别,并解释ARC的工作原理。1.ARC与手......