Believe it or not, only a minority of Android developers use Unit tests or tests at all. That brings up a question – how can they be sure that the source code they produce works.
Many companies don’t use them by default, and the client, in most cases, is not willing to pay for extra hours just for unit tests. Unfortunately, that mistake can be costly later when something happens in the wild and the app is already in production.
In this article, we will explain a few fundamental principles (that we attempt to accomplish) for writing excellent unit tests for Android apps, so let’s dive into it.
What is the use of unit testing for Android?
Unit tests are the fundamental tests in your app testing strategy. By creating and running unit tests against your code, you can easily verify that the logic of individual units is correct. After every build, running unit tests help you quickly catch and fix software regressions introduced by code changes to your app. Android official
We like our app to work correctly (at least we aim for that), so we are aware of the risk in which we could involve our client if we don’t test everything that we produce. Because of that, we are trying hard to find time for unit tests even if a client is not willing to take extra hours for that.
I remember one situation that happened two years ago where I didn’t write tests, and we deployed a new Android release. It was a release with a few new features, and that app went through the QA department, which tested every single use case with all those features. In the Android department, we got a green light.
Great, let’s submit it to Google Play. A few hours later, emails started coming to our support department. What was the problem? We didn’t have a test for login functionality, and it didn’t work anymore.
That happened because the QA department tested features while logged in and none of them checked the fundamental thing like login. After that incident, we started writing tests for everything.
1. Make them independent
The most frequent mistake many developers are making is creating a unit test that is dependent on some other unit test. With that approach, if one unit test fails, all tests that depend on it will fail as well.
The right way is to ensure that every unit test is testing only one thing and doesn’t depend on any other test.
For example, let’s say that you would like to test if your list has above the minimum number of items and below the maximum number of items. It’s the wrong approach to check both things in a single method.
Test for that use case should have at least two methods, one in which you would test for the minimal number and the second method which would test for maximum. If your test has both checks in the same method, you are doing something wrong.
Wrong way
@Test public void checkIfListIsInRange() { assertThat(list.params.size).isBetween(min, max); }
Right way
@Test public void checkIfListIsGreaterThanMin() { assertThat(list.params.size).isGreaterThanOrEqualTo(min); } @Test public void checkIfListIsLessThanMax() { assertThat(list.params.size).isLessThanOrEqualTo(max); }
2. Make them readable
Every single test should be readable and straightforward. Otherwise, you know what will happen if the test is not legible? When a new developer executes that test for the first time and that test fails, it would be easier to delete the test than find the problem inside the test.
It’s so much better and efficient to write it readable in the first place. It will help you to avoid so many problems later. When we are writing tests, we have a straightforward rule for readability. We write the comment only on the test class. If we have to comment on every red flag method showing that the test is too complicated, we should rewrite it.
The name of the test method should describe what the method is all about, and if that is not enough, we have a problem there.
3. They should fire automatically
You probably already know about continuous integrations and how that can help your tests automatically fire when something is pushed to GitHub. Use it. And if you don’t have that process done in your organization, leave everything that you are doing right now and fix that.
I used to say, “Okay, I don’t need continuous integration because I always execute tests when some task is done, but that is just a theory. A few times, when I was in a hurry fixing some bug, I just pushed without executing it, thinking nothing wrong could happen. Don’t forget it is always better to have a system that helps you avoid mistakes like that than not to have it at all.
Please write unit tests for Android
I care about projects that we are building inside our development agency, and I care for them to have at least 80% of unit test coverage, but I also care for other companies. Why? If I use some other app on my Android phone, I don’t want that app to crash once in a while.
Unit testing takes discipline, extra effort, a lot of time to learn, and even more time to master.
The most significant advantage of testable code is quickly understanding, maintaining, and extending that code along with the testability itself.
There is nothing more frustrating than an app that crashes, and you can only guess what the reason behind it is. As a developer, I always find a few reasons why the app crashed, and in many cases it could be avoided if developers were just careful enough and wrote tests.
What is your experience with testing code? We would love to hear it. Please write us.