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:
问题:
回答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.
回答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
回答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
回答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.
回答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
回答6:
I've tested a lot of scenarios (like http://tryge.com/2013/02/28/android-gradle-build/ and http://www.peterfriese.de/android-testing-with-robolectric/) but only the solution provided by the Robolectric team worked for me. The setup uses instrumented and robolectric tests in one Android project with gradle as build system.
See http://robolectric.org/getting_started/ and the sources on https://github.com/robolectric/deckard-gradle
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.2'
classpath 'org.robolectric.gradle:gradle-android-test-plugin:0.9.4'
}
}
allprojects {
repositories {
mavenCentral()
}
}
apply plugin: 'android'
apply plugin: 'android-test'
android {
packagingOptions {
exclude 'LICENSE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE'
}
compileSdkVersion 19
buildToolsVersion "19.0.3"
defaultConfig {
minSdkVersion 18
targetSdkVersion 18
versionCode 2
versionName "1.0.0-SNAPSHOT"
testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
}
buildTypes {
release {
runProguard false
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = ['res']
}
androidTest {
setRoot('src/test')
}
}
}
androidTest {
include '**/*Test.class'
exclude '**/espresso/**/*.class'
}
dependencies {
repositories {
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
// Espresso
androidTestCompile files('lib/espresso-1.1.jar', 'lib/testrunner-1.1.jar', 'lib/testrunner-runtime-1.1.jar')
androidTestCompile 'com.google.guava:guava:14.0.1',
'com.squareup.dagger:dagger:1.1.0',
'org.hamcrest:hamcrest-integration:1.1',
'org.hamcrest:hamcrest-core:1.1',
'org.hamcrest:hamcrest-library:1.1'
androidTestCompile('junit:junit:4.11') {
exclude module: 'hamcrest-core'
}
androidTestCompile('org.robolectric:robolectric:2.3-SNAPSHOT') {
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.+'
}
apply plugin: 'idea'
idea {
module {
testOutputDir = file('build/test-classes/debug')
}
}