Android Option Menu UI Testing

Android Option Menu UI Testing

How to automate and test Option Menu UI using Kakao DSL.

ยท

3 min read

In this article, we will automate user interaction and test the Toolbar option menu. Option menu is actually representing a list of items to be shown to the user to perform associated actions. Please check my article for the basics of Android UI testing.

Scenario

When a user clicks on the menu icon it will show a drop-down list having two items Delete All Tasks and Show History, so by clicking on the first item it will show a confirmation popup to ask the user for deleting all tasks from the app.

Setup

Add following dependencies to module-level build.gradle file

testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
androidTestImplementation("io.github.kakaocup:kakao:3.0.4")

Create Screen Class

Let's create a class extending from Screen in androidTest directory

class HomeScreen : Screen<HomeScreen>() {
    private val toolbar = KToolbar { withId(R.id.toolbar) }
    private val deleteAll = KView {
        withText(R.string.label_delete_all) 
    }

    private val yesView = KView { withText(R.string.yes) }
    private val noView = KView { withText(R.string.no) }
    private val deleteAllTitle = KView { 
        withText(R.string.delete_all_title) 
    }
    private val deleteAllDescription = KView { 
        withText(R.string.delete_all_description) 
    }

    fun assertToolbar() {
        toolbar.isDisplayed()
    }

    fun showConfirmationDialog() {
        deleteAllView.click()
        assertConfirmationDialog()
    }

    fun confirmDeleteAllTask(confirmOption: ConfirmOption){
        if (confirmOption == ConfirmOption.YES) {
            yesView.perform {
                click()
            }
        } else {
            noView.perform {
                click()
            }
        } 
    }

    fun assertTasksListEmptiness(){
        recyclerView {
            hasSize(0)
        }
    }

    private fun assertConfirmationDialog() {
        deleteAllTitle.isDisplayed()
        deleteAllDescription.isDisplayed()
        yesView.isDisplayed()
        noView.isDisplayed()
    }

    fun isTasksListEmpty(): Boolean {
        return recyclerView.getSize() == 0
    }

    enum class ConfirmOption {
        YES,
        NO
    }
}

In Kakao Framework the Screen<T> class is basically used for following uses,

  • Get the views references KToolbar, KView and KButton etc.
  • Apply assertions on these views i.e. isDisplayed(), hasSize(value) before and after some actions.
  • Perform actions on views i.e. click(), doubleClick() and scrollTo() etc.

Write Test Class

Now let's access HomeScreen views, assertions and actions methods inside our UI test to implement automation.

class TaskPlannerTests {
    @Test
    fun testDeleteAllTasks(){
        onScreen<HomeScreen> {
            assertToolbar()
            if(isTasksListEmpty()) {
                performClickOnFAButton()
                createNewTask()
            }
        }
        ...
    }

    private fun createNewTask() {
        onScreen<NewTaskScreen> {
            saveHappyTask()
        }
        onScreen<HomeScreen> {
            assertRecyclerView(newTaskTitle)
        }
    }
}
  1. Inside testDeleteAllTasks() test method onScreen<HomeScreen> { ... } lambda is used to access the views objects and associated methods for assertions and actions.
  2. Then it will check whether the Toolbar on the screen is displayed or not.
  3. Further it will create a new task and insert it in the list if the list is empty.

After following the above steps, we are having at least one task in the list and the toolbar is showing where we have created our options menu.

IMPORTANT: Let's open the option menu popup now by invoking openContextualActionModeOverflowMenu() inside testDeleteAllTasks() test method.

We are now able to click on the Delete All Tasks option in the menu.

onScreen<HomeScreen> {
    showConfirmationDialog()
    confirmDeleteAllTask(HomeScreen.ConfirmOption.YES)
    assertTasksListEmptiness()
}

On deleting all tasks from the list we also check our expected output that the list is empty or not now by assertTasksListEmptiness()

Test Class Code

Check the implementation detail on GitHub repo

import androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu
import com.android.dayplanner.app.screens.HomeScreen
import com.android.dayplanner.app.screens.NewTaskScreen
import io.github.kakaocup.kakao.screen.Screen.Companion.onScreen
import org.junit.Test

class TaskPlannerTests {
    @Before
    fun setup() {
        ActivityScenario.launch(MainActivity::class.java)
    }

    @Test
    fun testDeleteAllTasks(){
        onScreen<HomeScreen> {
            assertToolbar()
            if(tasksListIsEmpty()) {
                performClickOnFAButton()
                createNewTask()
            }
        }

        openContextualActionModeOverflowMenu()

        onScreen<HomeScreen> {
            showConfirmationDialog()
            confirmDeleteAllTask(HomeScreen.ConfirmOption.YES)
            assertTasksListEmptiness()
        }
    }

    private fun createNewTask() {
        onScreen<NewTaskScreen> {
            saveHappyTask()
        }
        onScreen<HomeScreen> {
            assertRecyclerView(newTaskTitle)
        }
    }
}

Final Fruit ๐Ÿฅ‘

ezgif.com-video-to-gif.gif

ย