

checkableなメニューアイテムのテストをしたいです。  
通常のメニューアイテムは、以下のように表示状態を確認出来ますが、

[code]

    onView(withText(R.string.action_one)).check(matches(isDisplayed()))
                .perform(click());
    
[/code]

このアイテムがcheckableなときに、そのチェック状態を確認したくて、以下のように書きましたが、階層内にViewが見つからないとエラーになりました。

[code]

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

その時報告された階層ダンプ内には、CheckBoxが存在しています(AppCompatCheckBox)。  
でも確かに"アクション１"を持つTextViewの兄弟ではないです。（1つ上にいるようです）

[code]

    View Hierarchy:
    +>PopupViewContainer{id=-1, visibility=VISIBLE, width=636, height=336, has-focus=true, has-focusable=true, 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, child-count=1}
    |
    +->DropDownListView{id=-1, visibility=VISIBLE, width=588, height=288, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=24.0, y=24.0, child-count=2}
    |
    +-->ListMenuItemView{id=-1, visibility=VISIBLE, width=588, height=144, 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, child-count=2}
    |
    +--->RelativeLayout{id=-1, 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=48.0, y=39.0, child-count=2}
    |
    +---->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=アクション１, input-type=0, ime-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, ime-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, ime-target=false, has-links=false, is-checked=false}
    |
    +-->ListMenuItemView{id=-1, visibility=VISIBLE, width=588, height=144, 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=144.0, child-count=1}
    |
    +--->RelativeLayout{id=-1, 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=48.0, y=39.0, child-count=2}
    |
    +---->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=アクション２, input-type=0, ime-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, ime-target=false, has-links=false}
    |
    
[/code]

この場合、どう書けばいいか分かる方いらっしゃいましたら、ご教授下さい。


CC BY-SA 3.0
2016-05-31T04:27:35.937
25324
2016-06-08T16:06:25.333
14921
question
android
EspressoでcheckableなMenuItemのテスト


自己解決しました。

Qiitaに解決方法を投稿しましたので、もし良ければ参考にしてください。  
<http://qiita.com/kasa_le/items/b517146b532a17f40365>

結局いろいろ試行錯誤して、質問にも載せたViewの階層状態を参考にして、次のようにMatcherを作りました。

Checkboxクラスのオブジェクトを全部受け取って、その親Viewが持つ子Viewの中からTextViewを探し、指定したタイトル文字列を持っているかチェックしています。

OSのバージョンが違ったらもしかしたらアウトかも知れませんが、support-
libraryを使っている間は大丈夫な気がします・・・が、何も保証は出来ません。

[code]

    public static MenuItemTitleMatcher withCheckBoxTitle(final String title) {
        return new MenuItemTitleMatcher(title);
    }
    
    public static class MenuItemTitleMatcher extends BaseMatcher<Object> {
        private final String title;
    
        public MenuItemTitleMatcher(String title) {
            this.title = title;
        }
    
        TextView getChildTextView(ViewGroup view, String title) {
            int num = view.getChildCount();
            for (int i = 0; i < num; i++) {
                View child = view.getChildAt(i);
                if (child instanceof TextView) {
                    if (title.equals(((TextView) child).getText())) {
                        return (TextView) child;
                    }
                }
            }
            return null;
        }
    
        @Override
        public boolean matches(Object o) {
            if (o instanceof CheckBox) {
                CheckBox checkbox = (CheckBox) o;
                ViewParent parent = checkbox.getParent();
                if (parent instanceof ListMenuItemView) {
                    // 子のViewGroupからTextViewを探す
                    int num = ((ListMenuItemView) parent).getChildCount();
                    for (int i = 0; i < num; i++) {
                        View child = ((ListMenuItemView) parent).getChildAt(i);
                        if (child == o) continue;
                        if (child instanceof ViewGroup) {
                            TextView textView = getChildTextView((ViewGroup) child, title);
                            if (textView != null)
                                return true;
                        }
                    }
                }
                return false;
            }
            return false;
        }
    
        @Override
        public void describeTo(Description description) {
            description.appendText("expected with Title: ");
            description.appendText("" + title);
        }
    }
    
[/code]

使用方法

[code]

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


CC BY-SA 3.0
2016-06-08T06:27:18.807
26557
2016-06-08T16:06:25.333
2016-06-08T16:06:25.333
3068
14921
25324
answer