I am displaying a TabLayout and connecting it to a ViewPager2 object (by means of the TabLayoutMediator class). The TabLayout has a tabMode of scrollable and contains more tabs than can fit in the screen at once. I want to assert that a certain one of the tabs is visible and selected when my activity or fragment is rendered. How do I do this?
2 Answers
Thanks to Aaron's answer, I've defined withTabText(text:)
and isSelectedTab()
functions and my test's are now reading more fluently, as follows:
onView(withTabText("SomeText")).check(matches(isCompletelyDisplayed()))
onView(withTabText("SomeText")).check(matches(isSelectedTab()))
The isSelectedTab()
function is implemented as follows:
/**
* @return A matcher that matches a [TabLayout.TabView] which is in the selected state.
*/
fun isSelectedTab(): Matcher<View> =
object : BoundedMatcher<View, TabLayout.TabView>(TabLayout.TabView::class.java) {
override fun describeTo(description: Description) {
description.appendText("TabView is selected")
}
override fun matchesSafely(tabView: TabLayout.TabView): Boolean {
return tabView.tab?.isSelected == true
}
}
The withTabText(text:)
function is implemented as follows:
/**
* @param text The text to match on.
* @return A matcher that matches a [TabLayout.TabView] which has the given text.
*/
fun withTabText(text: String): Matcher<View> =
object : BoundedMatcher<View, TabLayout.TabView>(TabLayout.TabView::class.java) {
override fun describeTo(description: Description) {
description.appendText("TabView with text $text")
}
override fun matchesSafely(tabView: TabLayout.TabView): Boolean {
return text == tabView.tab?.text
}
}
I've added both of these functions to my collection of custom view matchers in the android-test-utils GitHub repo.

- 30,049
- 21
- 112
- 147
-
can you check this [issue](https://stackoverflow.com/a/69813808/11560810) – Kotlin Learner Jan 11 '22 at 17:12
You can create a custom Matcher
for the tabs:
fun withTab(title: String) = withTab(equalTo(title))
fun withTab(title: Matcher<String>): Matcher<View> {
return object : BoundedMatcher<View, TabView>(TabView::class.java) {
override fun describeTo(description: Description) {
description.appendText("with tab: ")
title.describeTo(description)
}
override fun matchesSafely(item: TabView): Boolean {
return title.matches(item.tab?.text)
}
}
}
Then to find if a tab is currently showing, you can conveniently do it with:
onView(withTab("tab text")).check(matches(isCompletelyDisplayed()))
If you want to assert if a tab is currently selected, you can either adjust matchesSafely
to work with item.tab?.isSelected
, or simply create a new matcher.
However if you have more than one TabLayout
on the screen, then you may need to composite your matcher with isDescendantOfA
or withParent
.

- 3,764
- 2
- 8
- 25
-
can you check this [issue](https://stackoverflow.com/a/69813808/11560810) – Kotlin Learner Jan 11 '22 at 17:12