Espresso之onView()&onData()

本文深入解析Espresso的onView()和onData(),包括ViewInteraction和DataInteraction的使用,如perform()、check()、inRoot()等方法,以及在AdapterView中的操作。文章强调了每个操作的独立性,提醒开发者注意操作顺序的影响,同时提供了关于自定义FailureHandler和适配器视图协议的建议。
摘要由CSDN通过智能技术生成

总目录:Espresso从开始到…

如果你看了上一篇中对一些常用方法的介绍,想必现在已经可以对Espresso正常进行使用了,从这里开始我们开始看一些“简单”的东西。了解一下这三部曲是什么。

onView(ViewMatcher)
    .perform(ViewAction)
    .check(ViewAssertion);

从onView()&onData()开始

作为一个程序猿自然不能满足于三部曲,虽然不能什么都一清二楚,但是最差也要知道大概的流程吧。不然都不好意思说自己用过Espresso。所以与 Espresso 的故事就是从 Ctrl 打开 onView()开始了。
这里直接进入 Espresso 类, 这里主要有几个常用的静态工具函数

函数名 功能
pressBack() 返回键
closeSoftKeyboard() 关闭软键盘
openActionBarOverflowOrOptionsMenu() 菜单键
openContextualActionModeOverflowMenu(); 实体键盘菜单键

还有几个registerIdlingResourcesunregisterIdlingResources等关于IdlingResources的函数。以及本文的关键onView()onData(),在这里分别生成了ViewInteractionDataInteraction

 public static ViewInteraction onView(final Matcher<View> viewMatcher) {
    return BASE.plus(new ViewInteractionModule(viewMatcher)).viewInteraction();
  }

注:onView 在这里使用了 Dagger 框架 ,由于笔者没有使用过该框架,在这里就不多赘述,感兴趣的可以自行查阅。

   public static DataInteraction onData(Matcher<? extends Object> dataMatcher) {
    return new DataInteraction(dataMatcher);
  }

ViewInteraction

ViewInteraction中的公共函数非常少,只有四个:

函数名 功能
perform() 执行ViewAction操作
check() 检查ViewAssertion
inRoot() 确定目标view所在的root
withFailureHandler() 提供错误处理方式
1.perform()

我们还是按照三部曲的顺序进行先看perform()

public ViewInteraction perform(final ViewAction... viewActions) {
    checkNotNull(viewActions);
    for (ViewAction action : viewActions) {
        doPerform(action);
    }
    return this;
  }

从方法的形参ViewAction... viewActions我们可以知道perform()是支持同时执行多个操作的,但是会通过doPerform(action)按照顺序依次执行。
到这里问题就来了,如果按照三部曲的理解来说,现在应该开始对控件执行操作了,但是需要操作的控件在哪?我们至今没有看到,难道在onView()初始化的过程中已经将View检索出来存储为成员变量了?ok,我们来看一下 ViewInteraction 有哪些成员变量:

 //用于进行简单UI操作的工具
  private final UiController uiController;
  
 //用于查找View的工具
  private final ViewFinder viewFinder;
  
  //执行已提交 runnable 任务的对象
  private final Executor mainThreadExecutor;
  
  //错误处理机制与 withFailureHandler() 有关
  private volatile FailureHandler failureHandler;
  
  //view的匹配器(我们在onView(viewMatcher)传入的)
  private final Matcher<View> viewMatcher;
  
  //缺点查询 view 的 root 与 inRoot() 有关
  private final AtomicReference<Matcher<Root>> rootMatcherRef;

好吧,现实并不是想象的那样,ViewInteraction 并没有存储 view ,里面只有用于查找 view 的工具(ViewFinder)和材料(Matcher<View>)。看来答案需要在接下来的doPerform(action)中寻找了。让我们看一下代码:

private void doPerform(final ViewAction viewAction) {
    checkNotNull(viewAction);
    final Matcher<? extends View> constraints = checkNotNull(viewAction.getConstraints());
    runSynchronouslyOnUiThread(new Runnable() {

      @Override
      public void run() {
        uiController.loopMainThreadUntilIdle();
        View targetView = viewFinder.getView();
        Log.i(TAG, String.format(
            "Performing '%s' action on view %s", viewAction.getDescription(), viewMatcher));
        if (!constraints.matches(targetView)) {
          // TODO(user): update this to describeMismatch once hamcrest is updated to new
          StringDescription stringDescription = new StringDescription(new StringBuilder(
              "Action will not be performed because the target view "
              + "does not match one or more of the following constraints:\n"));
          constraints.describeTo(stringDescription);
          stringDescription.appendText("\nTarget view: ")
              .appendValue(HumanReadables.describe(targetView));

          if (viewAction instanceof ScrollToAction
              && isDescendantOfA(isAssignableFrom((AdapterView.class))).matches(targetView)) {
            stringDescription.appendText(
                "\nFurther Info: ScrollToAction on a view inside an AdapterView will not work. "
                + "Use Espresso.onData to load the view.");
          }

          throw new PerformException.Builder()
            .withActionDescription(viewAction.getDescription())
            .withViewDescription(viewMatcher.toString())
            .withCause(new RuntimeException(stringDescription.toString()))
            .build();
        } else {
          viewAction.perform(uiController, targetView);
        }
      }
    });
  }

函数开始,先对viewAction的可看性进行检查,并获取viewAction操作对 view 限制条件 constraints (绝大多数操作只能在相对应的控件上进行操作),然后的操作在runSynchronouslyOnUiThrea

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值