Guide to Android Testing: Basics

Asad Mansoor
Since Last Commit
Published in
5 min readOct 29, 2019

Suppose you are working on a cool idea for a mobile application. As you build out your features, you are constantly running the application on an emulator or a physical device and verifying that it works. Naturally, you are testing your application.

Testing is essential to building a robust software. As you continue to grow your application in features, the number of tests you will need to perform will increase proportionally to ensure nothing is broken. Testing provides validation on two aspects:

  • New changes are working as intended
  • New changes did not break any other parts of the application

Once these validations are in place, making changes to an application becomes easier and increases confidence in refactoring the codebase. However, manual testing will start to become a repetitive task, that could be time consuming and lead to a lot of human error. As a result, developers write automated tests, that are executed whenever they would like to validate their changes. In this blog post, we’ll cover the basic of testing an Android application.

Local vs Instrumented Testing

When you create a new Android application on Android Studio, the project is structured into various projects. These folders are called source sets.

Source sets are divided into three category:

  • main: contains the application’s source code
  • androidTest: contains test files for instrumented testing
  • test: contains test files for local testing

The main difference between test and androidTest is where the tests are required to be executed. Local testing includes tests that can be executed on the JVM and do not require the Android SDK. These could be testing the core business logic with a specific input and expected output. For example, the sample local test is asserting on whether 2 + 2 equals to 4.

Instrumented tests require the Android SDK, as they interact with the user interface or application context. In this case, an emulator or physical device will be required. For example, the instrumented test below assert on the package name of the context.

When you create a new Android project on Android Studio, these two tests are packaged with every new project.

Running your tests

To run your tests, you can do one of two things:

  • Right click on ExampleUnitTest and select Run ‘ExampleUnitTest’
  • Open terminal, navigate to the root project directory and execute ‘./gradlew testDebugUnitTest’

Both operations will execute the local test and produce some sort of output, to indicate whether the test case has passed or not. When you execute the gradlew command, the gradle task also creates a html report of the test run. To find the html report, navigate to app/build/reports/tests/testDebugUnitTest and open index.html.

Summary of the test

Testing the codebase

Now for the fun part 🎉! Let’s create a new Kotlin file named getLowerAndHigherRanges.kt, which takes a list of Integers and returns an object with two values: the percentage of integers that are less than 50 and the percentage of integers that are equal or more than 50.

For example

  • Given a list of integers: 1,3,44,59,99,102
  • Percentage of lower values: 50%
  • Percentage of higher values: 50%

getLowerAndHigherRanges.kt

internal fun getLowerAndHigherRanges(values: List<Int>): RangeResult {
val totalValues = values.size
val numberOfLowerValues = values.count { it < 50 }
val lowerPercent = 100 * numberOfLowerValues / totalValues
val higherPercent = 100 * (totalValues - numberOfLowerValues) / totalValues

return RangeResult(
lowerPercent = lowerPercent.toFloat(),
higherPercent = higherPercent.toFloat()
)
}

data class RangeResult(val lowerPercent: Float, val higherPercent: Float)

Writing our first test cases

To create a test file for our getLowerAndHigherRanges.kt, open the file on Android Studio and right click on the class name. Click on generate and select test. Follow the instructions to create a new test class under the test source set.

As of now, we have the code that needs to be tested as well as an empty test class file. Let’s start by creating a few test cases around these requirements:

  • Given a list of all integers below 50, the lowerPercent should equal 100% and higherPercent should equal 0%
  • Given a list of all integers above 50, the lowerPercent should equal 0% and higherPercent should equal 100%

The local test should look somewhat similar to the code below.

Discovering our first bug

As of now, all of the test cases should pass. However, there is a bug in the code 😱. We have not considered the case where the list is empty.

If we were to implement a test case to check that scenario, the code would throw an arithmetic exception as we are dividing by zero.

This is a perfect opportunity for test driven development.

Test Driven Development

In test driven development, the following steps are performed:

  1. Write a test case
  2. Confirm that the test case fails
  3. Write the minimal code to get the test to pass
  4. Repeat

We can proceed with writing a test case that takes in an empty list as input. Once we verify that it does fail, we can modify the getLowerAndHigherRanges.kt file to cover this case scenario. Once that is implemented, we will run the test again to verify that the bug has been fixed.

Final Code

getLowerAndHigherRanges.kt

getLowerAndHigherRangesKtTest.kt

Summary report of all the test cases

Would like to chat? Let’s connect on Twitter.

--

--