Before we start this article talking about how we can build effective unit tests for Android, we need to explain what automated tests are and why we need them to create good and reliable software.
“By running tests against your app consistently, you can verify your app’s correctness, functional behavior, and usability before you release it publicly”.
The quote above is on the first page of this guideline for any Android developer who is getting into the world of tests with Android. That statement explains the most important benefit of testing apps: to guarantee that everything is working fine before we deploy them to production. Every developer – and this extends to all chain of people involved in software production (QA, PO, client) – has to know that writing automated tests is the most important and verified technique for avoiding bugs (not all, of course), what leads to a better experience for the final user.
My experience reveals that software can be scalable and present a lot of “side-dependencies”, which means that writing only part of a code can impact and maybe generate some errors in other parts. Also, tests can be useful to understand the usability of the app by reading methods’ names. With that, you can see what can and cannot be done as a user or when interacting with other systems. Another thing about tests is that they can be really handy when you need to refactor part of the code, after all, writing tests and before starting a refactoring – it is the best way to guarantee that the behavior remains the same.
There are a lot of concepts involved in how to organize tests in software development, but I want to highlight two pictures that show how we can achieve that.
The Ice-cream cone demonstrates how tests are built in a great number of organizations: It shows a lot of manual tests and a few automated tests, especially unit ones. It happens more often in legacy systems, and therefore puts a lot of responsibility in the QA team to catch defects.
The ideal scenario is shown in the test pyramid designed by Mike Cohn in his book Succeeding with Agile, from which we can deduce some things:
Here, I will explain the parts of the pyramid and some tools that we can use to create those tests:
– Unit Tests
Tests can be done without involving any other dependency, meaning that they can be run without starting a database or calling REST APIS, etc. They are low-level, focusing on a small part of the system, meaning that they can be run very frequently when programming and have low costs because you don’t need a big machine to run them. You can use tools like JUnit and Mockito.
– Service (API/Integration/Component) Tests:
Service tests are tests that integrate with other systems, like REST APIS and databases. These tests are not as fast as unit tests and need a tool like Roboletric or AndroidJunit4, that simulate Android 4.1 (API level 16) or higher, and also provides fake ones, called shadows. This functionality allows you to test code that depends on the framework without using an emulator. Using a working version of the real Android framework, however, makes test execution slower and adds a degree of brittleness when compared to pure unit tests.
– UI Tests:
Most known as end-to-end tests, UI tests check if the user interface of your application works correctly. User input should trigger the right actions, data should be presented to the user, the UI state should change as expected. Normally the tool recommended for UI tests is Espresso, that allows you to programmatically locate and interact with UI elements in your app in a thread-safe way. This kind of tests is slow because you must deploy your app to an emulator or device and drive it using the UI. They are expensive because this often means maintaining an internal device lab and CI server or paying for a cloud testing service.
– Manual UI tests:
Tests that are made mostly by the QA team.
This article intended to explain the different tests and how to create them using some of the libraries in an Android context, but it also can be a guide for any developer who wants to achieve a good and trustable software. Remember, building consistent tests and clean code is the key element to achieve good quality in software development.
About the author
Leonardo Ramos is a Software Engineer at Poatek.