Quick start guide to writing Espresso UI tests on Android - Android Testing Part 4

In this tutorial we’ll be going over how to get started writing Android UI tests using Espresso. We’ll continue adding tests to the ImportantTodos app repository.

Here are a few useful resources when attempting to write Espresso tests:

To get started it is recommended to disable animations on your Android Virtual Device to avoid flakiness in your tests. To do this launch your virtual device and go to Settings > Developer Options and disable the following:

  • Window animation scale

  • Transition animation scale

  • Animator duration scale

Next you’ll want to add the following dependencies to your app/build.gradle file:

androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test:rules:1.5.0'

Then make sure this line is also listed under the android.defaultConfig block of the same app/build.gradle file:

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Now it’s time to write our first test. Navigate to the app/src/androidTest directory and add a new file called TodosIntegrationTest.kt. Within our file we can declare a new class that will contain our tests, add a rule that will launch our MainActivity class, and since our app is so simple, we can essentially write a single integration test that will cover most of the core user flows.

@RunWith(AndroidJUnit4::class)
class TodosIntegrationTest {

    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)

    @Test
    fun addTodo_updateIt_and_deleteIt() {
        val originalTitle = "Buy chocolate chip cookies"
        val newTitle = "Buy ice cream"

        // Add list item
        onView(withId(R.id.todo_title)).perform(typeText(originalTitle))
        onView(withId(R.id.todo_save_button)).perform(click())


        onView(allOf(withId(R.id.todo_name), withText(originalTitle)))
            .check(matches(isDisplayed()))
            .perform(click())

        // Update it
        onView(withId(R.id.todo_name)).perform(replaceText(newTitle))
        onView(withId(R.id.update_button)).perform(click())
        onView(allOf(withId(R.id.todo_name), withText(newTitle)))
            .check(matches(isDisplayed()))

        // Delete it
        onView(withId(R.id.todo_name)).perform(click())
        onView(withId(R.id.delete_button)).perform(click())
        onView(withId(R.id.todos_list)).check(matches(not(hasDescendant(withText(newTitle)))))
    }
}

This was a brief introduction to using Espresso for writing integration tests on Android. I hope you found it useful and if you have any tips or suggestions please let me know down in the comments. Thank you for reading!

Daniel Perez-Gomez

Hi there! 👋 I'm an Android developer currently based in New York City. I write mostly about Android development using Kotlin as well as other programming bits. I'm committed to making this complex field fun and accessible to beginners through my guides and tutorials. I'm also driven by the belief in technology's power to enhance lives, which motivates me to develop apps that are both user-friendly and prioritize accessibility, catering to various needs. Additionally, I host a YouTube channel, “Daniel Talks Code”, where I break down complex concepts into easy-to-follow instructions. Join me in my quest to make the world of Android development inclusive and accessible for all!

Previous
Previous

Becoming an Explorer

Next
Next

How to write Unit Tests for the Database Access Object on Android