很多时候espresso不能自由的滑动 , 它必须在指定的View上进行 ( 当然 , view不可见的时候是不能滑动的 ) . 然而我们就是希望在屏幕上滑动一下来使某个view可见 , 一般情况很简单嘛 :
onView(isRoot()).perform(swipeLeft());
onView(isRoot()).perform(swipeDown());
这样真的就解决了吗 , 当然 . 这样可以解决大部分的问题 , 但如果说是在浮动出来的View上滑动呢 ? 比如 :
这时是无法在RootWindow上操作的了.
算了, 我们自己来吧 . 自由 ! 自由 !
自定义一个可以通过坐标点来滑动的 ViewAction:
public static final class SwipeAs implements ViewAction{
/** Maximum number of times to attempt sending a swipe action. */
private static final int MAX_TRIES = 3;
private final Swiper swiper;
private final float[] startCoordinates; //开始坐标
private final float[] endCoordinates; //结束坐标
private final float[] precision ; //这个是精度
public SwipeAs(Swiper swiper, float[] startCoordinates, float[] endCoordinates, float[] precision) {
this.swiper = swiper;
this.startCoordinates = startCoordinates;
this.endCoordinates = endCoordinates;
this.precision = precision;
}
@Override
public Matcher<View> getConstraints() {
return withAny(); //这个是啥? 当然是自定义的Matcher. 当心,它很关键 ,其意思是匹配所有 .(实现方式很简单,实现一个空的TypeSafeMatcher , 直接return true; 即可.) 如若不会, 请参见余前面的关于自定义Matcher的博客.
}
@Override
public String getDescription() {
return "swipe .";
}
@Override
public void perform(UiController uiController, View view) {
Swiper.Status status = Swiper.Status.FAILURE;
for (int tries = 0; tries < MAX_TRIES && status != Swiper.Status.SUCCESS; tries++) {
try {
Log.i(TAG, "SwipeAs perform .swipe as : "+ Arrays.toString(startCoordinates)
+ " -> "+ Arrays.toString(endCoordinates) +
" ; precision : "+ Arrays.toString(precision));
status = swiper.sendSwipe(uiController, startCoordinates, endCoordinates, precision);
} catch (RuntimeException re) {
throw new PerformException.Builder()
.withActionDescription(this.getDescription())
.withViewDescription(HumanReadables.describe(view))
.withCause(re)
.build();
}
int duration = ViewConfiguration.getPressedStateDuration();
// ensures that all work enqueued to process the swipe has been run.
if (duration > 0) {
uiController.loopMainThreadForAtLeast(duration);
}
}
if (status == Swiper.Status.FAILURE) {
throw new PerformException.Builder()
.withActionDescription(getDescription())
.withViewDescription(HumanReadables.describe(view))
.withCause(new RuntimeException(String.format(
"Couldn't swipe from: %s,%s to: %s,%s precision: %s, %s . Swiper: %s "
+ "start coordinate provider: %s . Tried %s times",
startCoordinates[0],
startCoordinates[1],
endCoordinates[0],
endCoordinates[1],
precision[0],
precision[1],
swiper,
Arrays.toString(startCoordinates),
MAX_TRIES)))
.build();
}
}
}
当然某些部分还是直接从Google API中摘出来的 , 如异常部分.
初步使用:
onView(isRoot()).perform(
new CustomViewAction.SwipeAs(Swipe.FAST ,new float[]{213.0f ,1578.356f}
,new float[]{213.0f ,1517.0f} , Press.FINGER.describePrecision())
);
试试看, 还不错吧 . 这乱糟糟的有什么用 , 不好看也不好写 . 嘿 , 这之后的封装工作当然就是课后作业了哈.
经过层层封装后 当然也可以这么优雅 :
onView(isRoot()).perform(swipeUpAs());
只不过这中间的封装一篇博文是说不完的 ( 也不过些基础知识 ).
本文探讨了在使用Espresso进行Android UI测试时遇到的滑动限制问题,尤其是在需要在浮动View上滑动的情景。通过创建一个自定义ViewAction,允许以坐标点为基准进行滑动操作,解决了在RootWindow上无法操作的问题。示例代码展示了如何使用这个自定义方法,以更优雅的方式实现自由滑动。
1万+

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



