我正在尝试定义位置,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%覆盖率,因为无法提取文件。所以我需要将文件存储在公共场所。
答案 0 :(得分:3)
但是,尚未生成覆盖率报告。要启用此选项,我们需要向我们的调试版本中添加一个属性。使用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的coverage任务,因此必须确保先执行它。接下来,我们需要运行单元测试,然后使用两个文件(
ec
和exec
)创建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。
因此,命令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
已更新为命令行方法,请遵循these步骤。
运行检测到的应用程序
一旦有了EmmaInstrumentation
类(位于ref链接中),我们就需要进行一些其他调整,以获取正在运行的应用程序的覆盖率报告。
首先,我们需要将新的Activity添加到清单中。其次,如果这是我们决定生成覆盖率报告的位置,则应允许我们的应用程序写入sdcard。为此,您应该授予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是源代码。
答案 1 :(得分:1)
缺少的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
的包。
答案 2 :(得分:1)
对我们来说,这是一个AOSP应用程序。我们通过禁用Jack编译器来生成测试和模块apk,这导致了进一步的问题。因为对我们而言,需要Jack编译器来生成coverage.em
。但是错误并不十分相关。因此没有任何进一步的线索。
因此解决方法是运行jack编译器服务器并获取使用它生成的apk。