Android project with Robolectric and Gradle (Android studio)

18,799

Solution 1

This is unlikely to work out of the box as src/test isn't used automatically. You'd need to create a test task automatically that compiles this source sets, sets the right dependencies and run it.

We intend to support this in the future but right now you'd need to do this manually.

Solution 2

@Aldo Borrero, finally it seems that someone has found the way to test android projects under "Android Studio" using Robolectric and Gradle. Please, take a look at this answer Robolectric with Gradle

Update: The guys from square have released a plugin to make Robolectric work out of the box with Gradle and Android Studio, this feature will be integrated with Robolectric in v2, meanwhile you can grab the plugin here: Gradle Android test Plugin

Solution 3

I tried different appraoaches to combine android studio & robolectric & espresso. I ended with this example project setup https://github.com/nenick/android-gradle-template

Here some explanation for the different approaches:

application module + espresso + robolectric

There is an example https://github.com/robolectric/deckard-gradle supported by robolectric maintainers. This is based on the plugin https://github.com/robolectric/gradle-android-test-plugin. But this have a drawback with dependency pollution reported at https://github.com/robolectric/gradle-android-test-plugin/issues/17 which results in slow esspresso tests compile time and execution time.

build.gradle snippet which combines all

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.10.+'
        classpath 'org.robolectric.gradle:gradle-android-test-plugin:0.10.+'
    }
}

apply plugin: 'android'
apply plugin: 'android-test'

android {
    defaultConfig {
        testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
    }
}

androidTest {
    include '**/*Test.class'
    exclude '**/espresso/**/*.class'
}

dependencies {
    androidTestCompile('junit:junit:4.11')
    androidTestCompile('org.robolectric:robolectric:2.3-SNAPSHOT')
    androidTestCompile 'com.jakewharton.espresso:espresso:1.1-r2'
}

seperate espresso

An example is shown by https://github.com/stephanenicolas/Quality-Tools-for-Android but it is much outdated and had also some drawbacks. It will recompile and makes android studio behave strange. It flags application module sources as (root source) of the espresso test module. That works but not intuitive.

build.gradle snippet for espresso module

dependencies {
    androidTestCompile 'com.jakewharton.espresso:espresso:1.1-r2'
}

android {
    sourceSets {
        main {
            manifest.srcFile '../AndroidSample/AndroidManifest.xml'
            java.srcDirs += ['../AndroidSample/src/main/java']
            resources.srcDirs = ['../AndroidSample/res']
            res.srcDirs = ['../AndroidSample/res']
        }
    }
    defaultConfig {
        testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
    }

}

spereate robolectric

There exist a plugin https://github.com/novoda/gradle-android-test-plugin which enable us to put robolectric tests in a sperate package. This project setup works for me great:

- MyProject 
|- app (with espresso tests)
|- - build.gradle (app)
|- robolectric (unit tests)
|- - build.gradle (robo)

build.gradle (app + espresso) snippet

dependencies {
    androidTestCompile 'com.jakewharton.espresso:espresso:1.1-r2'
}            

android {
    defaultConfig {
        testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
    }
}    

build.gradle (robo) snippet

buildscript {
    repositories {
        mavenCentral()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.9.+'
        classpath "com.novoda:gradle-android-test-plugin:0.9.8-SNAPSHOT"
    }
}

android {
    projectUnderTest ':AndroidSample'
}

apply plugin: 'java'
apply plugin: 'android-test'

dependencies {
    testCompile 'junit:junit:4.11'
    testCompile 'org.mockito:mockito-core:1.9.5'
    testCompile 'com.squareup:fest-android:1.0.+')
    testCompile ('org.robolectric:robolectric:2.3-SNAPSHOT')
}

There a some pitfall when you try setup this project setup, so just start with a working example: https://github.com/nenick/android-gradle-template

Solution 4

I tested all the solutions presented here and they all lack of something (version of gradle / gradle plugin not supported, library project not supported, no integration with Android studio, etc). It may not be true in the future but it is today.

The best way I found is to configure the unit tests by yourself. You will need to add a few lines of config to your build.gradle file. Explications are on the following article: http://tryge.com/2013/02/28/android-gradle-build/. Since I'm not the author, I don't think I can copy past the content here directly.

