Android + JaCoCo: jacocoTestCoverageVerification never fails - android

I am trying to configure a new Android project to use JaCoCo for test coverage and fail when coverage is below a certain threshold. I have used this documentation, as well as looking at many SO posts. I expect the task to fail, since I don't have test coverage, but it succeeds without any warnings.
My :app build.gradle file includes the following:
plugins {
...
id 'jacoco'
}
jacoco {
toolVersion = "0.8.7"
reportsDirectory = layout.buildDirectory.dir('app/build/reports')
}
task jacocoTestCoverageVerification(type: JacocoCoverageVerification, dependsOn: ['jacocoTestReport']) {
onlyIf = { true }
violationRules {
failOnViolation = true
rule {
limit {
minimum = 1.0
}
}
}
}
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {
finalizedBy jacocoTestCoverageVerification
onlyIf = {true}
reports {
xml.enabled true
html.enabled true
html.outputLocation = layout.buildDirectory.dir('app/build/reports')
}
}
tasks.withType(Test) {
finalizedBy jacocoTestReport
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
android {
...
jacoco{
version = "0.8.7"
}
}
When I try to run tests, using any of the following:
./gradlew test
./gradlew jacocoTestReport
./gradlew jacocoTestCoverageVerification
The results are always the same:
...
> Task :app:connectedDebugAndroidTest
Starting 2 tests on Nexus 5X - 8.1.0
> Task :app:createDebugAndroidTestCoverageReport
> Task :app:createDebugCoverageReport
> Task :app:jacocoTestReport
> Task :app:jacocoTestCoverageVerification
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
See https://docs.gradle.org/7.2/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 31s
93 actionable tasks: 93 executed
Build Analyzer results available
1:10:48 PM: Task execution finished 'test'.
I expect the task to fail, since I have no test coverage. I have added a utility class and method, and partially implemented a test so that the JaCoCo report shows 60% coverage for one class, but this has not changed anything.

Related

How to enable code coverage with Kotlin dsl gradle?

When enabling jacoco with gradle kotlin dsl it fails because it looks at build.gradle file instead of build.gradle.kts file.
Here is the error :
##[warning]Unable to append code coverage data: Error: File or folder doesn't exist: /home/vsts/work/1/s/build.gradle
##[warning]Failed to enable code coverage: Unable to append code coverage data: Error: File or folder doesn't exist: /home/vsts/work/1/s/build.gradle
app/build.gradle.kts
plugins {
jacoco
}
tasks.withType(JacocoReport::class.java).all {
reports {
xml.isEnabled = true
xml.destination = File("$buildDir/reports/jacoco/report.xml")
}
}
tasks.withType<Test> {
jacoco {
toolVersion = "0.8.3"
reportsDir = file("$buildDir/reports/jacoco")
}
finalizedBy("jacocoTestReport")
}
Azure DevOps task
- task: Gradle#2
displayName: Gradle Build
inputs:
gradleWrapperFile: 'gradlew'
tasks: ':app:assembleDevDebug :networking:lintDebug :app:lintDevDebug --warning-mode all'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
javaHomeOption: 'JDKVersion'
sonarQubeRunAnalysis: false
codeCoverageToolOption: 'jaCoCo'
Messages
##[warning]Unable to append code coverage data: Error: File or folder doesn't exist: /home/vsts/work/1/s/build.gradle
##[warning]Failed to enable code coverage: Unable to append code coverage data: Error: File or folder doesn't exist: /home/vsts/work/1/s/build.gradle
are produced by AzureDevOps Gradle Task due to usage of option
codeCoverageToolOption: 'jaCoCo'
in your configuration of this task, because implementation of AzureDevOps Gradle Task contains hardcoded value build.gradle:
https://github.com/Microsoft/azure-pipelines-tasks/blob/9818b165441796437ca881c3f01bd7d90ee6856e/Tasks/GradleV2/gradletask.ts#L66
https://github.com/microsoft/azure-pipelines-tasks/issues/9340
quoting comment from the above bug ticket
The way for you to use code coverage would be to enable it in your build config files and publish them using another task - PublishCodeCoverageResults

Gradle .execute method showing error after gradle update

My project was running perfect with gradle plugin version 3.0.1 after updating to version 3.4.1 I am going through sync failure.
Previously I was using wrapper 4.10.1 which is now updated to 5.1.1.
afterEvaluate(new Action<Project>() {
#Override
void execute(Project project) {
tasks.getByName("assembleRelease").doLast {
tasks.copyReleaseBuild.execute() //error is here
tasks.copyReleaseBuildToXX.execute()
tasks.copyReleaseBuildToXXXX.execute()
}
}
copyReleaseBuild task is written something like below...
task copyReleaseBuild(type: Copy) {
def releaseDir = getProjectProperty('releaseDir')
if (releaseDir?.trim()) {
//if release folder is provided
def releaseAarFile =
getProjectProperty('sourceCodeDir') + "/android-corekit/kit/build/outputs/aar/kit-release.aar"
from releaseAarFile
into releaseDir
}
task copyReleaseBuildToXX(type: Copy) {
from "./build/outputs/aar/kit-release.aar"
into "../kitwrapper/libs"
}
task copyReleaseBuildToXXXX(type: Copy) {
from "./build/outputs/aar/kit-release.aar"
into "../kitwrapperapp/libs"
}
}
I have been trying to resolve from last two days but nothing is working as I lack knowledge of groovy.
Please check error log I am getting while building the project...
It happens because you are using an updated version of gradle (check the migration to gradle v5)
The following properties and methods of TaskInternal have been removed — use task dependencies, task rules, reusable utility methods, or the Worker API in place of executing a task directly.
execute()
executer
getValidators()
addValidator()
Now you can't call the execute method directly, but you have to use the tasks dependencies to obtain the same result.
Just define in your build.gradle:
task copyReleaseBuild {
dependsOn 'assembleRelease'
//...
}
and remove this:
afterEvaluate(new Action<Project>() {
#Override
void execute(Project project) {
tasks.getByName("assembleRelease").doLast {
tasks.copyReleaseBuild.execute() //error is here
}
}
Upgrading your build from Gradle 4.x to 5.0
The following properties and methods of TaskInternal have been removed — use task dependencies, task rules, reusable utility methods, or the Worker API in place of executing a task directly.
execute()
executer
getValidators()
addValidator()
in your case seems you have dependency between tasks: copyReleaseBuild must run after assembleRelease
so, this simple build.gradle represents this dependency:
task copyReleaseBuild {
dependsOn 'assembleRelease'
doLast {
println 'run copyReleaseBuild'
}
}
task assembleRelease {
doLast {
println 'run assembleRelease'
}
}
and the command gradle copyReleaseBuild
runs both tasks:
# gradle copyReleaseBuild
> Task :assembleRelease
run assembleRelease
> Task :copyReleaseBuild
run copyReleaseBuild
BUILD SUCCESSFUL in 2s
2 actionable tasks: 2 executed

FindBugs stopped working after upgrading Android Gradle Plugin from 3.1.3 to 3.2.0

I use FindBugs for static code analysis in my Android projects. The setup is the following:
quality.gradle
plugins.apply('findbugs')
task findbugs(type: FindBugs) {
ignoreFailures = false
effort = 'max'
reportLevel = 'high' // Report only high priority problems.
classes = files("${project.projectDir}/build/intermediates/classes")
source = fileTree('src/main/java')
classpath = files()
reports {
xml.enabled = true
html.enabled = false
}
excludeFilter = rootProject.file('quality/findbugs.xml')
}
build.gradle:
subprojects {
afterEvaluate {
project.apply from: '../quality/quality.gradle'
tasks.findByName('findbugs').dependsOn('assemble')
tasks.findByName('check').dependsOn('findbugs')
}
}
But after I upgraded the Gradle Android Plugin from 3.1.3 to 3.2.0 the build started failing:
./gradlew clean build
> Task :app:findbugs FAILED
No files to be analyzed
...
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:findbugs'.
> Failed to run Gradle FindBugs Worker
> Process 'Gradle FindBugs Worker 6' finished with non-zero exit value 1
Downgrading to 3.1.3 makes the build pass again. I haven't found anything related in the changelog of the Gradle Android Plugin. Can anybody point me out what's wrong with the plugin or my setup?
After a short investigation, I found out that the location of Java class files has changed from build/intermediates/classes to build/intermediates/javac. The new FindBugs configuration:
task findbugs(type: FindBugs) {
...
classes = files("${project.projectDir}/build/intermediates/javac")
...
}
The strange thing that this breaking change isn't mentioned in the Android Gradle Plugin changelog, or in the Gradle changelog.

Gradle Android: How to Display test results without using --info

I am running android tests using the Gradle Android plugin and want to see individual test results.
From answers to this Question Gradle: How to Display Test Results in the Console in Real Time? it seems I can either use --info (which prints a LOT of other verbose junk I don't care about) or use this closure which only works for the Java plugin (not the Android plugin)
test {
afterTest { desc, result ->
println "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
}
}
Is there some other option / closure I can use when I am running the connectedCheck task just to print the individual test results without all the other "verbosity".
Use Gradle info
This will print all information from Gradle:
gradle --info
or Use Android Gradle plugin:
android.testOptions.unitTests.all {
// Configure whether failing tests should fail the build
ignoreFailures false
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
}
}
or Use Gradle directly:
allprojects {
tasks.withType(Test) {
testLogging {
exceptionFormat "full"
showCauses true
showExceptions true
showStackTraces true
showStandardStreams true
events = ["passed", "skipped", "failed", "standardOut", "standardError"]
}
}
}
See: https://github.com/jaredsburrows/android-gradle-java-app-template/blob/master/gradle/compile.gradle#L20
Output:
io.github.hidroh.materialistic.data.SessionManagerTest > testView PASSED
io.github.hidroh.materialistic.data.SessionManagerTest > testIsViewFalse PASSED
io.github.hidroh.materialistic.data.SessionManagerTest > testIsViewNull PASSED
io.github.hidroh.materialistic.data.SessionManagerTest > testIsViewTrue PASSED
io.github.hidroh.materialistic.data.SessionManagerTest > testViewNoId PASSED
Source: https://github.com/hidroh/materialistic/blob/master/robolectric.gradle
Gradle Docs: https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestLogEvent.html
For me all the options mentioned in the other answer still printed a lot of verbose information. So despite the requirement that info should not be used, I successfully use the following. For example, if your tests are in the package com.example.android, you can use:
gradle --info connectedDebugAndroidTest | grep "com\.example\.android\..* >"
Will print e. g.:
com.example.android.login.LoginActivityTest > enterCredentialsTest[Testing_emulator(AVD) - 9] SUCCESS
And the word "SUCCESS" will be green, which is awesome.
For Android Studio (tested on com.android.tools.build:gradle:2.1.0 and gradle version gradle-2.10) I added the following section to print exceptions in full format as well as logging every executed test:
apply plugin: 'com.android.application'
android { ... }
dependencies { ...}
tasks.withType(Test) {
testLogging {
exceptionFormat "full"
}
afterTest { desc, result ->
println "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
}
}

Allow unstable Android Gradle builds on Jenkins

Hi I have set up my Android project on Jenkins to provide CI. Its working well, running tests on a connected Android handset. The tests run on the Android Test Framework which extends jUnit3.
Unfortunately, the build is marked as a failure if there are any test failures. I'd like to be able to improve this in two ways:
Allowing unstable builds
Being able to mark known test failures
For item 1 I tried adding this to the project build.gradle:
connectedCheck {
ignoreFailures = true
}
But it has no effect. Looking at the build log, I realised the actual test task is called connectedInstrumentTest, but this task is not found:
connectedInstrumentTest {
ignoreFailures = true
}
causes:
Could not find method connectedInstrumentTest() for arguments [build_4ldpah0qgf0ukktofecsq41r98$_run_closure3#9cd826] on project ':Playtime'.
That am I missing?
Thanks
EDIT: Heres my project build.gradle, nothing special:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.+'
}
}
apply plugin: 'android'
dependencies {
compile files('libs/android-support-v4.jar')
}
android {
compileSdkVersion 17
buildToolsVersion "18.0.1"
defaultConfig {
minSdkVersion 8
targetSdkVersion 16
testPackageName "com.bb.pt.test"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
}
}
connectedCheck {
ignoreFailures = true
}
My gradle settings in jenkins:
switches: --stacktrace --info
tasks: :pt:assembleDebug :pt:assembleTest :pt:connectedCheck
EDIT:
I built gradlew and tried that. Same output. I don't want the build to FAIL if there are test failures:
:pt:connectedInstrumentTest FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':pt:connectedInstrumentTest'.
> There were failing tests. See the report at: file:///home/simon/WorkingCopies/bb/code/trunk/pt/pt/build/reports/instrumentTests/connected/index.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output.
BUILD FAILED
I tried to qualify the task name in build.gradle:
task connectedCheck {
ignoreFailures = true
}
But it thinks I am trying to add a new task rather than modify the existing one.
FAILURE: Build failed with an exception.
* Where:
Build file '/home/simon/WorkingCopies/bb/code/trunk/pt/pt/build.gradle' line: 31
* What went wrong:
A problem occurred evaluating project ':pt'.
> Cannot add task ':pt:connectedCheck' as a task with that name already exists.
After our conversation I believe that:
the problem is gradle configuration only and not jenkins related. Get it to work in gradle.
in gradle I believe (though I am not an expert) you should get the connectedInstrumentTest to ignore failures, but your attempt to use the following failed
connectedInstrumentTest {
ignoreFailures = true
}
maybe the solution is to wrap this config node like this:
project.gradle.taskGraph.whenReady {
connectedInstrumentTest {
ignoreFailures = true
}
}
https://github.com/stanfy/hotandroid/blob/master/part0/build.gradle

Categories

Resources