Android TDD Using JUnit, Robolectric and Mockito

Android now supports unit testing. Android unit testing runs on devices or emulators that adds extra time during development. I'm a big fan of TDD and the way android testing is done does not help me much.

However...

Thanks to Robolectric, headless testing is now possible by leveraging gradle. I wrote this post as a result of trying out several different approaches that confused me. Hopefully this one will help you set it up better.

How?

First, current common Android development projects are tightly coupled. Most stuffs are done in the Activity or Fragment, blame the tutorials. This makes it hard for us to actually do unit testing since a unit test should be isolated. The tight coupling makes unit testing impossible.

Then, come this approach called Model - View - Presenter (MVP). MVP aims at separating concerns.
The three components involved handles different concerns:


Model

This component groups all data related concerns. This component handles data queries (be it via SharedPreference or SQLite) and network connections. The Model will be the provider of data for the Presenter. The presenter will then sends the data to the View.


View

Just like the name suggests, the View handles all the presentation layers. You change the views, texts and contents in this component including navigation. The View should not handle view state and logic.


Presenter

This component handles the logic of the view and maintains the view state. The presenter will be the one communicating with the models and updates the view when data is retrieved.

The MVP components are created using interfaces that standardize it. This separates concerns from each layers. The components communicates via the interfaces and does not connect directly to the implementations. This removes tight coupling of each layers. You pose no effect to other layers when you subsitute your implementation.

For more references on MVP implementation try reading this blog post by Antonio Leiva.

Setting Unit Test on Android Studio Project

We need a special gradle plugin to set the environment for unit testing on Android. I use the Robojava gradle plugin by Gautam Korlam. It is simple and easy to set.

The first step you need to do is to create another module on your android project.


Make sure that you select the Java Library module.


After the module is created, delete all other files except the build.gradle so it looks like this


I named my library tests.

Now we need to tweak the gradle settings.

Make sure that your new library is listed in the settings.gradle file.
Mine looks like this:
include ':app', ':tests'
After that, we need to change the root build.gradle. That is the one on the root of your project.
Mine looks like this:


The next thing you need to change is the build.gradle of your main app. Make sure you list all the dependencies in this file and make sure that you set the test source to src/androidTest. Mine looks like this:


Then, finally you need to change the test module's build.gradle. This is to make sure that the test are executed in the right source and can be done headlessly. Mine looks like this:

And there you go, it's ready.

Anytime you wish to create a test, simply create a test on the presenter class, make sure it's a JUnit 4 test case and it's placed in the androidTest/ directory.

Anytime you wish to run the test go to the command line, cd to your project root folder and run:

$ ./gradlew test

If it is successful you should see something like this:


Robolectric tests can also be run for integration tests. You can also use this for continuous integration. Simply run:

$ ./gradlew build

Gradle will build and run tests. If any of the tests failed the build will fail.

I have the full example of this project on github. However, the project does not demonstrate the use of dependency injection as suggested by Antonio Leiva.

Feel free to comment or ask me.

regards

-E-

follow @femmerling on twitter
visit my website

Comments

Post a Comment

Popular posts from this blog

Customizing Sanic's Logging output on Gunicorn

5 Takeaways From My Past 5 Years With Coral, Prism, Midtrans and Gojek

Lessons From Leading and Developing Product Engineering Teams - Part 1