espresso 目前尚不能处理多个View , 不论是 onData 还是其他 , 都只能操作唯一匹配的View . 如果多个view被匹配 , 将抛出 AmbiguousViewMatcherException 这个异常 , 那么我们想循环遍历操作一组同类的views时 将变得不太现实 .
举个例子有一波 Text 相同的View , 我想全部点击一遍 , 一个个的通过复杂定位去点击 , 显然不太现实 .
那么是自己动手实现的时候了 , 此文在此抛砖引玉了 , 若有更好的方法 , 烦请告知哈 . 之前翻看源码后 , 用反射将 ViewInteraction 对象的属性全拿出来重组 , 再通过 ViewHandle 来 getTargetViews() , 然而这种效率是很低的 .
Talk is cheep :
public class ViewsFinder {
private List<View> views = new ArrayList<>();
private boolean has_more_views;
private final String TAG = this.getClass().getSimpleName();
private Matcher<View> thisMatcher(Matcher<View> matcher){
return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("this is a view finder .");
}
@Override
protected boolean matchesSafely(View view) {
if(matcher.matches(view)){
views.add(view);
return true;
}
return false;
}
};
}
private void hasViews(Matcher<View> matcher){
try {
//下面的nothing() , 是一个空的 ViewAction
onView(thisMatcher(matcher)).perform(nothing());
has_more_views = true;
} catch (AmbiguousViewMatcherException e) {
has_more_views = true;
} catch (Exception ne){
Log.e(TAG, "hasViews: ", ne);
has_more_views = false;
}
}
public List<View> getViews(Matcher<View> matcher) {
this.hasViews(matcher);
if(has_more_views)
return views;
else {
Log.w(TAG, "getViews: 没有匹配的view" );
return null;
}
}
}
初步使用 :
ViewsFinder viewsFinder = new ViewsFinder();
List<View> recycler = viewsFinder.getViews(withResourceName("recycler"));
在调用 getViews 方法时将会执行 nothing() 这个空的 ViewAction , 这样不会对元素进行具体的操作 , Matcher 总是在 perform 执行的时候才去取 View , 并一个个的进行匹配 . 这时 , 匹配到一个就views.add(view) 这样放进list中去了 .
Views 列表是有了 , 那么接下来的操作 就可以for 循环了 . 啥 ? 光个view 怎么用 ? 自定义个Matcher 就搞定了嘛 .
Espresso在处理多个匹配的View时会抛出Ambiguous异常,使得遍历操作变得困难。本文探讨如何在Android测试中,针对相同View类型进行循环操作,包括使用空的ViewAction收集匹配的View,并通过自定义ViewAction实现逐个点击。
612

被折叠的 条评论
为什么被折叠?



