Пункт меню "Эспрессо"

У меня есть меню в панели действий, с которой я создаю:

@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());
}

Но this он также подходит для элементов переполнения:

Да, так оно и работает в Espresso. Проблема здесь в том, что в Android, представление, представляющее элемент меню, не имеет идентификатора пункт меню. Поэтому onView (withId (X)) просто не находит View. Я не имеют лучшую рекомендацию, чем просто использовать withText(). Если у вас есть несколько видов с одним и тем же текстом, используя иерархию для разграничения работы.

Теперь мой вопрос - что делать, когда вы тестируете на разных устройствах, и вы не знаете, когда будет место для элемента. Я не знаю ответа, возможно, сочетаю оба решения.

Ответ 2

Этот метод можно использовать для выбора пункта меню. Сначала нажмите кнопку меню, используя этот код

openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());

Затем выполните пункт меню щелчка на основе текста. Замените имя вашего меню "MenuItemName"

onView(withText("MenuItemName")).perform(click());

Ответ 3

Espresso.openContextualActionModeOverflowMenu() 

был единственным вариантом, который работал на моем Samsung Note 3. Этот openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); попытался бы и без ошибок проиграть

Ответ 4

Панель инструментов не является actionBar, нет необходимости в вызове:

openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());

И если вы это сделаете, убедитесь, что ваш элемент не будет найден там (это не в ActionBar), а ToolBar принадлежит к "нормальному виду".

Ответ 5

Это мое решение, которое охватывает все три ситуации: меню аппаратного меню, меню переполнения, только значки:

    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());

Ответ 6

Используйте это для соответствия тексту описания элемента меню:

onView(withContentDescription(R.string.add)).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());