Android Expresso验证上下文菜单和actionBar项目

时间:2017-06-17 16:23:44

标签: android expresso

我有一个列表,其中每一行都包含一个名称和一个调用选项的上下文菜单的按钮。我想写一个验证以下内容的测试

  1. 上下文菜单包含正确的项目数
  2. 上下文菜单包含正确的VALUES
  3. 上下文菜单中不包含任何不合理的选项(上面的检查1和2将测试此情况)
  4. 我还想在长项目选项时测试actionBar和actionBar溢出菜单的内容。

    对于这两个测试,我可以编写一个检查,确保显示一个带有正确“标签”的视图元素(即使用onView查找视图(withText(this.elementText))。但是我有2个动作具有相同的标签,但ID不同,我需要确保上下文菜单/长按菜单中的正确操作。

    我不能将我在XML中指定的ID用于我的上下文菜单菜单,因为Android的上下文菜单视图没有这些ID,而是包含内部Android ID(请参阅下面的屏幕截图)。enter image description here < / p>

    当我使用Robotium编写测试时,我必须获取某种类型的所有当前视图,并通过它们解析它们是否是actionBar项目,请参阅下面的示例代码。

    public static List<MenuItemImpl> getLongClickMenuItems(String itemName) {
        List<MenuItemImpl> menuItems = new ArrayList<>();
    
        // long select the item
        solo.clickLongOnText(itemName);
    
        // get the children of the of the long click action bar
        ArrayList<ActionMenuView> outViews = solo.getCurrentViews(ActionMenuView.class, solo.getView(R.id.action_mode_bar));
    
        if (!outViews.isEmpty()) {
            // get the first child which contains the action bar actions
            ActionMenuView actionMenuView = outViews.get(0);
            // loop over the children of the ActionMenuView which is the individual ActionMenuItemViews
            // only a few fit will fit on the actionBar, others will be in the overflow menu
            int count = actionMenuView.getChildCount();
            for (int i = 0; i < count; i++) {
                View child = actionMenuView.getChildAt(i);
    
                if (child instanceof ActionMenuItemView) {
                    menuItems.add(((ActionMenuItemView) child).getItemData());
                } else {
                    // this is the more button, click on it and wait for the popup window
                    // which will contain a list of ListMenuItemView
                    // As we are using the AppCompat the actionBar's menu items are the
                    // the AppCompat's ListMenuItemView (android.support.v7.view.menu.ListMenuItemView)
                    // In the context menu, the menu items are Android's native ListMenuItemView
                    // (com.android.internal.view.menu.ListMenuItemView)
                    solo.clickOnView(child);
                    solo.waitForView(ListMenuItemView.class);
                    ArrayList<ListMenuItemView> popupItems = solo.getCurrentViews(ListMenuItemView.class);
                    for (ListMenuItemView lvItem : popupItems) {
                        menuItems.add(lvItem.getItemData());
                    }
    
                    // close the more button actions menu
                    solo.goBack();
                }
            }
        }
    
        // get out of long click mode
        solo.goBack();
    
        return menuItems;
    }
    

    有没有人知道如何使用Expresso获取Context Row菜单项列表。

    有没有人知道如何使用Expresso获取actionBar项目(包括溢出菜单中的所有项目)?

2 个答案:

答案 0 :(得分:0)

如果我正确理解了您的问题,您应该可以使用onData()方法与上下文菜单进行交互,因为它们只是AdapterViews(从屏幕截图中注意到弹出窗口是{{ 1}})。

所以你应该可以这样做:

ListPopupWindow$DropDownListView

上面的onView(withText("Item Label")).perform(longClick()); final int expectedItemCount = 10; // Now the floating popup should be showing, // first assert it has the expected item count onView(isAssignableFrom(AdapterView.class)) .check(matches(withItemCount(expectedItemCount))); // Now assert each entry (which should just be a string) is shown correctly for (int i = 0; i < expectedItemCount; i++) { String expectedItemText = getExpectedItemTextForIndex(i); onData(instanceOf(String.class)).atPosition(i) .check(matches(withText(expectedItemText))); } 匹配器是一个简单的匹配器,它根据给定的适配器视图的适配器计数进行断言:

withItemCount

我认为相同的概念应该适用于操作栏溢出菜单。

我不清楚你的意思是:

  

对于这两个测试,我可以编写一个确保有视图的检查   具有正确&#34;标签的元素&#34;显示(即使用查找视图)   onView(withText(this.elementText))。但是我有2个动作   具有相同的标签但不同的ID,我需要确保正确   动作在上下文菜单/长按菜单中。

但是public static Matcher<View> withNumberOfItems(final int itemsCount) { return new BoundedMatcher<View, AdapterView>(AdapterView.class) { @Override public void describeTo(Description description) { description.appendText("with number of items: " + itemsCount); } @Override protected boolean matchesSafely(AdapterView item) { return item.getAdapter().getCount() == itemsCount; } }; } 应该能够准确地获取您对该列表感兴趣的视图,如果您需要在目标项目中作为子视图进行定位,则可以添加atPosition列表。

希望有所帮助!

答案 1 :(得分:0)

非常感谢dominicoder给了我这个问题的答案。在他们的回复工作,我已设法让它工作。

我没有使用“isAssignableFrom(AdapterView.class)”,而是使用“isAssignableFrom(ListView.class)”。

然后我使用完全相同的匹配器“dominicoder”来验证上下文菜单项计数。

使用“dominicoder”的示例匹配器,我能够自己编写一个代码来检查ListView中某个位置的MenuItem,我可以比较ID以确保它是我期望的ID。

public boolean verifyRowContextMenuContents(String name, MyActionObject[] actions){
    // invoke the row context menu
    clickRowActionButton(name);

    // The Context Menu Popup contains a ListView
    int expectedItemCount = actions.length;

    // first check the Popup's listView contains the correct number of items
    onView(isAssignableFrom(ListView.class))
            .check(matches(correctNumberOfItems(expectedItemCount)));

    // now check the order and the IDs of each action in the menu is the expected action
    for (int i = 0; i < expectedItemCount; i++) {
        onView(isAssignableFrom(ListView.class))
                .check(matches(correctMenuId(i, actions[i].getId())));
    }

    // close the context menu
    pressBack();

    return true;
}

private static Matcher<View> correctNumberOfItems(final int itemsCount) {
    return new BoundedMatcher<View, ListView>(ListView.class) {
        @Override
        public void describeTo(Description description) {
            description.appendText("with number of items: " + itemsCount);
        }

        @Override
        protected boolean matchesSafely(ListView listView) {
            ListAdapter adapter = listView.getAdapter();
            return adapter.getCount() == itemsCount;
        }
    };
}

private static Matcher<View> correctMenuId(final int position, final int expectedId) {
    return new BoundedMatcher<View, ListView>(ListView.class) {
        @Override
        public void describeTo(Description description) {
            description.appendText("with position : " + position + " expecting id: " + expectedId);
        }

        @Override
        protected boolean matchesSafely(ListView listView) {
            ListAdapter adapter = listView.getAdapter();
            Object obj = adapter.getItem(position);
            if (obj instanceof MenuItem){
                MenuItem menuItem = (MenuItem)obj;
                return menuItem.getItemId() == expectedId;
            }
            return false;
        }
    };
}   

使用此代码,我可以检查上下文菜单包含正确数量的菜单项,以及菜单中的项目是我期望的(使用ID验证)和我期望的顺序。

非常感谢“多米诺骨牌”。遗憾的是你无法将这两个答案标记为正确,因为你实际上给了我几乎正确的答案。