One of the things I was always obsessed with, when developing in Android, was unit testing. The very first thing I like doing when starting a new android project is setting up Robolectric.

“Robolectric is a unit test framework that de-fangs the Android SDK jar so you can test-drive the development of your Android app. Tests run inside the JVM on your workstation in seconds.”

Because before Robolectric, unit test on android meant launch the emulator and run the test on them (or in a real device). Sure you could do unit test to java classes non-android related, but if you wanted to test user interface elements or the internals of your android app, there was no other way than running the test on an emulator or device.

Here it is the current set up I have for the android project the mobile team is working in Backbase.

Requirements for the current set up:

Gradle Integration

Either having a project already on Android Studio or you are going to create a new one, here it is the Gradle changes you will need to do.

  • We are going to use a gradle plugin that will allows unit test for the android plugin.

Inside the project build.gradle file:

dependencies {
    classpath 'com.android.tools.build:gradle:1.0.0'
    classpath 'com.github.jcandksolutions.gradle:android-unit-test:2.1.1'
}

You can find more information about this plugin in the android-unit-test github page.

Inside the module you want to test, add:

apply plugin: 'android-unit-test'
  • Install the Android Studio Unit Test

Go to Android Studio Preferences-> Plugins -> Browse repositories… and search for Android Studio Unit Test.

  • Add the Robolectric dependencies to the module

Inside the module you want to test add the following dependencies

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'org.robolectric:robolectric:2.4'
  testCompile 'junit:junit:4.12'
}
  • Add test sources location

Inside the android object in the gradle.build file:

android{
    ...
    sourceSets {
        androidTest {
            setRoot('src/test')
        }
    }
}

This is how the final gradle file looks like:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 18
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "backbase.com.robolectric.example"
        minSdkVersion 15
        targetSdkVersion 18
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }

    sourceSets {
        androidTest {
            setRoot('src/test')
        }
    }
}

apply plugin: 'android-unit-test'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'org.robolectric:robolectric:2.4'
    testCompile 'junit:junit:4.12'
}

With this configuration you will be able to run your tests on command line using the “gradle test” or “gradle build” and inside Android studio.

Robolectric

Robolectric extends the Android SDK to make our apps more testable. Here is a basic example of how to test an Activity behaviour.

Having the following Activity:

public class MainActivity extends Activity implements View.OnClickListener, View.OnLongClickListener {
Button button;
TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        textView = (TextView) findViewById(R.id.textView);

        button.setOnClickListener(this);
        button.setOnLongClickListener(this);
    }

    @Override
    public void onClick(View view) {
        textView.setText("Button clicked!");
    }

    @Override
    public boolean onLongClick(View view) {
        textView.setText("Button long clicked!");
        return false;
    }
}

We want to test the events of a button that changes the text on a TextView with two events: the onClick and onLongClick events.

This will be the test code:

@RunWith(RobolectricTestRunner.class)
public class ActivityTest {

    @Test
    public void testClickButton() throws Exception {
        Activity activity = Robolectric.buildActivity(MainActivity.class).create().get();
        Button pressMeButton = (Button) activity.findViewById(R.id.button);
        TextView results = (TextView) activity.findViewById(R.id.textView);
        pressMeButton.performClick();
        String resultsText = results.getText().toString();
        
        assertThat(resultsText, equalTo("Button clicked!"));
    }

    @Test
    public void testLongClick() throws Exception {
        Activity activity = Robolectric.buildActivity(MainActivity.class).create().get();
        Button pressMeButton = (Button) activity.findViewById(R.id.button);
        TextView results = (TextView) activity.findViewById(R.id.textView);
        pressMeButton.performLongClick();
        String resultsText = results.getText().toString();
        assertThat(resultsText, equalTo("Button long clicked!"));
     }
}

Let’s make a test fail, to see what do we get:

In the “testLongClick()” test case I changed the following line

assertThat(resultsText, equalTo("Button long clicked!"));

To this one

assertThat(resultsText, equalTo("Button normal clicked!"));

Here is the result:

In future articles we will go deeper into Robolectric, play around with Mockito and show how to configure jacoco to give test and coverage reports.