如何检查在Espresso UI自动化测试中启用/禁用MenuItem

时间:2017-04-05 04:17:20

标签: android menuitem android-espresso

我正在Espresso for Android中编写UI自动化测试。遇到了一个我到目前为止还没有得到任何解决方案的场景。

在一个Fragment中,我OptionsMenu只有一个项目。根据API响应的值设置MenuItem的状态。

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    menu.clear();
    getActivity().getMenuInflater().inflate(R.menu.menu_cancel_order, menu);
    MenuItem cancelMenuItem = menu.findItem(R.id.cancel_order);
    if(something) { // something can be a boolean value from server
        cancelMenuItem.setEnabled(true);
    } else {
        cancelMenuItem.setEnabled(false);
    } 
}

对于UI测试,我需要编写测试用例以检查是否启用/禁用此MenuItem

点击overflowmenu,

ViewInteraction actionMenuItemView = onView(
            allOf(withId(R.id.action_settings), withContentDescription("Settings"), isDisplayed()));
actionMenuItemView.perform(click());

到目前为止,我试图检查断言的内容如下:

onView(allOf(withText("Cancel Order"), withId(R.id.cancel_order))).check(matches(not(isEnabled())));

但这会使NoMatchingViewException触发消息

  

NoMatchingViewException:找不到层次结构中的视图匹配:(带   text:is" Cancel Order"和id:   com.equinix.ecp.betatest:ID / cancel_order)

所以我尝试将其更改为

onView(allOf(withText("Cancel Order"))).check(matches(not(isEnabled())));

不知何故,这与视图匹配,但它不是MenuItem,而是MenuItem&中的TextView。由于我将setEnabled()设置为MenuItem,check()断言因为TextView而无法按预期工作。

所以我的问题是如何编写Test以检查MenuItem的启用/禁用状态。

2 个答案:

答案 0 :(得分:0)

我建议您使用菜单项的ID来执行检查。 我用这个菜单试了一下:

<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="at.hellobank.hellomarkets.symbols.DetailActivity">

<item
    android:id="@+id/action_1"
    android:icon="@android:drawable/arrow_down_float"
    android:title="Menu1"
    app:showAsAction="always" />

<item
    android:id="@+id/action_2"
    android:enabled="false"
    android:icon="@android:drawable/arrow_down_float"
    android:title="Menu2"
    app:showAsAction="always" />
</menu>

因此启用了一个菜单项,其中一个被禁用。我检查这个的测试看起来像这样,并按预期工作:

@Test
public void testMenuItemsStatus() throws Exception {
    onView(withId(R.id.action_1)).check(matches(isEnabled()));
    onView(withId(R.id.action_2)).check(matches(not(isEnabled())));
}

通常在测试中使用ID更好,因为您更加独立于拼写错误和一般语言。如果您测试使用其他语言本地化的应用,withText("Cancel Order")可能无效。

答案 1 :(得分:0)

最好使用uiautomatorviewer,在测试失败的位置插入一个断点,然后检查应用的布局以寻找线索

在我看来,您有两种看法。一个ID为R.id.cancel_order,另一个ID为文本"Cancel Order",该文本可能具有另一个ID(或可能/应该)。 因此它们一起返回NoMatchingView,因为它们不是同一视图。

它们可能是同级视图,或者一个视图可能是另一个视图的后代。 uiautomatorviewer在这里很方便找出屏幕上发生的事情

只要已安装“ Android SDK平台工具”和“ Android SDK工具” 从终端:

cd /Users/<user name>/Library/Android/sdk/tools/bin
./uiautomatorviewer

(将其另存为脚本,并且为了方便起见仅使用别名快捷方式也很有帮助)

至于您的匹配者,我会尝试:

onView(allOf(
    withId(R.id.cancel_order),
    hasSibling(withText("Cancel Order")) 
)).check(matches(not(isEnabled())));

或将hasSibling(_)更改为hasDescendent(_)isDescendentOfA(_),具体取决于它们之间的关系(您可以使用uiautomatorviewer找出它们)