Espresso select 包含布局的子项

Espresso select children of included layout

我一直在使用 Espresso 通过 Android 应用程序执行自动化 UI 测试。 (我下班在家时一直试图找到解决问题的方法,所以我没有确切的示例和错误,但我可以在明天早上更新)。我 运行 遇到一个布局中的单元测试按钮问题,该布局多次包含在单个用户界面中。下面是一个简单的例子:

<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" />

这是@layout/boxes:

中的一个例子
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/button1" />
    <Button
        android:id="@+id/button2" />
</RelativeLayout>

我似乎无法访问包含我想要的“include_one”中的第一个按钮,而不访问所有三个按钮。

我尝试使用以下方法访问按钮:

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

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

这两个都是我从这个答案中找到的:onChildView and hasSiblings with Espresso不幸的是我没有成功!

我知道这不太好,但由于我没有使用工作计算机,所以我无法告诉您我遇到的确切错误,但我遇到过:

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

还有一个错误告诉我没有找到匹配项。

我使用的代码很有意义,尽管我是使用 Espresso 的新手 任何人都可以提供一些建议,或者指出我可能误解的地方吗?

这是尝试在同一布局中多次 <include/> 同一自定义 xml 时的常见陷阱。

如果您现在尝试拨打

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

因为 boxes.xml 被包含不止一次,结果你总是会得到第一个子布局中的按钮,而不是另一个。

你非常接近,但你需要使用 withParent() 视图匹配器。

onView(allOf(withId(R.id.button1), withParent(withId(R.id.include_one))))
                .check(matches(isDisplayed()))
                .perform(click());

我遇到了类似的问题,应用了已接受的答案但没有用。因此,我看到了对父层次结构的预期级别的调查

   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);
        }
   }

然后创建一个辅助方法

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

用法如下

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