Jacoco覆盖率报告问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jacoco覆盖率报告问题相关的知识,希望对你有一定的参考价值。

我正在尝试定义位置,jacoco将为真实设备上运行的仪器测试创建覆盖文件。

从gradle任务的--debug运行中我看到这个日志:

[DEBUG] [org.gradle.api.Task] DeviceConnector 'Nexus 5X - 6.0.1': installing /home/martin/workspace/lib/my-lib/build/outputs/apk/my-lib-debug-androidTest-unaligned.apk
[INFO] [org.gradle.api.Task] Starting 1 tests on Nexus 5X - 6.0.1
[INFO] [org.gradle.api.Task]  de.my.lib.utils.UtilsTest testMyTest[Nexus 5X - 6.0.1] [32mSUCCESS [0m
[DEBUG] [org.gradle.api.Task] DeviceConnector 'Nexus 5X - 6.0.1': fetching coverage data from /data/data/de.my.lib.test/coverage.ec
[DEBUG] [org.gradle.api.Task] DeviceConnector 'Nexus 5X - 6.0.1': uninstalling de.my.lib.test 13:46:14.538
[DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Finished executing task ':my-lib:connectedDebugAndroidTest'

我尝试了三种方法来定义位置:

在清单文件中使用<instrumentation>标记并没有改变任何东西。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="de.my.lib.test"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <instrumentation
        android:name="android.support.test.runner.AndroidJUnitRunner"
        xmlns:tools="http://schemas.android.com/tools"
        android:targetPackage="de.my.lib.test"
        tools:replace="android:targetPackage">
        <meta-data
            android:name="coverage"
            android:value="true" />
        <meta-data
            android:name="coverageFile"
            android:value="/sdcard/coverage.ec" />
    </instrumentation>
</manifest>

我用gradle尝试了它,但输出是相同的:

defaultConfig 
    // unimportant stuff
    testApplicationId "de.my.lib.test"

    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    testInstrumentationRunnerArgument('coverageFile', '/sdcard/coverage.ec')

最后我用adb命令试了一下:

adb shell am instrument -w -e coverage true -e coverageFile /sdcard/coverage.ec de.my.lib.test/android.support.test.runner.AndroidJUnitRunner

但在那里我得到2个错误:

de.my.lib.utils.UtilsTest :.找不到类:org.jacoco.agent.rt.internal_773e439.CoverageTransformer。时间:0,072

好的(1个测试)

错误:无法生成emma覆盖率。

我完全迷失在这里。有任何想法吗?

背景为什么我需要将它存储在另一个地方:某些设备和Android版本上有adb shell run-as命令的错误,因此我的测试设备场中的设备返回0%覆盖率,因为无法提取文件。所以我需要将文件存储在公共场所。

答案

但是,尚未生成覆盖率报告。要启用此选项,我们需要向调试版本变量添加属性。使用Android插件DSL,我们可以通过testCoverageEnabled属性启用覆盖:

android 
    ...
    buildTypes 
        debug 
            testCoverageEnabled true
        
        ...
    

要在使用2.2版本的Android Gradle插件时启用本地测试的覆盖率报告,您需要在应用的build.gradle中启用它:

android 
    //...

    testOptions 
        unitTests.all 
            jacoco 
                includeNoLocationClasses = true
            
        
    

Jacoco执行的检测生成执行文件,其中包含创建报告所需的数据(html,XML等)。这里的问题是,Espresso生成.ec文件,而单元测试执行生成.exec文件...我们有不同的格式!

由于我们无法配置Espresso的覆盖任务,我们必须确保首先执行它。接下来,我们需要运行单元测试,然后使用两个文件(ecexec)创建coverage数据。

要启用此功能,我们需要再次编辑我们的任务,并将coverage.ec文件作为参数添加到executionData属性中:

apply plugin: 'jacoco'

task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) 

    reports 
        xml.enabled = true
        html.enabled = true
    

    def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
    def debugTree = fileTree(dir: "$buildDir/intermediates/classes/debug", excludes: fileFilter)
    def mainSrc = "$project.projectDir/src/main/java"

    sourceDirectories = files([mainSrc])
    classDirectories = files([debugTree])
    executionData = fileTree(dir: "$buildDir", includes: [
            "jacoco/testDebugUnitTest.exec", 
            "outputs/code-coverage/connected/*coverage.ec"
    ])

由于Android Gradle插件2.2。+现在为每次执行生成一个覆盖文件,使用文件名中的设备/模拟器,现在我们需要将每个文件传递给执行数据,因为文件名现在是动态的。另外,我添加了createDebugCoverageReport任务作为我们自定义任务的依赖项,因此我们不需要手动运行它:)

最后,当我们执行这两项任务时,首先运行Espresso测试,我们将获得统一的覆盖率报告!

gradle clean jacocoTestReport

有关详细说明,请参阅here

Edit:

因此,命令adb shell am instrument不会生成报告,为此您必须使用gradle解决方案来处理它。如果你真的想要自己测试它,那么你必须使用custom runner

参考文献:

1)How to Generate Android Testing Report in HTML Automatically

2)How to retrieve test results when using "adb shell am instrument"

3)https://github.com/jsankey/android-junit-report


Test from the command line


更新为命令行方法遵循these步骤。

运行已检测的应用程序

一旦我们有了EmmaInstrumentation类(在ref链接中),我们需要进行一些调整才能获得正在运行的应用程序的覆盖率报告。

首先,我们需要将新的Activity添加到清单中。其次,如果我们决定生成覆盖率报告,我们应该允许我们的应用程序写入SD卡。要做到这一点,你应该授予android.permission.WRITE_EXTERNAL_STORAGE权限。然后,是时候构建和安装检测的apk:

$ ant clean
$ ant instrument
$ ant installi

一切都准备好启动仪表化的应用程序

$ adb shell am instrument -e coverage true \
    -w com.example.i2at.tc/\
        com.example.instrumentation.EmmaInstrumentation

Here是源代码。

另一答案

缺少的CoverageTransformer类提示缺少对JaCoCo代理运行时的依赖。一种简单的解决方案可能是,为它提供它所需要的(在设备上可用):

testImplementation "org.jacoco:org.jacoco.agent:0.8.3"

如果你得到一个FileNotFoundException,当ClassNotFoundException被修复时,请确保有权写入SD卡,这似乎是另一个可能的陷阱:

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

正如我刚才所见,还有一个org.jacoco.report包,可以选择添加:

testImplementation "org.jacoco:org.jacoco.report:0.8.3"

org.jacoco.agent在每种情况下都包含类CoverageTransformer

另一答案

对我们来说这是一个AOSP应用程序。我们正在生成带有禁用Jack编译器的测试和模块apks,这导致了这个进一步的问题。因为对我们来说杰克编译器需要生成coverage.em。但错误并不十分重要。所以没有任何进一步的线索。

所以解决方法是运行jack编译器服务器并获取使用它生成的apks。

以上是关于Jacoco覆盖率报告问题的主要内容,如果未能解决你的问题,请参考以下文章

使用Maven生成JaCoCo代码覆盖率报告

ANT 任务:使用 JaCoCo 的 SonarQube 扫描仪代码覆盖率报告

在没有 Maven 或 Gradle 的情况下运行 jacoco 报告

Jacoco简析原理 和 改造新增代码覆盖率标识进入报告

使用 Gradle 过滤 JaCoCo 覆盖率报告

如何在 Maven 测试阶段生成 jacoco 报告