UI Testing with Kakao Tutorial for Android: Getting Started

In this UI Testing with Kakao tutorial for Android, you’ll learn how to create simple, readable UI tests using Kakao and why these are important. By Fernando Sproviero.

Leave a rating/review
Download materials
Save for later
Share

There are several ways to test an app. One of the most important ways is creating UI Tests. These tests run on a device or emulator and interact with the screens of your app, emulate user behavior and verify UI results.

Although UI tests are slow and expensive, they are important because they help to avoid unexpected results or bad user experiences by simulating various possible user scenarios.

In this tutorial you’ll learn how to use Kakao to write UI tests. UI tests on Android are typically written using Espresso. Kakao a library that provides a Domain Specific Language (DSL) for writing expressive Espresso tests.

Note: This tutorial assumes you have previous experience with developing for Android in Kotlin. If you are unfamiliar with the language have a look at this tutorial. If you’re beginning with Android, check out some of our Getting Started and other Android tutorials.

Note: This tutorial assumes you have previous experience with developing for Android in Kotlin. If you are unfamiliar with the language have a look at this tutorial. If you’re beginning with Android, check out some of our Getting Started and other Android tutorials.

Espresso and Kakao

Espresso is an open source testing framework from Google. They created it to provide an API to create UI tests with the following characteristics in mind:

  • Small
  • Predictable
  • Easy to learn API

Kakao is a library built on top of Espresso. Agoda, which has created more than a thousand automated tests for their codebase, developed it when they realized the code readability of their tests was quite low when using Espresso. They developed this library pursuing the following benefits:

  • Readability
  • Reusability
  • Extensible DSL

Getting Started

Throughout this tutorial you’ll work with IngrediSearch, an app that allows users to search for recipes and favorite them.

To start, download the sample project using the Download Materials button at the top or bottom of this tutorial. Open Android Studio 3.3 or later, click File ▸ New ▸ Import Project and select the top-level project folder for the starter project you downloaded. Alternatively, to open the project you can select Open an existing Android Studio project from the Welcome screen, again choosing the top-level project folder for the starter project you downloaded.

Before you can run the app, you need an API key. This app relies on the Food2Fork API, which requires an API key. To set this up:

  • Get your Food2Fork API key by creating an account here
  • Create a keystore.properties file in the root project. File location screenshot
  • Add the following content to the file, placing the API key you just got within the quotes: FOOD2FORK_API_KEY="YOUR API KEY"

You’re all set. Build and run the project to become familiar with it:

The project contains the following main files:

  • MainActivity.kt contains the main screen.
  • SearchActivity.kt allows the user to input ingredients.
  • SearchResultsActivity.kt searches for recipes using the API and shows the results. It also provides the ability to add or remove favorites.
  • RecipeActivity.kt shows the recipe detail.
  • FavoritesActivity.kt shows the list of favorites.
  • RecipeRepository.kt interacts with the API to search for recipes. It also stores the favorites in SharedPreferences.
  • RecipeAdapter.kt is an adapter used to show the list in SearchResultsActivity and FavoritesActivity.

Note: Because this project was also used for a Unit Test Tutorial, you’ll find other files under the app ‣ src ‣ test ‣ java ‣ com ‣ raywenderlich ‣ android ‣ ingredisearch directory. These files contain unit tests which are different from UI tests.

Unit tests are smaller tests that verify class method outputs or state based on a set of given input. Check the Unit Test Tutorial to know more about them.

Note: Because this project was also used for a Unit Test Tutorial, you’ll find other files under the app ‣ src ‣ test ‣ java ‣ com ‣ raywenderlich ‣ android ‣ ingredisearch directory. These files contain unit tests which are different from UI tests.

Unit tests are smaller tests that verify class method outputs or state based on a set of given input. Check the Unit Test Tutorial to know more about them.

Setup

You need to make sure you have all your dependencies and configurations ready to start testing. Open build.gradle for the app module and add the following dependencies:

  androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
  androidTestImplementation 'androidx.test:runner:1.1.1'
  androidTestImplementation 'androidx.test:rules:1.1.1'
  androidTestImplementation 'com.agoda.kakao:kakao:2.0.0'

The first three dependencies are part of Android’s standard testing libraries. The fourth is the Kakao library.

Also add the testInstrumentationRunner line below to the same file. The android and defaultConfig lines are to help you know where in the file to place the line:

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

AndroidJUnitRunner is the entry point for running the entire suite of instrumentation tests. It controls the test environment and test APK and launches all of the tests defined in your androidTest package.

Sync your Gradle files after these changes.

Note: When you create a new project, Android Studio will include the test instrumentation runner and some of the dependencies mentioned. Here you are adding them manually for educational purposes.

Creating UI Tests

Basics

UI tests involve the following steps:

  1. Finding the view: First, you’ll look for a view where you’ll perform actions or verify states. You’ll use ViewMatchers for this. Normally, you’ll find a view by its id.
  2. Performing an action: After finding the view, you’ll perform some kind of action on it such as a click or a gesture. These are ViewActions. This step is optional and you only need it if there’s an action you want to perform.
  3. Verifying: Finally, you’ll check something on the view. For example, you might check if it’s visible, has changed the position or if the text or color changed. These are ViewAssertions.

Creating Your First UI Test

Create a package called search under app ‣ src ‣ androidTest ‣ java ‣ com ‣ raywenderlich ‣ android ‣ ingredisearch. Notice that you’re putting it under androidTest instead of test. This is because tests that require a device or emulator are instrumented tests, which go in this directory.

Your first test will check that searching with an empty text shows a Snackbar with an error message.

First, the test set up. Create a new class called SearchUITests in the directory you just created. Then, place the following class in the same file above the SearchUITests class:

class SearchScreen : Screen<SearchScreen>() {
  val searchButton = KButton { withId(R.id.searchButton) }
  val snackbar = KView { 
    withId(com.google.android.material.R.id.snackbar_text) 
  }
}

You want to import com.raywenderlich.android.ingredisearch.R when prompted, and the com.agoda.kakao.* imports for the others. Unless otherwise noted, default to these imports for this tutorial. You can add imports automatically using Alt + Enter with your cursor placed on the unresolved reference.

Kakao requires a class that inherits from Screen. In this Screen you add the views involved in the interactions of the tests. This can represent a portion or the whole user interface.

The above code sets up the Screen for the search screen. In in you have references to the search button and the Snackbar views. You find them both with a ViewMatcher. In this case, you find the button and the Snackbar with their ids.

With that set up, it’s time to write the test. Replace the SearchUITests class with the following:

// 1
@LargeTest
class SearchUITests {

  // 2
  @Rule
  @JvmField
  var rule = ActivityTestRule(SearchActivity::class.java)

  // 3
  private val screen = SearchScreen()

  // 4
  @Test
  fun search_withEmptyText_shouldShowSnackbarError() {
    // 5
    screen {
      searchButton.click()
      snackbar.isDisplayed()
    }
  }
}
    Here’s what that code does:
  1. Annotates the class with @LargeTest. This is not required but is recommended because you can run a group of tests with this annotation. In the Android ecosystem functional UI tests are considered large tests.
  2. Annotates with @Rule and instantiates an ActivityTestRule. This launches the activity before running each test.
  3. Instantiates the screen where you’ll perform actions and verifications.
  4. Annotates the method with @Test to let the test runner know that this method is a test.
  5. Using the screen object, performs a click, the ViewAction, on the button and verifies that the Snackbar displays, the ViewAssertion.