使用 Android Espresso 进行测试时如何单击操作栏项目?

How to click on Action Bar items when testing with Android Espresso?

我正在使用 Android Espresso 来测试我的 activity。我有多个操作栏项目,其中大部分隐藏在溢出中。我正在尝试 运行 此测试,但错误提示层次结构中没有视图(与不可见不同):

@MediumTest
public void testClickInsertItem() {
  Espresso.onView(ViewMatchers.withId(R.id.action_insert)).perform(ViewActions.click());
}

错误:

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: blogr.vpm.fr.blogr:id/action_insert
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:android.widget.ListView{5283cfb0 VFED.VC. ........ 2,2-762,973 #7f07000b app:id/allitems}

View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=768, height=1184, has-focus=true, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+->ActionBarOverlayLayout{id=16909075, res-name=action_bar_overlay_layout, visibility=VISIBLE, width=768, height=1184, has-focus=true, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}
|
+-->FrameLayout{id=16908290, res-name=content, visibility=VISIBLE, width=768, height=1038, has-focus=true, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=146.0, child-count=1}
|
+--->RelativeLayout{id=-1, visibility=VISIBLE, width=768, height=1038, has-focus=true, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+---->ViewPager{id=2131165186, res-name=pager, visibility=VISIBLE, width=764, height=1034, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=2.0, y=2.0, child-count=3}
|
+----->PagerTitleStrip{id=2131165187, res-name=pager_title_strip, visibility=VISIBLE, width=764, height=59, 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, root-is-layout-requested=false, has-input-connection=false, x=763.0, y=0.0, child-count=3}
|
+------>TextView{id=-1, visibility=VISIBLE, width=125, height=43, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=8.0, text=Free text, input-type=0, ime-target=false, has-links=false}
|
(...)
|
+-->ActionBarContainer{id=16909076, res-name=action_bar_container, visibility=VISIBLE, width=768, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=50.0, child-count=2}
|
+--->ActionBarView{id=16909077, res-name=action_bar, visibility=VISIBLE, width=768, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+---->LinearLayout{id=-1, desc=Hello, Navigate up, visibility=VISIBLE, width=124, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+----->HomeView{id=-1, visibility=VISIBLE, width=97, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+------>ImageView{id=16908890, res-name=up, visibility=VISIBLE, width=32, height=32, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=32.0}
|
+------>ImageView{id=16908332, res-name=home, visibility=VISIBLE, width=64, height=64, 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, root-is-layout-requested=false, has-input-connection=false, x=25.0, y=16.0}
|
+----->LinearLayout{id=-1, visibility=VISIBLE, width=27, height=49, 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, root-is-layout-requested=false, has-input-connection=false, x=97.0, y=23.0, child-count=2}
|
+------>TextView{id=16908901, res-name=action_bar_title, visibility=VISIBLE, width=11, height=49, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=Hello, input-type=0, ime-target=false, has-links=false}
|
+------>TextView{id=16908902, res-name=action_bar_subtitle, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false, has-links=false}
|
+---->ActionMenuView{id=-1, visibility=VISIBLE, width=644, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=124.0, y=0.0, child-count=3}
|
+----->EditText{id=2131165210, res-name=postTitle, visibility=VISIBLE, width=420, height=96, 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, root-is-layout-requested=false, has-input-connection=true, editor-info=[inputType=0x1 imeOptions=0x8000005 privateImeOptions=null actionLabel=null actionId=0 initialSelStart=0 initialSelEnd=0 initialCapsMode=0x0 hintText=New Post label=null packageName=null fieldId=0 fieldName=null extras=null ], x=0.0, y=0.0, text=Hello, hint=New Post, input-type=1, ime-target=false, has-links=false}
|
+----->ActionMenuItemView{id=2131165222, res-name=action_publish, desc=Publish, visibility=VISIBLE, width=112, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=420.0, y=0.0, text=, input-type=0, ime-target=false, has-links=false}
|
+----->OverflowMenuButton{id=-1, desc=More options, visibility=VISIBLE, width=112, height=96, 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, root-is-layout-requested=false, has-input-connection=false, x=532.0, y=0.0}
|
+--->ActionBarContextView{id=16909078, res-name=action_context_bar, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=0}
|
+-->ActionBarContainer{id=16909079, res-name=split_action_bar, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=0}
|
at dalvik.system.VMStack.getThreadStackTrace(Native Method)

那么,我该如何访问 ID 为 R.id.action_insert 的按钮项?

我注意到 OverflowMenuButton。我可以单击它,但我会得到另一个看起来不像操作项列表的视图层次结构。我是否应该在视图层次结构中挖掘直到找到我的操作项,或者是否有更好的指定方法来单击溢出中的操作项?我在 Android 文档中找不到任何关于操作栏的文档。

Espresso 有 openActionBarOverflowOrOptionsMenu(Context context) 打开操作栏菜单的方法。您必须将其放在菜单项的测试操作之前。

import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;

@Test
public void testClickInsertItem() {
    openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().getTargetContext());
    onView(withId(R.id.action_insert)).perform(click());
}

希望对collaspingtoolbar的人有所帮助

我有以下菜单布局。

使用 Espresso Recorder 后,我发现菜单按钮是点击 withContentDescription 功能

我在xml中也使用了ToolBarCollapsingToolbarLayout,我在测试中所做的只是使用withContentDescription打开菜单。

menu.xml

<?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_more"
    android:icon="@drawable/ic_more_vert_white_24dp"
    android:title="@string/menu_action_more"
    app:showAsAction="always">
    <menu>
      <item
        android:id="@+id/action_login"
        android:icon="@drawable/ic_account_circle_black_24dp"
        android:orderInCategory="100"
        android:title="@string/menu_login" />
      <item
        android:id="@+id/action_settings"
        android:icon="@drawable/ic_settings_black_24dp"
        android:orderInCategory="100"
        android:title="@string/menu_settings" />
      <item
        android:id="@+id/action_about"
        android:icon="@drawable/ic_info_black_24dp"
        android:orderInCategory="100"
        android:title="@string/menu_about" />
    </menu>
  </item>
</menu>

MainTest.java

      @Test
      public void menu_Login() {        
        onView(withContentDescription(R.string.menu_action_more))
            .perform(click());
        onView(withText("Login")).perform(click());
        intended(hasComponent(LoginActivity.class.getName()));
      }