如何使用Espresso测试在Tab Layout中选择特定的选项卡位置

12

我有一个带有视图页面的选项卡布局。我正在使用 Espresso 测试我的Android应用程序。在我的以前的项目中,我使用选项卡标题来执行点击以选择选项卡位置,如下所示。

我有一個帶有視圖頁面的選項卡佈局。我正在使用 Espresso 測試我的Android應用程式。在我的以前的專案中,我使用選項卡標題來執行點擊以選擇選項卡位置,如下所示。

    Espresso.onView(ViewMatchers.withText("MAP"))
            .perform(ViewActions.click());

我现在有114个选项卡,所以我不能使用上面的方法随机选择这些选项卡进行测试。有没有办法可以通过它们的位置来选择选项卡。我已经检查了其他解决方案,但都没有帮助。

3个回答

32

使用自定义 ViewAction 应该是可行的。类似这样:

fun selectTabAtPosition(tabIndex: Int): ViewAction {
    return object : ViewAction {
        override fun getDescription() = "with tab at index $tabIndex"

        override fun getConstraints() = allOf(isDisplayed(), isAssignableFrom(TabLayout::class.java))

        override fun perform(uiController: UiController, view: View) {
            val tabLayout = view as TabLayout
            val tabAtIndex: TabLayout.Tab = tabLayout.getTabAt(tabIndex)
                    ?: throw PerformException.Builder()
                            .withCause(Throwable("No tab at index $tabIndex"))
                            .build()

            tabAtIndex.select()
        }
    }
}

以及用途:

onView(withId(R.id.tab_layout)).perform(selectTabAtPosition(99))

如何在GridView中向下滚动以执行操作,因为测试是在第5个索引位置之前执行的,剩余的项目在滚动之前不可见。 - RockyGlobal

10

以上两个答案都很好。对于我来说,在选择标签后,我还想通过与标题匹配来验证它是否是正确的标签。由于这篇文章是关于浓缩咖啡测试的,我将在此分享代码片段,因为它可能对某些人有帮助。

fun matchCurrentTabTitle(tabTitle: String): Matcher<View> {
return object : TypeSafeMatcher<View>() {
    override fun describeTo(description: Description?) {
        description?.appendText("unable to match title of current selected tab with $tabTitle")
    }

    override fun matchesSafely(item: View?): Boolean {
        val tabLayout = item as TabLayout
        val tabAtIndex: TabLayout.Tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)
                ?: throw PerformException.Builder()
                        .withCause(Throwable("No tab at index ${tabLayout.selectedTabPosition}"))
                        .build()

        return tabAtIndex.text.toString().contains(tabTitle, true)
    }
  }
}

fun matchTabTitleAtPosition(tabTitle: String, tabIndex: Int): Matcher<View> {
return object : TypeSafeMatcher<View>() {
    override fun describeTo(description: Description?) {
        description?.appendText("unable to select tab at index $tabIndex and match title with $tabTitle")
    }

    override fun matchesSafely(item: View?): Boolean {
        val tabLayout = item as TabLayout
        val tabAtIndex: TabLayout.Tab = tabLayout.getTabAt(tabIndex)
                ?: throw PerformException.Builder()
                        .withCause(Throwable("No tab at index $tabIndex"))
                        .build()

        return tabAtIndex.text.toString().contains(tabTitle, true)
    }
  }
}

9

作为一个没有转换/使用 Kotlin 的人,这里是 Java 版本。它基本上与 @Be_Negative 相同,所以只需以相同方式使用即可。

@NonNull
private static ViewAction selectTabAtPosition(final int position) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return allOf(isDisplayed(), isAssignableFrom(TabLayout.class));
        }

        @Override
        public String getDescription() {
            return "with tab at index" + String.valueOf(position);
        }

        @Override
        public void perform(UiController uiController, View view) {
            if (view instanceof TabLayout) {
                TabLayout tabLayout = (TabLayout) view;
                TabLayout.Tab tab = tabLayout.getTabAt(position);

                if (tab != null) {
                    tab.select();
                }
            }
        }
    };
}

谢谢。我会研究一下。 - Vinayak B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接