We all know testing is essential to verify the behaviour of the software you write. In the Android world with its huge variety of devices and OS versions, this is even more so. Unfortunately, the performance of the Android development environment, most notably the Android Emulator, leaves much to be desired which sometimes leads to neglicence of test discipline. Robolectric is a test framework that tries to alleviate this situation.
Robolectric achieves this by sitting between your code and the Android OS code intercepting calls and redirecting them to shadow objects, making it possible to run your tests inside a regular JVM. This effectively means you can run your tests on your desktop – no waiting for your code to be deployed to the Emulator or a physical device!
Creating a New Project
To better understand how Robolectric works, let’s create a very simple project we’ll use as our object under test. We’ll use Android Studio (at the time of writing, version 0.3.0 was the latest version).
Create a new project using the settings you can see in the following screenshots. Choose Blank Activity and Navigation Type None.
To make things a bit more interesting, let’s change the UI so we’ve got a
InputView and a
Button on, just like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
Preparing for Testing
To prepare your project for testing with Robolectric, there are a few things you need to do:
- Create a folder for your tests and make sure both Gradle and Android Studio recognize it.
- Add the Gradle Android Test Plug-in to your project
- Add a customized TestRunner
Creating a Folder For Your Tests
When you create a new project in Android Studio, it is not yet configured for testing. If you used to develop Android apps in Eclipse, you probably are used to creating a new project for your tests. The good news is, with the new Android build system based on Gradle, you can now place your tests in the same project as your production code (refer to the build system documentation for more details).
However, Android Studio (and the Gradle Plug-in) currently expect you to place tests in
src/instrumentTest. As we won’t be writing instrument tests, we’d rather like to place our tests in
src/test. In order for this to work, we need to tell Gradle and Android Studio we’re deviating from the default project structure:
- Create a new folder
src/test/javato contain your tests.
build.gradlein your project folder and add the following source set configuration to the Android plug-in configuration, right beneath the
1 2 3
- Next, in Android Studio, select
Tools -> Android -> Sync Project with Gradle Filesfrom the main menu. This will tell Android Studio where to find your test files.
You will notice how the icon for your test files folder turns from orange to green:
Adding the Gradle Test Plug-in
In order to be able to run Android unit tests with Gradle, we need to add the Gradle Android Test plug-in to the build script.
- Add the maven snapshots repository to the build script repositories and regular repositories section. This is in order to get the fix provided in pull request 26.
1 2 3
Add the plug-in to the dependencies section of your
Apply the plug-in:
- Add test-only dependencies:
1 2 3 4 5 6
build.gradle should now look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
Adding a Customized Test Runner
Because of the way Robolectric looks for your
AndroidManifest.xml during test startup, it won’t find the manifest if your tests are located in
src/test/java. To alleviate this situation, we need to add a custom test runner.
Add the following file to your project, making sure to place it somewhere in the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
Writing Your First Robolectric Test
Let’s write our first test! Add the following class to
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
A couple of things to note here:
Firstly, we use the newly created
RobolectricGradleTestRunnerto make sure the test can access the Android manifest (and thereby the other Android components in your app).
Secondly, we added a simple test method, making sure it will fail. Why is this a good idea? Well, it makes sure our test fails when running it, so we can be sure the whole setup actually works. If we run the test and it does not fail, we know that something is wrong.
So, let’s run the test!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
So, the test failed – just as we expected. You can open the test report (
../RobolectricDemoProject/RobolectricDemo/build/test-report/debug/index.html) in your browser to get more detailed information about the test run.
Enhancing the Test
Now that we’ve got everything in place, let’s develop a small feature in a test-driven way. You already noted how we enhanced the UI of the application at the beginning, but apart from looking nice, there’s not much functionality.
Let’s enhance the app so the user can enter their name, press a button and be greeted by the application.
Make sure to statically import the Android FEST assertations – they’ll help us to write our tests in a fluent manner:
As we need to have access to the app’s main activity in all of our tests, let’s add a private field for it and create a setup method that will create a fresh activity before each test is run:
1 2 3 4 5 6
It is a good practice to ensure the UI is fired up and all UI elements have been initialized as expected (i.e. are not null):
1 2 3 4 5 6 7 8 9 10 11 12 13
Next, let’s write a test that places a text inside the edit field, presses the button and compares the result in the text view with the expected result.
Here is the test method:
1 2 3 4 5 6 7 8 9 10 11
When you run the test, it will obviously fail, so let’s fix this.
MainActivity.java and insert the following private class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
As you can see, this code will register an
OnClickListener for the button and set the text of the text view according to the value of the edit field.
Also, change the constructor of
MainActivity so it uses the new fragment class when instantiating the view fragment:
1 2 3 4 5
The test should now pass:
1 2 3 4
Setting up Robolectric so that you can use both Gradle and Android Studio may not be as simple as it should be, but it’s reasonably easy with the information I have given you above. Adding Robolectric to a new Android project is just a matter of minutes with these instructions and helps you save a lot of time you’d have had to spend otherwise running the tests on the emulator or on physical devices.
The source code for this blog post is available on Github.