Kelevandos
Kelevandos

Reputation: 7082

How to setup Robolectric in Android Studio 1.0

I am a Android developer and a TDD passionate. Recently, I learned about a new testing framework, Robolectric, which seems to be far superior to the JUnit 3 solution Android Studio provides by default. I wanted to setup it, but after numerous tries, failures and java.lang.RuntimeException: Stub! I achieved nothing.

Here is my question:

How do I setup, step-by-step, the Robolectric testing framework on Andoird Studio 1.0? Please note:

The setup of this framework is very problematic and has numerous issues among different versions of Android Studio and IntelliJ. I browsed all of them, but to no avail. I need help from someone who succeded in using the framework on Android Studio 1.0.

Upvotes: 4

Views: 3580

Answers (2)

Kelevandos
Kelevandos

Reputation: 7082

EDIT:

Over those few months the setup process of Robolectric for Android Studio improved quite a bit, so before trying the below, 'long' approach, just try the official guide here! :-)


Ok, I managed to setup it! It is very tricky and not fully compatible with the newest Gradle 1.0.0, but it is working like a charm!

My solution is based mainly on this tutorial

So, your build.gradle file (the "inner" one, inside the project's folder) should look like this:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.14.1'
        classpath 'org.robolectric:robolectric-gradle-plugin:0.14.0'
    }
}

allprojects {
    repositories {
        mavenCentral()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
    }
}

apply plugin: 'com.android.application'
apply plugin: 'robolectric'


android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"
    defaultConfig {
        applicationId '[your app id]'
        minSdkVersion 9
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    sourceSets {
        androidTest.setRoot('src/androidTest') // This one is important, make sure to avoid typos in it, or you will get empty tests
    }
    lintOptions {
        abortOnError false
        disable 'InvalidPackage'
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:21.0.2'

    // ================== TESTING LIBRARIES ======================
    androidTestCompile 'junit:junit:4.10'
    androidTestCompile 'org.robolectric:robolectric:2.4'
    androidTestCompile 'org.bouncycastle:bcprov-jdk15on:1.50'
}

robolectric {
    // configure the set of classes for JUnit tests
    include '**/*Test.class' //Make sure you call all your test classes according to this expression!!!

    // configure max heap size of the test JVM
    maxHeapSize = "2048m"
}

apply plugin: 'jacoco'

jacoco {
    toolVersion = "0.7.1.201405082137"
}

def coverageSourceDirs = [
        '../app/src/main/java'
]

task jacocoTestReport(type: JacocoReport, dependsOn: "testDebug") {
    group = "Reporting"

    description = "Generate Jacoco coverage reports"

    classDirectories = fileTree(
            dir: '../app/build/intermediates/classes/debug',
            excludes: ['**/R.class',
                       '**/R$*.class',
                       '**/*$ViewInjector*.*',
                       '**/BuildConfig.*',
                       '**/Manifest*.*']
    )

    additionalSourceDirs = files(coverageSourceDirs)
    sourceDirectories = files(coverageSourceDirs)
    executionData = files('../app/build/jacoco/testDebug.exec')

    reports {
        xml.enabled = true
        html.enabled = true
    }

}

It looks alot like the "outer" build.gradle file, but all this stuff has to be right here.

Some of the elements my be unneeded here, but I did my best to cut it down to the core part. After you so this, a Test class is created like this:

import android.app.Activity;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;


@Config(emulateSdk = 18, reportSdk = 18) //Those are required as the framework does not yet support higher API levels
@RunWith(RobolectricTestRunner.class)
public class RoboDummyTest {

    @Test
    public void testActivityFound() {
        Activity activity = Robolectric.buildActivity(MainActivity.class).create().get();

        Assert.assertNotNull(activity);
    }
}

All data is stub of course :-)

Finally, the tests are run by typing gradlew test into the terminal inside Android Studio. The results will be saved to a html file inside the build directory of your project.

I hope this will be helpful to anyone planning on setting Robolectric with Android Studio 1.0. Happy TDDing!

EDIT: The author of the blog post I used to write the answer, Kvandermast, was as kind as to provide the below link to a repository containing a working example, updated every Android Studio update: https://github.com/kvandermast/my-robolectric-app

Upvotes: 5

Håkan
Håkan

Reputation: 11

I have tried out all different workarounds that I have been able to find, got some to work and some did not work at all.

But yesterday I found one that actually worked without too much effort and does it so quite nicely: http://www.bignerdranch.com/blog/all-in-together-android-studio-gradle-and-robolectric/

This approach is based on a another gradle robolectric plugin, but it also includes an android studio plugin that handles the classpath problems in a neat way.

Best solution for this that I have found! It works almost as if out-of-box.

Upvotes: 1

Related Questions