Unit Tests and Mocking with Android
Automation testing has a large role in developing software. Through the years this field has evolved and become incredibly broad – it’s difficult to navigate such massive amount of information or even pick a starting point.
This is especially true for mobile app automation where one can find multitude of different tools and approaches. The answer to “Which one should I use?” more often than not is “It depends” based on the specific circumstances. All of them enable our favourite services, apps and experiences to function smoothly and to improve constantly.
With this series, the intent is to provide a short view on the popular tools used for automation and how they ultimately fit together.With the first article, let’s take a look at one of the extremes – unit testing for Android mobile apps and the tools coming with the platform. The same holds true for iOS with XCTest framework.
Native tools for Android
– Android’s Junit tests, Mockito and Espresso
For the past 10 years, Android has matured into providing a rather comprehensive suite of tools and software development approaches to provide sustainable testing capabilities.Unit tests are focused on providing information on the smallest pieces that can be verified within the app. Espresso is a tool to handle UI tests and used for broader, more comprehensive tests on the overall segments of the application.
– JUnit tests
JUnit tests are at the core – simple Java tests, which are perfect for verifying the behaviour of small pieces of code and extremely quick to execute.
This is one of examples found in the Android documentation
At a first glance, this example doesn’t appear to provide much value. We grab a small function
readStringFromContext_LocalizedString() and compare its output with a known value that is correct. It’s easy to verify this without the test as well, so why write it?
The answer is rather easy – creating the test and running it takes minimal effort. Checking such a small piece of functionality manually on the other hand, takes significantly more time and effort in comparison.
It’s almost completely different than the initial simplistic example at a glance. On closer inspection, it uses the same internal methodology – take a function from the app, feed it information and verify if the result matches an expected value. The time required to verify manually if the above functions work correctly, immediately becomes far less appealing, doesn’t it? 😉
Create enough of those small, cheap tests and the application’s base transforms into robust piece. Any change to the project from updates to the Android version, libraries, further extension of the code and so on, will have a quick method of notifying you as the developer that the behaviour has changed at a precise position.
Don’t let the simplistic examples from the documentations fool you – unit tests are amazing to let you and your team to spend time your time productively. They are faster and more accurate at repetitively verifying that the building blocks of the project are working correctly.
Unit tests are great for simple logical checks but it’s rare when every piece inside the application can be tested on its own. An incredible amount of work is being done by developers to separate the responsibility of the code within a project for this exact purpose – just look at the plethora of MV* (insert series of letters here) patterns.
More often than not, the application relies on information provided from a server or the different pieces of code rely on each other to function as expected.
Welcome your new best friend, Mockito ! Android has first class support for this wonderful tool. This framework helps by “mocking” code which otherwise would be required for the unit tests. As an example, you may want to verify if the function to sort a list is correct. However, instead of creating an actual list of items or passing through several different layers of the app to get the list within the test to begin with (as the test won’t run without it), the list is mocked instead.
Notice that there is no explicit information provided about the `List.class`. The test doesn’t know how to create it or what is required for it. All of this is handled by Mockito leaving onlythe important piece – the code we want to test, to remain front and centre.
Mocking and dependency injection are indispensable tools to create extensive unit tests that provide value. They allow the opportunity to focus only on the piece of code that is of interest and remove the complexity from otherwise orchestrating a massive number of required steps to create the necessary environment to even run the test itself.
To be continued…
This concludes the first part of the series. It displayed briefly what the smallest possible tests providing value are – the aptly named unit tests. They are an amazing tool for any software project!Next time, the focus will shift towards the larger UI tests and how they differ from their smaller counterparts.