意式浓缩咖啡点击菜单项

我在操作栏中有一个菜单,我通过以下方式创建:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    menu.add(Menu.NONE, 98,Menu.NONE,R.string.filter).setIcon(R.drawable.ic_filter_list_white_48dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    menu.add(Menu.NONE, 99,Menu.NONE,R.string.add).setIcon(R.drawable.ic_add_white_48dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);


    getMenuInflater().inflate(R.menu.menu_main, menu);

    return true;
}

menu_main.xml看起来像这样:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">
    <item
        android:id="@+id/action_settings"
        android:title="@string/action_settings"
        android:orderInCategory="100"
        app:showAsAction="never"
        android:icon="@drawable/ic_settings_white_48dp"/>
</menu>

在Espresso中测试时,我想点击“添加”图标(menuId 99)。我试过了

@Test
public void testAdd() {
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
    onView(withText(R.string.add)).perform(click());
}

但这在NoMatchingViewException中失败。(设置项,它是在xml中直接定义的,我可以用相同的代码单击。

这是针对targetSdkVersion 23和AppCompatActivity的。工具栏的相关行包括:

Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
if( getSupportActionBar() != null ) {
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

tool_bar.xml看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar     xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:background="@color/ColorPrimary"
    android:elevation="4dp"
    tools:ignore="UnusedAttribute">
</android.support.v7.widget.Toolbar>

答案 1

更新:我没有看到行的最后一行,忽略我之前的回复,我试图快速修复它,我做错了。我真的不知道答案。

...setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)

您的问题由Espresso团队在这里解释:

匹配可见图标:

  // Click on the icon - we can find it by the r.Id.
  onView(withId(R.id.action_save))
    .perform(click());

对于正常的操作栏来说,单击溢出菜单中的项目有点棘手,因为某些设备具有硬件溢出菜单按钮(它们将在选项菜单中打开溢出项),而某些设备具有软件溢出菜单按钮(它们将打开正常的溢出菜单)。幸运的是,Espresso为我们处理了这个问题。

  // Open the overflow menu OR open the options menu,
  // depending on if the device has a hardware or software overflow menu button.
  openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());

  // Click the item.
  onView(withText("World"))
    .perform(click());

因此,我理解这两种选择都是正确的,但取决于您的具体情况。如果您测试一个按钮,您通常会知道它在那一刻是否可见。

在你的情况下,按钮是可见的,因为有空间,并且像下面这样使用是正确的:withId

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

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

但对于溢出项目,这也是正确的:

是的,这就是它在Espresso中的工作方式。这里的问题是,在Android中,表示菜单项的视图没有菜单项的ID。所以 onView(withId(X)) 只是找不到一个视图。我没有比使用withText()更好的建议了。如果您有多个具有相同文本的视图,则使用层次结构进行区分是有效的。

现在我的问题是,当您在不同的设备上进行测试并且不知道何时会为某个项目留出空间时该怎么办。我不知道回应,也许结合这两种解决方案。


答案 2

这是我的解决方案,涵盖了所有三种情况:硬件菜单按钮,溢出菜单,仅图标:

    try {
        openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
    } catch (Exception e) {
        //This is normal. Maybe we dont have overflow menu.
    }
    onView(anyOf(withText(R.string.<your label for the menu item>), withId(R.id.<id of the menu item>))).perform(click());