we have a multi module project with some applications and libraries and use JaCoCo for coverage of unit tests and instrumented tests on android. Therefore we use the standard jacoco plugin for gradle together with android plugin for gradle. The JaCoCo target we use is createStandardDebugCoverageReport
.
However, we see some behaviour we can neither explain nor change: On both modules the tests run and pass, but on the one module the coverage report is created and downloaded from the emulator. On the other module, we see the error message after the test passed:
Caused by: java.lang.IllegalStateException: JaCoCo agent not started.
on logcat and thus a file with zero bytes is created.
We tested it with have two similar applications with ExampleUnitTest
and ExampleInstrumentedTest
classes.
The whole JaCoCo configuration is done in the project's root gradle.
Project's Root Gradle:
import org.ajoberstar.grgit.Grgit
buildscript {
ext {
jacocoVersion = "0.8.1"
}
repositories {
maven {
url "our.artifactory.url"
credentials {
username System.getenv("ARTIFACTORY_LOCAL_USERNAME") ? System.getenv("ARTIFACTORY_LOCAL_USERNAME") : project.property("ARTIFACTORY_LOCAL_USERNAME")
password System.getenv("ARTIFACTORY_LOCAL_PASSWORD") ? System.getenv("ARTIFACTORY_LOCAL_PASSWORD") : project.property("ARTIFACTORY_LOCAL_PASSWORD")
}
}
// The used repositories need to be configured within artifactory because we use it as dependency cache.
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0-alpha13'
classpath 'com.google.gms:google-services:3.2.0'
classpath 'io.fabric.tools:gradle:1.26.1'
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.7.5'
classpath 'org.ajoberstar:grgit:2.2.1'
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2"
classpath "org.jacoco:org.jacoco.core:${jacocoVersion}"
classpath "org.jacoco:org.jacoco.report:${jacocoVersion}"
classpath "org.jacoco:org.jacoco.agent:${jacocoVersion}"
classpath "org.codehaus.groovy:groovy-all:2.4.15"
}
}
plugins {
id "org.sonarqube" version "2.6.2"
}
// This block encapsulates custom properties and makes them available to all
// modules in the project.
ext {
versionCode = 110
versionName = "0.17.3"
currentBranchName = System.getenv("BRANCH")
def gitDirectory = file(file('.').parentFile.absolutePath + File.separator + '.git')
if (currentBranchName.equals("unknown") && gitDirectory.exists()) {
git = Grgit.open(dir: gitDirectory.parentFile)
currentBranchName = git.branch.current.name
}
artifactoryUser = System.getenv("ARTIFACTORY_LOCAL_USERNAME")
artifactoryPassword = System.getenv("ARTIFACTORY_LOCAL_PASSWORD")
minSdkVersion = 23
compileSdkVersion = 28
targetSdkVersion = 28
supportLibVersion = "28.0.0"
playServicesVersion = "16.2.0"
jacocoVersion = "0.8.1"
}
allprojects {
apply plugin: "com.jfrog.artifactory"
apply plugin: 'maven-publish'
repositories {
maven {
url "our.artifactory.url"
credentials {
username System.getenv("ARTIFACTORY_LOCAL_USERNAME") ? System.getenv("ARTIFACTORY_LOCAL_USERNAME") : project.property("ARTIFACTORY_LOCAL_USERNAME")
password System.getenv("ARTIFACTORY_LOCAL_PASSWORD") ? System.getenv("ARTIFACTORY_LOCAL_PASSWORD") : project.property("ARTIFACTORY_LOCAL_PASSWORD")
}
}
// The used repositories need to be configured within artifactory because we use it as dependency cache.
}
// This is the only place of any JaCoCo configuration
apply plugin: 'jacoco'
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
}
The following is a wear application, the working sample:
apply plugin: 'com.android.application'
configurations {
demoDebugCompile
demoReleaseCompile
standardDebugCompile
standardReleaseCompile
}
android {
signingConfigs {
ourSigningConfig {
keyAlias getEnvProperty("SIGNING_KEY_ALIAS")
keyPassword getEnvProperty("SIGNING_KEY_PASSWORD")
storeFile file(getEnvProperty("SIGNING_STORE_FILE"))
storePassword getEnvProperty("SIGNING_STORE_PASSWORD")
}
}
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "our.working.applicationid"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.ourSigningConfig
}
debug {
debuggable true
minifyEnabled false
applicationIdSuffix ".debug"
versionNameSuffix " Debug"
testCoverageEnabled true
}
}
flavorDimensions "mode"
productFlavors {
demo {
dimension "mode"
applicationIdSuffix ".demo"
versionNameSuffix " Demo"
buildConfigField "boolean", "DEMO", "true"
}
standard {
dimension "mode"
buildConfigField "boolean", "DEMO", "false"
}
}
testOptions {
unitTests {
includeAndroidResources = true
returnDefaultValues = false
}
unitTests.all {
jvmArgs '-noverify'
// https://stackoverflow.com/questions/32315978/jvm-options-in-android-when-run-gradlew-test/37593189#37593189
}
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
// External libraries
implementation fileTree(include: ['*.jar'], dir: 'libs')
// Support library
implementation 'com.google.android.support:wearable:2.1.0'
compileOnly 'com.google.android.wearable:wearable:2.1.0'
// Google Play services
implementation "com.google.android.gms:play-services-wearable:15.0.1" // TODO: use ${rootProject.ext.supportLibVersion}
// Authenticator
implementation project(':authenticator')
// Testing
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.0-beta-1'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion "${rootProject.ext.supportLibVersion}"
}
}
}
}
artifactoryPublish.skip = true
The following is a dummy application. This one gives us the agent not started exception
.
We compared the module gradle files and enhanced this one with the dependencies of the working gradle file.
apply plugin: 'com.android.application'
configurations {
demoDebugCompile
demoReleaseCompile
standardDebugCompile
standardReleaseCompile
}
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "our.nonworking.applicationid"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
consumerProguardFiles 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled false
applicationIdSuffix ".debug"
versionNameSuffix " Debug"
testCoverageEnabled true
}
}
flavorDimensions "mode"
productFlavors {
demo {
dimension "mode"
applicationIdSuffix ".demo"
versionNameSuffix " Demo"
buildConfigField "boolean", "DEMO", "true"
}
standard {
dimension "mode"
buildConfigField "boolean", "DEMO", "false"
}
}
testOptions {
unitTests {
includeAndroidResources = true
returnDefaultValues = false
}
unitTests.all {
jvmArgs '-noverify'
// https://stackoverflow.com/questions/32315978/jvm-options-in-android-when-run-gradlew-test/37593189#37593189
}
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
// Support library
implementation 'com.google.android.support:wearable:2.1.0'
compileOnly 'com.google.android.wearable:wearable:2.1.0'
// Google Play services
implementation "com.google.android.gms:play-services-wearable:15.0.1" // TODO: use ${rootProject.ext.supportLibVersion}
// Authenticator
implementation project(':authenticator')
// Testing
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.0-beta-1'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion "${rootProject.ext.supportLibVersion}"
}
}
}
}
artifactoryPublish.skip = true
We are out of ideas now. What could have an influence on that? We see the same behaviour on some libs in our project. The emulator tested on is Pixel XL API 28. Do you have some suggestion, advice or hint?
Thanks in advance.