Android Testing Tutorial

Writing Local tests in Android - Testing Fundamentals

Test it to believe it!

Saurabh Pant
Dev Genius
Published in
5 min readAug 6, 2022

--

Source: https://www.clouddefense.ai/

Well! Most of us are aware that unit testing is required to be done for the code we write but not all of us follow that notion. If I take my own example then I used to be very confused about why we do unit testing when we can do that manually and without writing code. And when I started learning about it, it came out to be more fun than expected.

If you haven’t started it yet, now is the right time!

In this article we’ll explore

  1. idea behind unit testing?
  2. what to test?
  3. what are local tests?
  4. how to build local tests?

So let’s begin answering our questions.

Idea behind Unit testing

Assume we’ve written a simple one page app and we want to test if it is working as expected or not. We start doing it manually. No problem. All good.

Now we add 10 new features in the app and the codebase gets bigger and functionality becomes complex. We again start testing it but this time it is not easy to test every possible user flow and that too on different devices. So what do we do now?

This is where we enter into the world of Unit testing which automate this process of testing and able to test different units in code independently. This is faster, reliable and correctly notifies us about the possible errors our user can encounter. Say if the feature set keeps in increasing but we make sure to write enough test cases for our codebase then this is also helpful in preventing regression bugs.

So the idea of unit testing is to keep your code bug free and healthy.

What to test?

Well! This depends on various factors and types of testing our project requires. But essentially in any app, we should consider writing test cases for

  • View models
  • Data layer classes e.g repository
  • Domain layer classes e.g. use cases, interactors
  • Helper or Utility classes

We should also consider to cover edge cases which are not very straightforwardly catchable. As per google docs:

  • Math operations using negative numbers, zero and boundary conditions
  • All the possible network connection errors.
  • Corrupted data, such as malformed JSON.
  • Simulating full storage when saving to a file.
  • Object recreated in the middle of a process (such as an activity when the device is rotated).

We should also consider writing tests for our UI interactions and flows.

What are local tests?

Local tests in Android are those tests which can be

  • tested on a system without requiring an actual android device or emulator
  • run on JVM

Local tests are faster as they don’t need an actual device deployment. We can test small pieces of code in isolation. Specially for the business logic these tests are very helpful.

The location for local tests is under test folder as shown.

How to build local tests?

So finally, let’s build some local tests.

Add the dependency for JUnit and Truth library in build.gradle

JUnit is for the unit testing support.
Truth is the recommended library by google. Its code is faster to type, easier to read and has simpler apis.

Now consider our Form Application, we built earlier. Lets write local tests for the Validator object which provide validation support.

Take a look at the validator object.

We see four different validation functions. Let’s start with validate account number function.

A successful validation would be when account number is not empty and is more than 5 digits.

It means that we can write tests in which we pass:

  • an empty account and expects a result status as False in return. This test should pass because we’re expecting correct behavior for the function. In case it returns true then the test will fail because that is not the correct output we expects from this validator function.
  • an account with less than 5 digit and expects a result status as False in return. This test should pass because we’re expecting correct behavior for the function. In case it returns true then the test will fail because that is not the correct output we expects from this validator function.

Alright, now we know what to test. Let’s set up a test class first. For this, right click on the class name and click on Create test.

This will create a test class in the test src folder with name ValidatorTest.kt. Let’s write first test case as follows.

Line 1 : We put this Test annotation on every function to make it a test case. This is imported from JUnit library.

Line 2: In local test, we can provide a function name as normal string by putting them under ``.

Line 3: We pass an empty string and save the result.

Line 4: assertThat is an api provided by Truth library using which we say that check if the result status is False. If it actually comes as False then our test case passes because this is what it is expecting from result status with isFalse().

We can run it by clicking the Run ValidatorTest as follows.

The result will be

Similarly if the test fails then it tells us the reason as shown

Changed the expectation to True while the result is False

Alright below are both the cases. Change the expectation either from the test case or from the validator function and play around.

Output:

Ohh Yeah!! We wrote the test successfully and checked the validity in just 24 ms. You can write the rest of the test cases for other functions yourself and play around with the testing. Let me know if you’re stuck somewhere.

You can checkout the this code in the unit-testing branch.

Pheww! This would be enough to get started well. We’ll continue on testing in further articles.

Bonus Read

That is all for now! Stay tuned!

Connect with me (if the content is helpful to you ) on

Subscribe to email to be in sync for further interesting topics on Android/IOS/Backend/Web.

Until next time…

Cheers!

--

--

App Developer (Native & Flutter) | Mentor | Writer | Youtuber @_zaqua | Traveller | Content Author & Course Instructor @Droidcon | Frontend Lead @MahilaMoney