[英]JaCoCo doesn't work with Robolectric tests
I wanted to generate code coverage reports on my JUnit tests in my android project so I added the JaCoCo gradle plugin.我想为我的 android 项目中的 JUnit 测试生成代码覆盖率报告,因此我添加了 JaCoCo gradle 插件。 This is my project level
build.gradle
file:这是我的项目级别
build.gradle
文件:
apply plugin: 'jacoco'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0-beta6'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
allprojects {
repositories {
jcenter()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
subprojects { prj ->
apply plugin: 'jacoco'
jacoco {
toolVersion '0.7.6.201602180812'
}
task jacocoReport(type: JacocoReport, dependsOn: 'testDebugUnitTest') {
group = 'Reporting'
description = 'Generate Jacoco coverage reports after running tests.'
reports {
xml {
enabled = true
destination "${prj.buildDir}/reports/jacoco/jacoco.xml"
}
html {
enabled = true
destination "${prj.buildDir}/reports/jacoco"
}
}
classDirectories = fileTree(
dir: 'build/intermediates/classes/debug',
excludes: [
'**/R*.class',
'**/BuildConfig*',
'**/*$$*'
]
)
sourceDirectories = files('src/main/java')
executionData = files('build/jacoco/testDebugUnitTest.exec')
doFirst {
files('build/intermediates/classes/debug').getFiles().each { file ->
if (file.name.contains('$$')) {
file.renameTo(file.path.replace('$$', '$'))
}
}
}
}
}
jacoco {
toolVersion '0.7.6.201602180812'
}
task jacocoFullReport(type: JacocoReport, group: 'Coverage reports') {
group = 'Reporting'
description = 'Generates an aggregate report from all subprojects'
//noinspection GrUnresolvedAccess
dependsOn(subprojects.jacocoReport)
additionalSourceDirs = project.files(subprojects.jacocoReport.sourceDirectories)
sourceDirectories = project.files(subprojects.jacocoReport.sourceDirectories)
classDirectories = project.files(subprojects.jacocoReport.classDirectories)
executionData = project.files(subprojects.jacocoReport.executionData)
reports {
xml {
enabled = true
destination "${buildDir}/reports/jacoco/full/jacoco.xml"
}
html {
enabled = true
destination "${buildDir}/reports/jacoco/full"
}
}
doFirst {
//noinspection GroovyAssignabilityCheck
executionData = files(executionData.findAll { it.exists() })
}
}
It works great by running ./gradlew jacocoFullReport
.通过运行
./gradlew jacocoFullReport
。 But unfortunately coverage is not reported for the tests that are run with the RobolectricTestRunner
(instructions that are obviously called in the tests are not reported as covered).但不幸的是,没有报告使用
RobolectricTestRunner
运行的测试的覆盖率(在测试中明显调用的指令未报告为已覆盖)。 Tests with no @RunWith
annotation or run with MockitoJUnitTestRunner
report coverage just fine.没有
@RunWith
注释的测试或使用MockitoJUnitTestRunner
报告覆盖率运行都很好。
Any help would be appreciated to fix this problem.解决此问题的任何帮助将不胜感激。
Update 1: I noticed that I should be using the RobolectricGradleTestRunner
.更新 1:我注意到我应该使用
RobolectricGradleTestRunner
。 But it didn't help.但这没有帮助。
It is known issue with the possible workaround - https://github.com/jacoco/jacoco/pull/288 已知问题可能的解决方法 - https://github.com/jacoco/jacoco/pull/288
Or downgrade jacoco version to 0.7.1.201405082137
或者将jacoco版本降级到
0.7.1.201405082137
UPDATE UPDATE
The workaround is not needed anymore. 不再需要解决方法。 You must use gradle version
2.13
and jacoco version 0.7.6.201602180812
. 您必须使用gradle版本
2.13
和jacoco版本0.7.6.201602180812
。
Update root build.gradle
: 更新root
build.gradle
:
buildscript {
dependencies {
classpath 'org.jacoco:org.jacoco.core:0.7.6.201602180812'
}
}
task wrapper( type: Wrapper ) {
gradleVersion = '2.13'
}
Run ./gradlew wrapper
运行
./gradlew wrapper
Update project build.gradle
: 更新项目
build.gradle
:
apply plugin: 'jacoco'
android {
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
}
I was facing the same issue but now it is resolved for me by following this link, 我遇到了同样的问题,但现在通过以下链接解决了这个问题,
issue link: https://github.com/robolectric/robolectric/issues/2230 问题链接: https : //github.com/robolectric/robolectric/issues/2230
Solution for this problem is mentioned here: 这里提到了解决这个问题的方法:
https://github.com/dampcake/Robolectric-JaCoCo-Sample/commit/f9884b96ba5e456cddb3d4d2df277065bb26f1d3 https://github.com/dampcake/Robolectric-JaCoCo-Sample/commit/f9884b96ba5e456cddb3d4d2df277065bb26f1d3
I had the same issue. 我遇到过同样的问题。 I changed the jacoco plugin version and added includenolocationclasses property.
我更改了jacoco插件版本并添加了includenolocationclasses属性。 Here is the working jacoco.gradle file (I am using gradle wrapper 2.14.1):
这是工作的jacoco.gradle文件(我使用的是gradle wrapper 2.14.1):
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.7.6.201602180812"
}
android {
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
}
project.afterEvaluate {
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type -> type.name }
def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
println(buildTypes)
println(productFlavors)
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
def sourceName, sourcePath
if (!productFlavorName) {
sourceName = sourcePath = "${buildTypeName}"
} else {
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
sourcePath = "${productFlavorName}/${buildTypeName}"
}
def testTaskName = "test${sourceName.capitalize()}UnitTest"
println("SourceName:${sourceName}")
println("SourcePath:${sourcePath}")
println("testTaskName:${testTaskName}")
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
task "${testTaskName}Coverage" (type:JacocoReport, dependsOn: "$testTaskName") {
group = "Reporting"
description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
classDirectories = fileTree(
dir: "${project.buildDir}/intermediates/classes/${sourcePath}",
excludes: ['**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/Manifest*.*']
)
def coverageSourceDirs = [
"src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"
]
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")
println("${project.buildDir}/jacoco/${testTaskName}.exec")
reports {
xml.enabled = true
html.enabled = true
}
}
}
}
}
The accepted answer is a bit dated. 接受的答案有点过时了。 Here is a similar fix we just implemented.
这是我们刚刚实施的类似修复程序。 In the module (ie app) build.gradle add:
在模块(即app)build.gradle中添加:
apply plugin: 'jacoco'
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
This does require JaCoCo 7.6+, but you are likely using it already. 这确实需要JaCoCo 7.6+,但您可能已经使用它了。
Notes for Studio: Studio的注释:
This is an old issue, but for those who are still facing, it is worth mentioning that if you are setting up JaCoCo + Robolectric + Espresso - you will indeed be using includeNoLocationClasses
, but still will see this error with Java9+ and probably end up here.这是一个老问题,但对于那些仍然面临的人来说,值得一提的是,如果您正在设置 JaCoCo + Robolectric + Espresso - 您确实会使用
includeNoLocationClasses
,但仍然会在 Java9+ 中看到此错误,并且可能会在这里结束. Add the below snippet to your module build.gradle file将以下代码片段添加到您的模块build.gradle文件中
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.