In addition to that article, if you want configure Android Studio to see the unit test folder as a source folder (autocompletion and stuff), you can apply the following little dirty hack and let the IDE think that the unit tests are located in the instrumentationTest folder. Of course, it will mess with your real instrumentation tests so it works only if you don't have any of those.

build.gradle

// the unit test source set as described in the article
sourceSets {
    unitTest {
        java.srcDir file('src/test/java')
        resources.srcDir file('src/test/resources')
    }
}

android {
    // tell Android studio that the instrumentTest source set is located in the unit test source set
    sourceSets {
        instrumentTest.setRoot('src/test')
    }
}

dependencies {
    // your unit test dependencies as described in the article
    unitTestCompile files("$project.buildDir/classes/release")
    unitTestCompile 'junit:junit:4.11'
    unitTestCompile 'com.google.android:android:4.1.1.4'
    unitTestCompile 'org.robolectric:robolectric:2.1.1'

    // duplicate these dependencies in the instrumentTestCompile scope 
    // in order to have the integration in Android Studio (autocompletion and stuff)
    instrumentTestCompile 'junit:junit:4.11'
    instrumentTestCompile 'org.robolectric:robolectric:2.1.1'
}

// the rest of the config as described in the article

Tested with Android Studio 0.2.6 and android gradle plugin 0.5.

Solution 5

Gradle Android Unit Testing Plugin is the best option for me.
Developed by Jake Wharton, I guess it is going to be the next standard (maybe until google releases an out of the box support for Robolectric in Android Studio).

You can import the library by adding in your build.gradle file:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.X.+'
        classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.+'
    }
}
...
apply plugin: 'android-test'
...

dependencies {
testCompile 'junit:junit:4.10'
testCompile 'org.robolectric:robolectric:2.1.+'
testCompile 'com.squareup:fest-android:1.0.+'
}

Update: This library has been deprecated since gradle plugin version 0.8

Share:
18,799

Related videos on Youtube

Flying Mongoose
Author by

Flying Mongoose

Updated on September 15, 2022

Comments

  • Flying Mongoose
    Flying Mongoose over 1 year

    I'm trying to use Robolectric in a project build with gradle inside the new Ide for android: Android studio, but I'm facing a strange problem, I've correctly imported all the libraries and created the "test" folder inside "src", the fact is that whenever I run the tests the ide keep saying "Class not found: "com.example.myandroidproject.test" what I'm doing wrong? i need to change something in the gradle.build? here's my directory structure:

    enter image description here

  • Flying Mongoose
    Flying Mongoose almost 11 years
    Thanks :) I'll try to set gradle as they recommend and make you know
  • Matthias
    Matthias almost 11 years
    I'm having a similar problem, with the difference being that all my unit tests are in a separate Gradle project. The tests run fine on the command line when running gradle test on the parent, however, from within Android Studio, I also get "ClassNotFound" on the test case class. I noticed that Android Studio seems to simply execute Gradle under the hood, so why would that not work?
  • LocoMike
    LocoMike almost 11 years
    @Xav : any example on how to create such a task? Also, once the task is created, should we add it as a dependency on "check"? Thank you
  • derekv
    derekv over 10 years
    I was able a while back to get Robolectric tests to run from a custom task in Android Studio (and it can already work in Gradle... see stackoverflow.com/questions/16649397/… ). You have to manipulate the module dependencies and setup quite a bit. However I never really published the steps anywhere because it wasn't practical, the android Gradle plugin will wipe out your customizations the next time it re-imports (soon).
  • bjb568
    bjb568 almost 10 years
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
  • bjb568
    bjb568 almost 10 years
    An example snippet would be nice.
  • nenick
    nenick almost 10 years
    More reasons while you down vote this answer? And why you don't remove the other posts here with just links and a short sentence?
  • bjb568
    bjb568 almost 10 years
    I didn't downvote. I just flagged the other link-only answers.
  • nenick
    nenick almost 10 years
    Then I judged to fast, sorry for that.
  • david.perez
    david.perez almost 10 years
    Gradle Android test plugin is deprecated now. :-(
  • Imanol
    Imanol almost 10 years
    You can use deckard gradle