· 4 min read

Android Unit Testing using Robolectric (I): Introduction

Unit tests have become an invaluable tool in recent times due to the increasing complexity of coding and new agile methodologies, which keep the code alive during the full development cycle. That’s why I wanted to start a series of tutorials that will focus on the most standardized mechanisms for Android unit testing nowadays.

Unit tests are the basis of test-driven development (TDD) methodology, in which you first develop the test and then the simplest code that validates the test.

But leaving that aside, the fact is that if your code is susceptible to continuous refactoring, unit testing becomes a crucial weapon to ensure that any change in code keeps on validating previous behaviour. And this is the goal I want to pursue here.

Robolectric

There are several Android libraries for unit testing, and even the SDK provides some tools. However Robolectric has become one of the favourite options among Android developers. I will not go into details, you can read all the information at the official Robolectric website, but these are its main features:

  • It lets tests run directly in the IDE, without having to launch an emulator, which reduces execution time from minutes to seconds.
  • Android SDK has been studied in deep to create classes that allow access to state, attributes and methods of objects that would otherwise be inaccessible. These classes are called shadows.
  • In Robolectric 2.0, now you can even test styles and themes, and can access the system resources.

First example

I will use a simplified example taken from Robolectric sample project: HomeActivity related tests. For now, it will be enough for you to understand what you will be able to do using this library.

Suppose we have an initial HomeActivity, which has a button that will open NamesActivity. Let’s create a test that will check that. The structure of a test class will have some attributes for elements that want to be tested, an init method called setUp(), and your test methods. This is our simple test:

@RunWith(RobolectricTestRunner.class) 
public class HomeActivityTest { 
    private HomeActivity activity; 
    private Button pressMeButton;

    @Before 
    public void setUp() throws Exception { 
        activity = Robolectric.buildActivity(HomeActivity.class).create().get(); 
        pressMeButton = (Button) activity.findViewById(R.id.press_me_button); 
    }

    @Test 
    public void pressingTheButtonShouldStartTheListActivity() throws Exception { 
        pressMeButton.performClick();

        ShadowActivity shadowActivity = shadowOf(activity); 
        Intent startedIntent = shadowActivity.getNextStartedActivity(); 
        ShadowIntent shadowIntent = shadowOf(startedIntent); 
        assertThat(shadowIntent.getComponent().getClassName(), equalTo(NamesActivity.class.getName())); 
    } 
}

As Robolectric is based on JUnit, you will need to set an annotation to indicate which class will be performing the test (RobolectricTestRunner.class in this case). Create an attribute for the activity you want to validate and the button that will take us to the next activity.

In setUp, we are retrieving an activity object and call onCreate as follows:

Robolectric.buildActivity(HomeActivity.class).create().get();

This way you will get your activity inflated, and therefore the button is available when searching by its ID.

Now we are testing that pressing the button actually opens NamesActivity. Let’s call performClick() and check what happens. To do this, we need to create a shadow object from our activity. As discussed above, it gives us the ability to access methods that would otherwise be impossible due to their access level, but it also adds some new ones that will help test the App behaviour.

In this case, create a shadow from the intent that was generated to call the next activity so that you can retrieve the name of the class that is going to be started. With the assert you check that, indeed, the class launched is the one you want.

Conclusion

Robolectric is a tool that requires a significant learning curve, but once mastered you will significantly improve the quality of your code by being sure that any change, addition or refactoring does not invalidate the tests.

In this tutorial I just wanted to give a little introduction to let you see how it works, but the following ones will explain more in-depth how to use it, from project structure and organization to specific testing situations.

    Share:
    Back to Blog