24

I have been using Espresso to carry out automated UI testing with an Android app. (I have been trying to find a resolution to the issue whilst at home from work, so I don’t have the exact examples and errors, but I can update tomorrow morning). I have run into an issue with unit testing buttons within a layout that is included multiple times within a single user interface. Below is a quick example:

<include 
   android:id="@+id/include_one"
   android:layout="@layout/boxes" />

<include 
   android:id="@+id/include_two"
   android:layout="@layout/boxes" />

<include 
    android:id="@+id/include_three"
    android:layout="@layout/boxes" />

Here is an example of what is within the @layout/boxes:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/button1" />
    <Button
        android:id="@+id/button2" />
</RelativeLayout>

I am seemingly unable to access button one within the include I want “include_one”, without accessing all three of the buttons.

I have tried accessing the buttons with the following:

onView(allOf(withId(R.id.include_one), isDescendantOfA(withId(R.id.button1)))).perform(click());

and

onView(allOf(withId(R.id.button1), hasParent(withId(R.id.include_one)))).perform(click());

Both of which I found from this answer: onChildView and hasSiblings with Espresso Unfortunately I haven’t had any success!

I know this isn’t great, but as I am not with my work computer I can’t tell you the exact errors I have come across, but I have encountered:

com.google.android.apps.common.testing.ui.espresso.AmbiguousViewMatcherException

also an error telling me there were no matches found.

The code I am using makes sense, although I am new to using Espresso Can anyone offer some advice, or point out what I may be misunderstanding?

Community
  • 1
  • 1
jordan_terry
  • 468
  • 1
  • 4
  • 12

2 Answers2

34

This is a common pitfall when trying to <include/> the same custom xml several times in the same layout.

If you now try calling

Button button1 = (Button) findViewById(R.id.button1);

since the boxes.xml is included more than once, you will always get as a result the button present in the first sub layout, and never another one.

You were pretty close but you need to use the withParent() view matcher.

onView(allOf(withId(R.id.button1), withParent(withId(R.id.include_one))))
                .check(matches(isDisplayed()))
                .perform(click());
appoll
  • 2,910
  • 28
  • 40
  • Thanks for the response! I really should have answered this myself when I fixed the issue. But you are right, I had a complex selector to select the right button when I was working on this problem. – jordan_terry Apr 17 '15 at 13:44
1

I had similar issue, applied accepted answer but didn't work. Hereby I come across look into expected level of parent hierarchy

   private static final class WithParentMatcher extends TypeSafeMatcher<View> {
        private final Matcher<View> parentMatcher;

        private int hierarchyLevel;

        private WithParentMatcher(Matcher<View> parentMatcher, int hierarchyLevel) {
            this.parentMatcher = parentMatcher;
            this.hierarchyLevel = hierarchyLevel;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("has parent matching: ");
            parentMatcher.describeTo(description);
        }

        @Override
        public boolean matchesSafely(View view) {
            ViewParent viewParent = view.getParent();
            for (int index = 1; index < hierarchyLevel; index++) {
                viewParent = viewParent.getParent();
            }
            return parentMatcher.matches(viewParent);
        }
   }

Then create a helper method

public static Matcher<View> withParent(final Matcher<View> parentMatcher, int hierarchyLevel) {
    return new WithParentMatcher(parentMatcher, hierarchyLevel);
}

Here is the usage

onView(allOf(withId(R.id.button1), withParent(withId(R.id.include_one), 2))).perform(click());
Krishna Sharma
  • 2,828
  • 1
  • 12
  • 23