I'm trying to run my Robolectric tests together with the new Gradle Android build system, but I'm stuck at accessing the resources of my main project.
I split the build into two separate projects to avoid conflicts between the java
and the android
gradle plugins, so the directory structure looks roughly like this:
. ├── build.gradle ├── settings.gradle ├── mainproject │ ├── build │ │ ├── classes │ │ │ └── debug │ ├── build.gradle │ └── src │ └── main │ ├── AndroidManifest.xml │ └── ... └── test ├── build.gradle └── src └── test └── java └── ... └── test ├── MainActivityTest.java ├── Runner.java ├── ServerTestCase.java └── StatusFetcherTest.java
My build.gradle
in test/
currently looks like this:
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.stanfy.android:gradle-plugin-java-robolectric:2.0' } } apply plugin: 'java-robolectric' repositories {...} javarob { packageName = 'com.example.mainproject' } test { dependsOn ':mainproject:build' scanForTestClasses = false include "**/*Test.class" // Oh, the humanity! def srcDir = project(':mainproject').android.sourceSets.main.java.srcDirs.toArray()[0].getAbsolutePath() workingDir srcDir.substring(0, srcDir.lastIndexOf('/')) } project(':mainproject').android.sourceSets.main.java.srcDirs.each {dir -> def buildDir = dir.getAbsolutePath().split('/') buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/') sourceSets.test.compileClasspath += files(buildDir) sourceSets.test.runtimeClasspath += files(buildDir) } dependencies { testCompile group: 'com.google.android', name: 'android', version: '4.1.1.4' testCompile group: 'org.robolectric', name: 'robolectric', version: '2.0-alpha-3' ... }
The evil classpath hackery allows me to access all classes of my main project, except for R
, which exists as .class
file in the build directory, but raises this error during the compileTestJava
task:
/.../MainActivityTest.java:16: error: cannot find symbol final String appName = activity.getResources().getString(R.string.app_name); ^ symbol: variable string location: class R 1 error :test:compileTestJava FAILED
There must be a better way to execute Robolectric tests with the new build system, right?
(Full source of the app)
I was running across this same issue and this is what I came up with. Instead of creating a separate project for the tests, I created a source set for the Robolectric tests and added a new task that "check" would depend on. Using some of the code from your question, here are the relevant bits of the (working) build file:
apply plugin: 'android' sourceSets { testLocal { java.srcDir file('src/test/java') resources.srcDir file('src/test/resources') } } dependencies { compile 'org.roboguice:roboguice:2.0' compile 'com.google.android:support-v4:r6' testLocalCompile 'junit:junit:4.8.2' testLocalCompile 'org.robolectric:robolectric:2.1' testLocalCompile 'com.google.android:android:4.0.1.2' testLocalCompile 'com.google.android:support-v4:r6' testLocalCompile 'org.roboguice:roboguice:2.0' } task localTest(type: Test, dependsOn: assemble) { testClassesDir = sourceSets.testLocal.output.classesDir android.sourceSets.main.java.srcDirs.each { dir -> def buildDir = dir.getAbsolutePath().split('/') buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/') sourceSets.testLocal.compileClasspath += files(buildDir) sourceSets.testLocal.runtimeClasspath += files(buildDir) } classpath = sourceSets.testLocal.runtimeClasspath } check.dependsOn localTest
I've included my dependencies block to point out that in order for me to get this up and going, I had to repeat all of my compile
dependencies in my custom testLocal
source set.
Running gradle testLocal
builds and runs just the tests inside of src/test/java
, while running gradle check
runs these tests in addition to those in the default android instrumentTest source set.
Hope this helps!
Update: Jake Wharton just announced the gradle-android-test-plugin
. You can find it at https://github.com/square/gradle-android-test-plugin
It seems to be pretty streamlined, especially if you plan to use robolectric
.
Old Answer Below
The robolectric-plugin
looks promising.
The sample build.gradle
file they provide is :
buildscript { repositories { mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots" } } dependencies { classpath 'com.android.tools.build:gradle:0.4.2' classpath 'com.novoda.gradle:robolectric-plugin:0.0.1-SNAPSHOT' } } apply plugin: 'android' apply plugin: 'robolectric' repositories { mavenCentral() mavenLocal() maven { url "https://oss.sonatype.org/content/repositories/snapshots" } } dependencies { //compile files('libs/android-support-v4.jar') // had to deploy to sonatype to get AAR to work compile 'com.novoda:actionbarsherlock:4.3.2-SNAPSHOT' robolectricCompile 'org.robolectric:robolectric:2.0' robolectricCompile group: 'junit', name: 'junit', version: '4.+' } android { compileSdkVersion 17 buildToolsVersion "17.0.0" defaultConfig { minSdkVersion 7 targetSdkVersion 17 } }
It doesn't seem to work with the Android Gradle plugin version 0.5 but maybe it will soon.
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