I'm trying to run Espresso (using Double Espresso) via instrumentation testing and unit tests via Robolectric. What I have so far is largely based on the deckard-gradle example.
Note: Gradle 1.10
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.10.4'
classpath 'org.robolectric.gradle:gradle-android-test-plugin:0.10.0'
}
}
apply plugin: 'android'
apply plugin: 'android-test'
android {
compileSdkVersion 19
buildToolsVersion '19.0.3'
defaultConfig {
packageName = 'com.example.app'
minSdkVersion 9
targetSdkVersion 19
versionCode 1
versionName '1.0.0'
testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
buildTypes {
debug {
debuggable = true
runProguard = false
}
release {
debuggable = false
runProguard = true
}
}
sourceSets {
androidTest {
setRoot('src/test')
}
}
packagingOptions {
exclude 'LICENSE.txt'
}
}
androidTest {
include '**/*Test.class'
exclude '**/espresso/**/*.class'
maxHeapSize = "2048m"
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.android.support:support-v4:19.1.0'
androidTestCompile('com.jakewharton.espresso:espresso:1.1-r3')
androidTestCompile('com.jakewharton.espresso:espresso-support-v4:1.1-r3') {
exclude group: 'com.android.support', module: 'support-v4'
}
androidTestCompile('junit:junit:4.11') {
exclude module: 'hamcrest-core'
}
androidTestCompile('org.robolectric:robolectric:2.3') {
exclude module: 'classworlds'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-plugin-registry'
exclude module: 'maven-profile'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'nekohtml'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-http-shared'
exclude module: 'wagon-provider-api'
}
androidTestCompile 'com.squareup:fest-android:1.0.8'
}
My directory structure is as follows, where com.example.app.espresso
needs to be run as connectedAndroidTest
and com.example.app.data
as test
:
src |- debug |- main |- release |- test |- java |- com |- example |- app |- espresso |- HomeActivityTest.java |- data |- DataTest.java |- resources |- data_input.json
So when I run gradle clean test
, I get errors not recognizing Espresso imports in HomeActivityTest.java
.
When I run gradle clean connectedAndroidTest
, I get errors not recognizing JUnit4 annotations in DataTest.java
(FailedToCreateTests.testSuiteConstructionFailed
).
If I take either part out (dependencies and sources), the other one works fine independently but not with everything included together.
Note: I tried importing Espresso jar's locally (no Double Espresso), same way deckard-gradle does it, which works until I use anything from the support-v4
library in the Espresso test (com.jakewharton.espresso:espresso-support-v4
appears to solve that, which there is no alternative for with local jar's), then it explodes into FailedToCreateTests.testSuiteConstructionFailed
.
Has anyone got this structure working? Is there any way to exclude source paths from each target?
Any solutions (full or partial) would be appreciated.
This is occurring because the Double Espresso artifacts are distributed as .aar files and the compile task that Robolectric generates for running the tests does not depend upon a task that unpackages .aar files that are part of the androidTestCompile dependency configuration.
Since you typically won't run your espresso tests as part of the task that runs your unit tests, you can safely exclude the espresso tests from the compilation task generated by the Robolectric plugin. I do this by adding a dependency to the compilation task generated by the Robolectric plugin to my build.gradle that touches up the source property. Example code below. Make sure to touch up the name of the robolectric generated compile task ('compileTestDebugJava' in my example) and your 'exclude' for your espresso tests as necessary.
tasks.whenTaskAdded { theTask ->
if ("compileTestDebugJava".toString().equals(theTask.name.toString())) {
def cleanupTask = "touchUpRobolectricSourceSet"
project.task(cleanupTask) << {
FileTree tree = fileTree(dir: 'src/test/java')
tree.exclude '**/espresso/**/*.java'
theTask.source = tree
}
theTask.dependsOn(cleanupTask)
}
}
Eventually, I abandoned the idea of using Double Espresso and going with the approach that deckard-gradle takes - manually importing the Espresso jar's (espresso
, testrunner
and testrunner-runtime
).
It appears that either Double Espresso is doing more than just wrapping the jar's as aar's and hosting them or the fact that they are aar's causes problems. Would be interested to know why.
To avoid keeping local dependencies, I uploaded the Espresso jar's to a Maven repo, daisy-chained them (espresso
depends on testrunner-runtime
, testrunner-runner
depends on testrunner
) and included all the third-party dependencies (Guava, Hamcrest, Dagger etc) in the POM. If you don't have a hosted Maven repo, you can use GitHub as your repo: https://stackoverflow.com/a/14013645/818393.
Admittedly, not the best solution but it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With