I currently am using the createDebugAndroidTestCoverageReport to run my android instrumentation tests and generate a coverage report. The only issue that I am running into is that there are packages that are generated from Realm and Databinding and these classes are also being included in my coverage report. How can I configure jacoco to exclude these packages?
test {
jacoco {
append = false
destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
classDumpFile = file("$buildDir/jacoco/classpathdumps")
excludes = []
}
}
Click here for more details on official Jacoco Gradle Plugin
When you are defining the debugTree you can add the fileFilters to be excluded.
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/package/**']
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter)
}
Related
I am working on the SonarQube code coverage...I have implemented locally and able to see jacocoTestReprt and all other necessary files...but when I run the task on Jenkins jacoco not able to generate any files.
In app/build.gradle
task jacocoTestReport(type: JacocoReport, dependsOn:
[‘testProdReleaseUnitTest’]) {
reports {
xml.enabled = true
html.enabled = true }
def fileFilter = ['/R.class', '/R$.class', '**/BuildConfig.',
'/Manifest*.*', 'android//.'] def debugTree = fileTree(dir:
"${buildDir}/intermediates/javac/prodRelease/classes", excludes:
fileFilter) def mainSrc = "${project.projectDir}/src/main/java"
getSourceDirectories().setFrom(files([mainSrc]))
getClassDirectories().setFrom(files([debugTree]))
getExecutionData().setFrom(fileTree(dir: "$buildDir", includes:
["jacoco/testProdReleaseUnitTest.exec"])
}
Jenkins artifacts:
What i want:
I want to match code coverage threshold to minimum value like 60% etc in Android gradle.
What i have tried
stack overflow question i have looked into
jacoco plugin gradle
Problem i am facing
My Gradle file is written like:
apply plugin: 'com.android.application'
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.7.6.201602180812"
reportsDir = file("$buildDir/customJacocoReportDir")
}
def coverageSourceDirs = [
'src/main/java',
]
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination "${buildDir}/jacocoHtml"
}
}
jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = 0.5
}
}
rule {
enabled = false
element = 'CLASS'
includes = ['org.gradle.*']
limit {
counter = 'LINE'
value = 'TOTALCOUNT'
maximum = 0.3
}
}
}
}
Now, When i sync my gradle file i face following erros
Could not find method jacocoTestReport() for arguments [build_5t0t9b9hth6zfihsyl5q2obv8$_run_closure2#41a69b20] on project ':app' of type org.gradle.api.Project.
and if i comment jacocoTestReport task then
Could not find method jacocoTestCoverageVerification() for arguments [build_5t0t9b9hth6zfihsyl5q2obv8$_run_closure2#3da790a8] on project ':app' of type org.gradle.api.Project.
I am not able to understand what exactly going on here. Why jacocoTestCoverageVerification method not in plugin. What i am doing wrong.
Is it something gradle is picking jacoco plugin from android plugin?
I have tried mentioning version of jacoco to 0.6.3 as mentioned in there doc that jacocoTestCoverageVerification method is written above this version.
It'll be very helpful if anybody can sort out this problem.
Let me know in any other info required.
Thanks
This problem keeps haunting me for a few times, every time the keyword android jacocoTestCoverageVerification leads me to this page and gets no answer. Finally, I succeeded make the jacoco work and I'd like to share my solution here.
The reason gradle can't find jacocoTestCoverageVerification and jacocoTestReport is because For projects that also apply the Java Plugin, the JaCoCo plugin automatically adds the following tasks jacocoTestReport and jacocoTestCoverageVerification.
It means for projects that not appling the java Plugin, it will not add jacocoTestReport and jacocoTestCoverageVerification.
So we have to add them yourself.
Follow the link: Code Coverage for Android Testing, we can add the task jacocoTestReport.
And the same way, we also can add the task jacocoTestCoverageVerification.
Full function goes like
// https://engineering.rallyhealth.com/android/code-coverage/testing/2018/06/04/android-code-coverage.html
ext.enableJacoco = { Project project, String variant ->
project.plugins.apply('jacoco')
final capVariant = variant.capitalize()
StringBuilder folderSb = new StringBuilder(variant.length() + 1)
for (int i = 0; i < variant.length(); i++) {
char c = variant.charAt(i)
if (Character.isUpperCase(c)) {
folderSb.append('/')
folderSb.append(Character.toLowerCase(c))
} else {
folderSb.append(c)
}
}
final folder = folderSb.toString()
project.android {
buildTypes {
debug {
testCoverageEnabled true
}
}
testOptions {
unitTests.all {
jacoco {
//You may encounter an issue while getting test coverage for Robolectric tests.
//To include Robolectric tests in the Jacoco report, one will need to set the includeNolocationClasses flag to true.
// This can no longer be configured using the android DSL block, thus we search all tasks of Test type and enable it
includeNoLocationClasses = true
}
}
}
jacoco {
version = '0.8.1'
}
}
project.jacoco {
toolVersion = '0.8.1'
}
project.tasks.create(
name: 'jacocoTestCoverageVerification',
type: JacocoCoverageVerification,
dependsOn: ["test${capVariant}UnitTest",
"create${capVariant}CoverageReport"
]
) {
onlyIf = {
true
}
violationRules {
rule {
limit {
minimum = 0.5
}
}
rule {
enabled = false
element = 'CLASS'
includes = ['org.gradle.*']
limit {
counter = 'LINE'
value = 'TOTALCOUNT'
maximum = 0.3
}
}
}
def coverageSourceDirs = [
"src/main/java",
"src/main/kotlin"
]
def fileFilter = [
'**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/*_MembersInjector.class',
'**/Dagger*Component.class',
'**/Dagger*Component$Builder.class',
'**/*Module_*Factory.class',
'**/*_MembersInjector.class',
'**/Dagger*Subcomponent*.class',
'**/*Subcomponent$Builder.class',
'**/Manifest*.*'
]
def javaClasses = fileTree(
dir: "${project.buildDir}/intermediates/javac/$folder",
excludes: fileFilter
)
def kotlinClasses = fileTree(
dir: "${project.buildDir}/tmp/kotlin-classes/$variant",
excludes: fileFilter
)
group = "Reporting"
description = "Applying Jacoco coverage verification for the ${project.name} with the " +
"$variant variant."
classDirectories = files([javaClasses], [kotlinClasses])
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = fileTree(dir: "${project.buildDir}", includes: [
"jacoco/testDebugUnitTest.exec",
"outputs/code_coverage/debugAndroidTest/connected/*.ec",
"outputs/code_coverage/connected/*.ec" //Check this path or update to relevant path
])
}
project.tasks.create(
name: 'jacocoTestReport',
type: JacocoReport,
dependsOn: ["test${capVariant}UnitTest",
"create${capVariant}CoverageReport"
]
) {
def coverageSourceDirs = [
"src/main/java",
"src/main/kotlin"
]
def fileFilter = [
'**/R.class',
'**/R$*.class',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/*_MembersInjector.class',
'**/Dagger*Component.class',
'**/Dagger*Component$Builder.class',
'**/*Module_*Factory.class',
'**/*_MembersInjector.class',
'**/Dagger*Subcomponent*.class',
'**/*Subcomponent$Builder.class',
'**/Manifest*.*'
]
def javaClasses = fileTree(
dir: "${project.buildDir}/intermediates/javac/$folder",
excludes: fileFilter
)
def kotlinClasses = fileTree(
dir: "${project.buildDir}/tmp/kotlin-classes/$variant",
excludes: fileFilter
)
group = "Reporting"
description = "Generate Jacoco coverage reports for the ${project.name} with the " +
"$variant variant."
classDirectories = files([javaClasses], [kotlinClasses])
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = fileTree(dir: "${project.buildDir}", includes: [
"jacoco/testDebugUnitTest.exec",
"outputs/code_coverage/debugAndroidTest/connected/*.ec",
"outputs/code_coverage/connected/*.ec" //Check this path or update to relevant path
])
onlyIf = {
true
}
println project
println "current $project buildDir: $buildDir project buildDir: ${project.buildDir}"
System.out.flush()
reports {
html.enabled = true
html.destination file("reporting/jacocohtml")
}
}
}
Gist version
First of all check you gradle verison:
For projects that also apply the Java Plugin, The JaCoCo plugin automatically adds the following tasks:
gradle 3.3 (jacocoTestReport task)
https://docs.gradle.org/3.3/userguide/jacoco_plugin.html#sec:jacoco_tasks
gradle 3.5 (jacocoTestReport , jacocoTestCoverageVerification task)
https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_tasks
Maybe for earlier versions of gradle you need add jacoco dependencies:
...
dependencies {
сlasspath (
[group: 'org.jacoco', name: 'org.jacoco.agent', version: version: '0.7.7.201606060606'],
[group: 'org.jacoco', name: 'org.jacoco.ant', version: version: '0.7.7.201606060606']
)}
...
I have a question that my jacoco can cover androidTest directory not test directory.How can I do make jacoco also covered test directory.
This is my gradle
apply plugin: "jacoco"
buildTypes {
debug{
testCoverageEnabled true
}
}
jacoco {
toolVersion = "0.7.6.201602180812"
reportsDir = file("$buildDir/customJacocoReportDir")}
When I run gradlew createDebugCoverageReport. It worked. But only AndroidTest covered . Junit not. In project of Android Studio, only androidTest directory covered,test directory not covered.
Here is my jacoco setup which covers not only androidTest directory and also able to work with different flavors.
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.7.7.201606060606"
}
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
}
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
// If buildtype and flavor combo is not available, skip
if (ignoreBuildFlavor(productFlavorName, buildTypeName)) {
return
}
def sourceName, sourcePath
if (!productFlavorName) {
sourceName = sourcePath = "${buildTypeName}"
} else {
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
sourcePath = "${productFlavorName}/${buildTypeName}"
}
def testTaskName = "test${sourceName.capitalize()}UnitTest"
// 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*.*',
'**/*$Lambda$*.*', // Jacoco can not handle several "$" in class name.
'**/*$inlined$*.*', // Kotlin specific, Jacoco can not handle several "$" in class name.
'**/*Module.*', // Modules for Dagger.
'**/*Dagger*.*', // Dagger auto-generated code.
'**/*MembersInjector*.*', // Dagger auto-generated code.
'**/*_Provide*Factory*.*',// Dagger auto-generated code.
'**/*$Icepick*.*']
)
def coverageSourceDirs = [
"src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"
]
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")
reports {
xml.enabled = true
html.enabled = true
}
}
}
}
And don't forget to add this line to your build.gradle:
apply from: "jacoco.gradle"
Finally,I used android-junit-jacoco-plugin.This plugin solved my problem.But if you use this plugin,the unit test have to be all success.If not,The coverage report will not be created by jacoco.
I have a project with two modules, one containing the code (submodule1), and the other containing the unit tests(submodule2). Running coverage tests on submodule1 provides coverage results of 0%, since the methods are supposed to be tested in submodule2. Running coverage tests on submodule2 however only returns coverage for classes defined in that module.
I have been trying to create a project-wide coverage and I've found the following:
subprojects {
apply plugin: 'jacoco'
def coverageSourceDirs = [
'src/main/java'
]
jacocoTestReport {
additionalSourceDirs = files(sourceSets.main.allSource.srcDirs)
sourceDirectories = files(sourceSets.main.allSource.srcDirs)
classDirectories = files(sourceSets.main.output)
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
}
test.finalizedBy(project.tasks.jacocoTestReport)
}
task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
additionalSourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs)
sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
classDirectories = files(subprojects.sourceSets.main.output)
dependsOn = subprojects.test
executionData = files(subprojects.jacocoTestReport.executionData)
reports {
html.enabled = true
xml.enabled = true
}
onlyIf = {
true
}
doFirst {
executionData = files(executionData.findAll {
it.exists()
})
}
}
However I'm unable to run it, since I get this error when trying to run ./gradlew jacocoRootReport:
Could not find method jacocoTestReport() for arguments [build_6nnhcgikryugeat1c382yp5m6$_run_closure3$_closure6#1a3e8e24] on root project 'MyProject'.
How can I fix this?
I'm trying to get Jacoco working with Espresso however when I try to follow an example like
http://raptordigital.blogspot.com/2014/08/code-coverage-reports-using-robolectric.html
The jacocoTestReport task depends on the 'testDebug' task, which Gradle is telling me can't be found in the project. How do I resolve this?
testDebug is the task for your unit tests (given that you are using android gradle plugin v1.2+ or some other unit tests plugin). What you are looking for is connectedAndroidTest task or its flavour.
Here is the complete jacocoTestReport task that works with espresso tests.
apply plugin: 'jacoco'
jacoco {
version "0.7.1.201405082137"
}
task jacocoTestReportAndroidTest(type: JacocoReport, dependsOn: "connectedAndroidTest") {
def coverageSourceDirs = [
'src/main/java'
]
group = "Reporting"
description = "Generates Jacoco coverage reports"
reports {
csv.enabled false
xml{
enabled = true
destination "${buildDir}/reports/jacoco/jacoco.xml"
}
html{
enabled true
destination "${buildDir}/jacocoHtml"
}
}
classDirectories = fileTree(
dir: 'build/intermediates/classes',
excludes: ['**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Activity*.*',
'**/*Fragment*.*'
]
)
sourceDirectories = files(coverageSourceDirs)
additionalSourceDirs = files(coverageSourceDirs)
if (project.hasProperty('coverageFiles')) {
// convert the comma separated string to an array to create an aggregate report from
// multiple coverage.ec files
def coverageFilesArray = coverageFiles.split(',')
executionData = files(coverageFilesArray)
}
else {
executionData = files('build/outputs/code-coverage/connected/coverage.ec')
}
}