Double Espresso not working with Robolectric

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

  • How to draw filled polygon?
  • GROUP BY with CursorLoader
  • Start a new Activity from non Activity class
  • What is the meaning of drawable-hdpi, drawable-ldpi, drawable-mdpi, drawable-xhdpi and drawable-xxhdpi
  • Android Media Player: Download to File and Stream From File
  • JNI Android - Converting char* to byte array and return it to java
  • 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.

    Related posts:

    Getting a reference to a child Fragment after the parent Fragment has been recreated
    Is there a way to test android applications directly on phone, without the emulator?
    Android adding image to picture taken with camera
    Android 6.0 Marshmallow. Cannot write to SD Card
    SpannableString with Image example
    FragmentManager is already executing transactions. When is it safe to initialise pager after commit?
  • How to get all android contacts but without those which are on SIM
  • How to convert a LatLng and a radius to a LatLngBounds in Android Google Maps API v2?
  • Android: Best XML Parsing Library?
  • Android: Sine Wave Generation
  • Android ScaleAnimation
  • How to update UI in a BroadcastReceiver
  • 3 Solutions collect form web for “Double Espresso not working with Robolectric”

    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.

    I had the same problem, seems to be the fault of Dagger 1.2 (included as a dependency in Jake’s double espresso). If you include the plain 1.1 libraries it should work.

    (Full thread here: https://groups.google.com/forum/#!topic/robolectric/xeLrnCAsq5Q)

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.