我一直在使用 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 和 hasSiblings with Espresso不幸的是我没有取得任何成功!
我知道这不太好,但由于我不在工作计算机上,我无法告诉你我遇到的确切错误,但我遇到过:
com.google.android.apps.common.testing.ui.espresso.AmbiguousViewMatcherException
还有一个错误告诉我没有找到匹配项。
我使用的代码是有道理的,尽管我是使用 Espresso 的新手,任何人都可以提供一些建议,或者指出我可能误解的内容吗?
在同一布局中多次尝试使用相同的自定义 xml 时,这是一个常见的陷阱。
如果您现在尝试致电
<include/>
由于boxes.xml
被包含多次,因此您将始终得到第一个子布局中存在的按钮,而不会出现另一个子布局。 你已经非常接近了,但是你需要使用
withParent() 视图匹配器。
Button button1 = (Button) findViewById(R.id.button1);
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());