自定义视图匹配器

Espresso 提供了各种选项来创建我们自己的自定义视图匹配器,它基于 Hamcrest 匹配器。自定义匹配器是一个非常强大的概念,可以扩展框架,也可以根据我们的喜好定制框架。编写自定义匹配器的一些优点如下:

  • 利用我们自己的自定义视图的独特功能

  • 自定义匹配器有助于在基于 AdapterView 的测试用例中匹配不同类型的底层数据。

  • 通过组合多个匹配器的功能来简化当前匹配器

我们可以在需求出现时创建新的匹配器,这非常容易。让我们创建一个新的自定义匹配器,它返回一个匹配器来测试 TextView 的 id 和文本。

Espresso 提供以下两个类来编写新的匹配器 −

  • TypeSafeMatcher

  • BoundedMatcher

这两个类本质上相似,只是 BoundedMatcher 透明地处理对象转换为正确类型,而无需手动检查正确类型。我们将使用 BoundedMatcher 类创建一个新的匹配器 withIdAndText。让我们查看编写新匹配器的步骤。

  • app/build.gradle 文件中添加以下依赖项并同步它。

dependencies {
   implementation 'androidx.test.espresso:espresso-core:3.1.1'
}
  • 创建一个新类以包含我们的匹配器(方法)并将其标记为final

public final class MyMatchers {
}
  • 在新类中声明一个静态方法,并附带必要的参数,并将 Matcher<View> 设置为返回类型。

public final class MyMatchers {
   @NonNull
   public static Matcher<View> withIdAndText(final Matcher<Integer>
   integerMatcher, final Matcher<String> stringMatcher) {
   }
}
  • 在静态方法中使用以下签名创建一个新的 BoundedMatcher 对象(同样返回值),

public final class MyMatchers {
   @NonNull
   public static Matcher<View> withIdAndText(final Matcher<Integer>
   integerMatcher, final Matcher<String> stringMatcher) {
      return new BoundedMatcher<View, TextView>(TextView.class) {
      };
   }
}
  • BoundedMatcher 对象中重写 describeTomatchesSafely 方法。describeTo 具有单个类型为 Description 的参数,没有返回类型,用于有关匹配器的错误信息。matchesSafely 具有单个类型为 TextView 的参数,返回类型为 boolean,用于匹配视图。

代码的最终版本如下,

public final class MyMatchers {
   @NonNull
   public static Matcher<View> withIdAndText(final Matcher<Integer>
   integerMatcher, final Matcher<String> stringMatcher) {
      return new BoundedMatcher<View, TextView>(TextView.class) {
         @Override
         public void describeTo(final Description description) {
            description.appendText("error text: ");
            stringMatcher.describeTo(description);
            integerMatcher.describeTo(description);
         }
         @Override
         public boolean matchesSafely(final TextView textView) {
            return stringMatcher.matches(textView.getText().toString()) &&
            integerMatcher.matches(textView.getId());
         }
      };
   }
}
  • 最后,我们可以使用我们的mew匹配器来编写如下所示的测试用例,

@Test
public void view_customMatcher_isCorrect() {
   onView(withIdAndText(is((Integer) R.id.textView_hello), is((String) "Hello World!")))
      .check(matches(withText("Hello World!")));
}