Test MenuItem Checkable with Espresso

Asked 2 years ago, Updated 2 years ago, 43 views

I would like to test checkable menu items.
You can check the display status of regular menu items as follows, but

onView(withText(R.string.action_one))).check(matches(isDisplayed()))
            .perform(click());

When this item is checkable, I wanted to check its check status, so I wrote the following, but I got an error when I couldn't find a View in the hierarchy.

onView(allOf(withClassName(endsWith("CheckBox")), hasSibling(withText(R.string.action_one)))))
            .check(matches(isNotChecked()))
            .perform(click());

CheckBox is in the hierarchy dump reported at the time (AppCompatCheckBox).
But I'm certainly not a brother of TextView with Action 1. (He seems to be one step up.)

View Hierarchy:
+>PopupViewContainer {id=-1, visibility=VISIBLE, width=636, height=336, has-focus=true, has-focus=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focus=is-false, is-false=is-false, is-false ,is-false
|
+->DropDownListView { id=-1, visibility=VISIBLE, width=588, height=288, has-focus=true, has-focus=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-fuscous=true, is-fuscous=true, is-fuscousabletrue
|
+---->ListMenuItemView {id=-1, visibility=VISIBLE, width=588, height=144, has-focus=false, has-window-focus=false, is-clickable=false, is-enabled=true, is-false, is-false=false, is-false, is-false=false, is-false=false, is-false
|
+--- RelativeLayout {id=-1, visibility=VISIBLE, width=396, height=65, has-focus=false, has-focus=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focus=false, is-focus=false, is-false=false, is-falseqfalse, is-false ,false
|
+---->AppCompatTextView{id=2131492945, res-name=title, visibility=VISIBLE, width=396, height=65, 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=アクション1,  input-type=0, image-target=false, has-links=false}
|
+---->AppCompatTextView{id=2131492961, res-name=shortcut, 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, image-target=false, has-links=false}
|
+--->AppCompatCheckBox{id=2131492960, res-name=checkbox, visibility=VISIBLE, width=96, 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=444.0, y=24.0, text=, input-type=0, image-target=false, has-links=false, is-checked=false}
|
+---->ListMenuItemView {id=-1, visibility=VISIBLE, width=588, height=144, has-focus=false, has-window-focus=false, is-clickable=false, is-enabled=true, is-false, is-false=false, is-false, is-false=false, is-false=false, is-false
|
+--- RelativeLayout { id = -1, visibility = VISIBLE, width = 492, height = 65, has-focus = false, has-window-focus = true, is-clickable = false, is-enabled = true, is-focal = false, is-focal = false = false, is-focal = false - false, is-focal f false = false, is-focal f false
|
+---->AppCompatTextView{id=2131492945, res-name=title, visibility=VISIBLE, width=492, height=65, 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=アクション2, input-type=0, image-target=false, has-links=false}
|
+---->AppCompatTextView{id=2131492961, res-name=shortcut, 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, image-target=false, has-links=false}
|

If you know how to write in this case, please let me know.

android

2022-09-30 17:50

1 Answers

Self-resolved.

I have posted a solution to Qiita, so please refer to it if you like.
http://qiita.com/kasa_le/items/b517146b532a17f40365

In the end, I tried and tried to create a Matcher based on the hierarchical state of View that I mentioned in the question as follows:

Receiving all the objects in the Checkbox class, looking for TextView among the child Views that its parent View has, and checking to see if it has the specified title string.

If the OS version is different, it may be out, but I think it will be fine while using support-library...but I can't guarantee anything.

public static MenuItemTitleMatcher with CheckBoxTitle (final String title) {
    return new MenuItemTitleMatcher(title);
}

public static class MenuItemTitleMatcher extensions BaseMatcher <Object>{
    private final String title;

    publicMenuItemTitleMatcher(String title){
        This.title=title;
    }

    TextView getChildTextView (ViewGroup view, String title) {
        int num=view.getChildCount();
        for(inti=0;i<num;i++){
            Viewchild=view.getChildAt(i);
            if (child instance of TextView) {
                if(title.equals(((TextView)child).getText())){
                    return(TextView) child;
                }
            }
        }
        return null;
    }

    @ Override
    public boolean matches (Objecto) {
        if(o instance of CheckBox){
            CheckBox checkbox=(CheckBox)o;
            ViewParent parent=checkbox.getParent();
            if(parent instance of ListMenuItemView) {
                // Look for TextView in child ViewGroup
                int num=((ListMenuItemView) parent).getChildCount();
                for(inti=0;i<num;i++){
                    View child=((ListMenuItemView) parent).getChildAt(i);
                    if(child==o)continue;
                    if (child instance of ViewGroup) {
                        TextView textView=getChildTextView((ViewGroup)child, title);
                        if(textView!=null)
                            return true;
                    }
                }
            }
            return false;
        }
        return false;
    }

    @ Override
    public void descriptionTo (Description description) {
        description.appendText("expected with Title:");
        description.appendText("+title);
    }
}

Usage

onView(allOf(withClassName(endsWith("CheckBox")),
            EspressoUtil.withCheckBoxTitle(getString(R.string.action_lock)))
            .check(matches(isNotChecked()))
            .perform(click());


2022-09-30 17:50

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.