Getting Started with Android testing

Getting Started With Android Testing

Saurabh Vashisht
The Startup
Published in
5 min readSep 5, 2020

--

If you are a new developer you must have heard about this dragon called testing that needs slaying. If you have some experience you probably know why it’s so important to add tests to your project as soon as possible. So without getting into why it’s important, let's get straight into the how. In this article, you will be introduced to the basics of writing tests for an Android app that we will develop.

We will start an empty Android project. If you wish to follow along you can check out the code for empty Android project here.

First we will write an Instrument test for our app. Instrumented unit tests are tests that run on physical devices and emulators. To read more about Instrumented tests you can checkout official documentation here.

Let’s get started…

Screenshot of our empty app

In this app we have a TextView which says “Hello World”.

We will now change the text in the app and then we will see if we can test whether the code we have written can be tested.

Go to the strings.xml file in app resources and add a new string resource. Let’s call it string_to_be_tested.

<string name="string_to_be_tested">We are going to test whether this string is shown in our App.</string>

Now go to your MainAcitivity’s layout file activity_main.xml and set the value of TextView to this string resource and we will also add an id attribute to our TextView.

<TextView
android:id="@+id/text_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/string_to_be_tested" />

An id attribute allows us to uniquely identify our TextView on the screen.

Now run the app and you will see the text in the app in place of Hello world.

Before we begin writing our test we need to understand what we are testing. In our app we show a text in a TextView and the text shown is present as a string resource.

Our test will verify that the string present as resource is shown on the screen when the app is opened.

To begin our testing process, first we need to add some dependencies. In our app’s top-level build.gradle file, we need to specify these libraries as dependencies:

dependencies {
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
// Optional -- Hamcrest library
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
// Optional -- UI testing with Espresso
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
// Optional -- UI testing with UI Automator
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
}

To use JUnit 4 test classes, make sure to specify AndroidJUnitRunner as the default test instrumentation runner in your project by including the following setting in your app's module-level build.gradle file:

android {
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}

The above dependency part is taken as is from official documentation. You can read the official documentation here. https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.

Now go to project tile on left side in Android studio and from the dropdown on the top, select “Android” and then open app->Java and look for the app’s package name with (androidtest) on the right side.

Now create a new class in the package selected in Blue above.

Since we are testing MainActivity, Let’s call the class MainActivityTest. In this class create a function that will contain the testing code.

package com.sample.androidtesting

import org.junit.Test

class MainActivityTest {
@Test
fun checkIfStringIsCorrect() {

}
}

At this point you can run the empty test and you will see that your test passes.

Now let’s add some code to this class. First we need to specify which Activity we will be testing. So we will create a rule that tells the test runner which Activity to launch.

@get:Rule
var activityRule: ActivityScenarioRule<MainActivity> =
ActivityScenarioRule(MainActivity::class.java)

Now we need to get the value of string from our resources so we can use the value to match with the text in our TextView. To get the string we need to create another rule to get an instance of resources.

var resources: Resources = InstrumentationRegistry.getInstrumentation().targetContext.resources
private lateinit var stringToBeChecked: String

@Before
fun getStringFromResources() {
stringToBeChecked = resources.getString(R.string.string_to_be_tested)
}

Before annotation allows getStringFromResources() method to be called before our test function checkIfStringIsCorrect() is executed. This way we can initialize any variables required for running our tests.

Now to test the value of text in our TextView.

@Test
fun checkIfStringIsCorrect() {
onView(withId(R.id.text_container)).check(matches(withText(stringToBeChecked)))
}

Let’s analyse the code we added here

onView(withId(R.id.text_container))

In this part we are looking for a view with id attribute equal to text_container. onView returns a ViewInteraction for view which matches with condition specoified as it’s arguments.

withId(R.id.text_container)

A matcher that matches Views based on its resource id.

check(matches(withText(stringToBeChecked)))

When we have the ViewInteraction, we call check with ViewAssertion. Check() method Checks the given ViewAssertion on the the view selected by the current view matcher.

matches(withText(stringToBeChecked))

This view assertion checks whether the text in TextView matches with the value of stringToBeChecked. matches() method returns a matcher that matches TextView based on its text property value.

The combined code for this class is here

package com.sample.androidtesting

import android.content.res.Resources
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@LargeTest
class MainActivityTest {
@get:Rule
var activityRule: ActivityScenarioRule<MainActivity> =
ActivityScenarioRule(MainActivity::class.java)
var resources: Resources = InstrumentationRegistry.getInstrumentation().targetContext.resources
private lateinit var stringToBeChecked: String

@Before
fun getStringFromResources() {
stringToBeChecked = resources.getString(R.string.string_to_be_tested)
}

@Test
fun checkIfStringIsCorrect() {
onView(withId(R.id.text_container)).check(matches(withText(stringToBeChecked)))
}

}

That’s it. We have written a test that can ensure the simple behavior of our app.
You can checkout the final code here

You can read the second part of this article here

https://link.medium.com/C5NVCb93y9

--

--