发布
社区首页 >问答首页 >无法使用Espresso在UI测试选项菜单中使用withId方法选择视图/菜单项

无法使用Espresso在UI测试选项菜单中使用withId方法选择视图/菜单项
EN

Stack Overflow用户
提问于 2020-04-05 07:34:54
回答 3查看 519关注 0票数 0

我正在做一个Android Kotlin项目。我正在将使用Espresso框架编写的UI测试添加到我的项目中。但是在我的测试中,我不能使用withId()方法在操作栏中选择options菜单的菜单项。

下面是我如何将菜单添加到活动中的操作栏中。

代码语言:javascript
代码运行次数:0
复制
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.event_list, menu)

        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
             R.id.action_logout -> {
                 ApplicationController.instance.clearLoginData()
                 finish()
             }
        }

        return super.onOptionsItemSelected(item)
    }

这是菜单资源文件夹中的event_list.xml

代码语言:javascript
代码运行次数:0
复制
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_logout"
        android:icon="@android:drawable/ic_lock_power_off"
        android:title="@string/menu_item_logout"
        app:showAsAction="never"/>
</menu>

这就是我的测试方法

代码语言:javascript
代码运行次数:0
复制
@Test
fun itWipesOutLoginDataWhenLogoutMenuItemIsTapped() {
    FakeEventService.SCENARIO_UNDER_TEST = 0
    this.eventListActivityRule.launchActivity(null)
    openActionBarOverflowOrOptionsMenu(ApplicationProvider.getApplicationContext<Context>())

    onView(withId(R.id.action_logout)).perform(click())
}

正如您在测试方法中看到的,我使用withId()方法选择菜单项。但是当我运行测试时,我得到了以下错误。

代码语言:javascript
代码运行次数:0
复制
androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: com.example.memento:id/action_logout
If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:androidx.appcompat.widget.MenuPopupWindow$MenuDropDownListView{2582e16 VFED.VC.. ........ 0,0-686,168}

View Hierarchy:
+>PopupDecorView{id=-1, visibility=VISIBLE, width=686, height=168, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(740,98)(686x168) gr=TOP START CENTER DISPLAY_CLIP_VERTICAL sim={state=unchanged} ty=APPLICATION_SUB_PANEL fmt=TRANSLUCENT surfaceInsets=Rect(112, 112 - 112, 112) (manual)
fl=LAYOUT_NO_LIMITS ALT_FOCUSABLE_IM WATCH_OUTSIDE_TOUCH SPLIT_TOUCH HARDWARE_ACCELERATED FLAG_LAYOUT_ATTACHED_IN_DECOR
pfl=WILL_NOT_REPLACE_ON_RELAUNCH LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+->PopupBackgroundView{id=-1, visibility=VISIBLE, width=686, height=168, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@de56b69, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+-->MenuDropDownListView{id=-1, visibility=VISIBLE, width=686, height=168, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@4044e8f, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+--->ListMenuItemView{id=-1, visibility=VISIBLE, width=686, height=168, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.AbsListView$LayoutParams@393b6fa, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+---->AppCompatImageView{id=2131230882, res-name=group_divider, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@70144ab, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+---->LinearLayout{id=2131230818, res-name=content, visibility=VISIBLE, width=686, height=168, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@d648c6, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+----->RelativeLayout{id=-1, visibility=VISIBLE, width=574, height=76, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@4a503dd, tag=null, root-is-layout-requested=false, has-input-connection=false, x=56.0, y=46.0, child-count=2}

我的代码出了什么问题?我该如何修复它?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-22 23:04:15

对于在这里搜索答案的人来说,与菜单交互的最简单方法是使用Barista库。它提供了像clickMenu(R.id.menu_item)openMenu()这样的方法来实现简单的菜单交互。即使项隐藏在溢出中,单击也可以工作。

我在我的Android UI testing tutorial中对它进行了示例测试。

票数 1
EN

Stack Overflow用户

发布于 2020-04-07 06:22:29

在选择菜单项时不能使用withId,因为菜单是用它们自己的视图和id放大的,因此您的id action_logout永远不会存在于视图层次结构(NoMatchingViewException)中:

尝试使用不同的视图匹配器,例如使用withText

代码语言:javascript
代码运行次数:0
复制
openActionBarOverflowOrOptionsMenu(ApplicationProvider.getApplicationContext<Context>())
onView(withText("your_menu_item_logout_string")).perform(click())

还请注意,当菜单打开(弹出)时,所有后续的测试交互都将在菜单中执行,直到它被清除,因此您不必担心背景视图中的冲突匹配。

票数 2
EN

Stack Overflow用户

发布于 2020-09-09 06:44:05

我遇到了这个问题,并尝试使用openActionBarOverflowOrOptionsMenu(),如Aaron的答案所示,但得到了一个"no overflowmenubutton“错误。然而,他的回答证实了我所认为的测试找不到我真正想要测试的菜单小部件的原因。因此,我尝试了其他一些我认为可以访问工具栏的东西,从而允许找到小部件,并通过以下操作获得了成功:

代码语言:javascript
代码运行次数:0
复制
onView(withId(R.id.my_toolbar)).check(matches(isDisplayed()));
onView(withId(R.id.my_toolbar)).check(matches(hasDescendant(withId(R.id.action_add))));
onView(withId(R.id.action_add)).perform(click());

我的猜测是,这个序列标识工具栏,然后允许小部件"action_add“按钮通过它的ID被找到。当我运行这个测试时,目标意图被打开,从而验证执行(action_add())确实点击了"action_add”小部件。

我希望这对处于同样困境的人有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61036163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档