Android Option Menu UI Testing
How to automate and test Option Menu UI using Kakao DSL.
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
andKButton
etc. - Apply assertions on these views i.e.
isDisplayed()
,hasSize(value)
before and after some actions. - Perform actions on views i.e.
click()
,doubleClick()
andscrollTo()
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)
}
}
}
- Inside
testDeleteAllTasks()
test methodonScreen<HomeScreen> { ... }
lambda is used to access the views objects and associated methods for assertions and actions. - Then it will check whether the
Toolbar
on the screen is displayed or not. - Further it will create a new task and insert it in the list if the list is empty.
After following above steps, we are having at least one task in the list and the toolbar is showing where we have created our options menu.
Open Option Menu
Let’s open the option menu popup now by invoking openContextualActionModeOverflowMenu()
inside testDeleteAllTasks()
test method.
So we have the Menu visible now, we will 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.Testclass 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)
}
}
}