In the last part of this series I’m going to talk about Android testing, UI and unit testing. Testing code in Android is not the easiest and funniest thing to do, however it gives you a lot of confidence about your app. During the last year i started testing my application with unit and integration tests.

Besides this tests you can also stress test your app with monkey tool, run static analyzers and so on. I’m gonna show how we can unit test a Job and how we can test the login use case in our app.

What’s the difference between UI and Unit tests ?

Unit tests, test a specific part of your code and run isolated from other components, with no external dependencies. For example, you can write a unit test to test a method that writes to a database, we should mock the database call, we only care about the logic inside the method, the code we wrote, we are not testing the database itself. In this case a mocked object is normally used to “fake” a database call. Unit tests are used to test the domain logic of our app, the logic we wrote ourselves and not external libraries . Android unit test can be of two type: local unit tests, that run on local JVM and don´t have dependencies on Android Framework, and instrumented tests, that need access to Android framework functionality.

test a specific part of your code and run isolated from other components, with no external dependencies. For example, you can write a unit test to test a method that writes to a database, we should mock the database call, we only care about the logic inside the method, the code we wrote, we are not testing the database itself. In this case a mocked object is normally used to “fake” a database call. Unit tests are used to test the domain logic of our app, . Android unit test can be of two type: and don´t have dependencies on Android Framework, and Integration tests are used to test the the interaction between the components of our application. For example, when clicking the login button with the wrong credentials a text view should appear warning the user about the error. Using Espresso we can simulate user interactions to test complex scenarios.

It’s important to keep this in mind, there are two kinds of tests local and instrumented.

Local tests run on the JVM and don’t need Android framework, much faster !!!!

Instrumented tests need Android framework to run, slower but sometimes necessary

Setup Android test environment

Android documentation is very good explaining the concepts and fundamentals of Android testing.

I highly recommend you to read it.

I’m not going to explain how to setup a project structure to run unit and instrumentation tests because it would take a separate article only for that, however Vogella has a great tutorial explaining all the steps you need to start testing in Android, go ahead and read it if you never worked with Android testing before.

Unit testing — practical use case

I’m gonna show you how we can unit test a “Job” in our application, like i said before testing on Android in my opinion in most cases is not an easy and fun thing to do, it takes time and can demotivate developers from doing it.

Imagine we have a “GetUserJob” that retrieves a user from the server and saves it’s email and username is Android preferences. What we are going to do is mock the preferences object and assert it to see if everything went ok. Normally we would mock the http call to the server, we shouldn’t depend on external factors however to show how to do it would make this article too long, so assume that the networking library in this case i’m using Retrofit is mocked.

GetUserJob

This is Job we want to test, as you can see if everything goes well, the preferences will be updated with the username and email of the user, after that an event is send with SUCCESS state, otherwise the event is send with ERROR state.

Reminder On part II we saw that one need a Dagger Component to inject our objects, that component contains a list of Dagger Modules that know how to create the objects we need. In this case we want to inject a mocked version of Android preferences, so we are going to create a Component that have a module that returns a mock, when “GetUserJob” runs and calls DI.get().inject(this), this will inject the mocked version.

The Dagger component

Simple component that injects GetUserJob, in modules list you can see the module GetUserJobModule, this module will return a mocked version of Android preferences.

The GetUserJob module

This module creates a mocked version of Android preferences, when the method prefs.edit() is called we return the mocked editor, and every time we call the method putString(anyString(),anyString()) we return the mocked editor too.

NOTE: I’m using Mockito library to mock and stub method calls.

The unit test

The test is a JUnit 4 class, every test method should be annotated with @Test. The setup method runs before each test method and is annotated with @Before. In setup we create our GetUserComponent that uses the GetUserJobModule that will provide a mocked version of Android preferences.

In testOkGetUserJob() we create a GetUserJob, and call the method onRun() this will make a “fake” network call and save the user email and username in the mocked preferences object, finally it sends the GetUserEvent. After calling onRun() we verify that the edit() was called one time and that putString() was called with the correct arguments.

This only shows one test, however we can have several test methods to test different possible scenarios.

Integration tests with Espresso

A integration test interactions between the different components within your app, for example a click on “Add User” button should create a user, save it and finally show a success message to the user. We are going to use Espresso library to simulate the interaction, I’m not going explain how espresso works in this article but there are plenty of good sources out there.

Integration Test — practical use case

We are gonna test login behavior, to do so, there are 3 scenarios we wan’t to test :

Error with empty fields

Error with bad credentials

Success

The above class looks very much the same as the previous test, however there is a @Rule annotation, this ActivityTestRule is a rule that launches the activity under test, in this case, AuthenticationActivity before each test method.

I’m using Espresso actions and matchers to perform actions(click) on the views, after that we check to see if the error labels are visible and have the correct message. Testing UI code in Android is tricky because Espresso needs to synchronize with the UI thread, if we are doing background work we need to wait for that work to finish before making checks and sometimes is not intuitive to test some simple things like “Is activity X loaded”.

You can see in line 93 we check if Toolbar is displayed, because the login activity does not have one and MainActivity has, so this is a simple way of checking if MainActivity is loaded, however as you can see is not intuitive when you look at it.

Waiting for background work

Some developers put “sleep()” calls inside the test method to wait for background work to finish and this is not the recommended way of doing it. Espresso has his own mechanism to do it, however you need to modify your production code and put more code and logic just to run the tests, personally i hate it, i normally go lazy in here and use an ElapsedIdlingResource that waits for X milliseconds before continuing.

You can check it here in more detail:

Last thoughts and what can be improved

There are a lot of other ways you can structure and build Android applications i just showed one way i used in the past and hopefully will help you start making Android apps.

Looking back there are a couple of things i would have done differently:

The view/presentation layer, in a future project i will experiment an MVP approach here, using an interface to abstract the view and using a presenter to mediate the interactions between the view<->model. This approach gives a better separation between the view layer and the rest of the components.

The data layer, one thing i can’t do with this architecture right now is switching the data layer from GreenDao to some other persistent library(memory based, disk based,etc..). The “Jobs” use GreenDao directly so to switch to another library i’ll have to change every job that uses it, there’s no abstraction here. The Repository Pattern looks like a very good way of abstracting the data layer as explained by Fernando Cejas in his article, maybe i’ll give it a shot in the future.

Package structure, the structure can be improved because i didn’t use gradle modules in the beginning, you should use a (presentation,domain,data) modules structure in my opinion, including the necessary modules in “settings.gradle” file.

Overall i think it ended up to a good architecture i can easily extend the app with new features, it’s testable and modifiable and it decouples the main layers(presentation,domain and data).

Sérgio Serra

Mobile Developer @GuestU Clarice App

sergioserra99@gmail.com

www.clariceapp.com