Espresso 测试框架 - 视图匹配器



Espresso 框架提供了许多视图匹配器。匹配器的目的是使用视图的不同属性(例如 Id、文本和子视图的可用性)来匹配视图。每个匹配器都匹配视图的特定属性并应用于特定类型的视图。例如,withId 匹配器匹配视图的 Id 属性并应用于所有视图,而 withText 匹配器匹配视图的 Text 属性,仅应用于 TextView

在本章中,让我们学习 Espresso 测试框架提供的不同匹配器,以及学习 Espresso 匹配器构建的基础库 Hamcrest

Hamcrest 库

Hamcrest 库在 Espresso 测试框架的范围内是一个重要的库。Hamcrest 本身是一个用于编写匹配器对象的框架。Espresso 框架广泛使用 Hamcrest 库,并在必要时对其进行扩展以提供简单且可扩展的匹配器。

Hamcrest 提供了一个简单的函数 assertThat 和一系列匹配器来断言任何对象。assertThat 有三个参数,如下所示:

  • 字符串(测试描述,可选)

  • 对象(实际值)

  • 匹配器(预期值)

让我们编写一个简单的示例来测试列表对象是否具有预期值。

import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;
@Test
public void list_hasValue() {
   ArrayList<String> list = new ArrayList<String>();
   list.add("John");
   assertThat("Is list has John?", list, hasItem("John"));
}

这里,hasItem 返回一个匹配器,它检查实际列表是否具有指定值作为其中一项。

Hamcrest 具有许多内置匹配器,以及创建新匹配器的选项。在 Espresso 测试框架中,一些有用的重要内置匹配器如下:

anything - 总是匹配

基于逻辑的匹配器

  • allOf - 接受任意数量的匹配器,只有当所有匹配器都成功时才匹配。

  • anyOf - 接受任意数量的匹配器,如果任何一个匹配器成功则匹配。

  • not - 接受一个匹配器,只有当匹配器失败时才匹配,反之亦然。

基于文本的匹配器

  • equalToIgnoringCase - 用于测试实际输入是否等于预期字符串(忽略大小写)。

  • equalToIgnoringWhiteSpace - 用于测试实际输入是否等于指定的字符串(忽略大小写和空格)。

  • containsString - 用于测试实际输入是否包含指定的字符串。

  • endsWith - 用于测试实际输入是否以指定的字符串结尾。

  • startsWith - 用于测试实际输入是否以指定的字符串开头。

基于数字的匹配器

  • closeTo - 用于测试实际输入是否接近预期数字。

  • greaterThan - 用于测试实际输入是否大于预期数字。

  • greaterThanOrEqualTo - 用于测试实际输入是否大于或等于预期数字。

  • lessThan - 用于测试实际输入是否小于预期数字。

  • lessThanOrEqualTo - 用于测试实际输入是否小于或等于预期数字。

基于对象的匹配器

  • equalTo - 用于测试实际输入是否等于预期对象。

  • hasToString - 用于测试实际输入是否具有 toString 方法。

  • instanceOf - 用于测试实际输入是否是预期类的实例。

  • isCompatibleType - 用于测试实际输入是否与预期类型兼容。

  • notNullValue - 用于测试实际输入是否不为空。

  • sameInstance - 用于测试实际输入和预期值是否为同一实例。

  • hasProperty - 用于测试实际输入是否具有预期的属性。

is - equalTo 的简写或语法糖

匹配器

Espresso 提供了 onView() 方法来匹配和查找视图。它接受视图匹配器并返回 ViewInteraction 对象以与匹配的视图交互。常用视图匹配器列表如下:

withId()

withId() 接受一个 int 类型的参数,该参数引用视图的 id。它返回一个匹配器,该匹配器使用视图的 id 来匹配视图。示例代码如下:

onView(withId(R.id.testView))

withText()

withText() 接受一个 string 类型的参数,该参数引用视图的文本属性的值。它返回一个匹配器,该匹配器使用视图的文本值来匹配视图。它仅适用于 TextView。示例代码如下:

onView(withText("Hello World!"))

withContentDescription()

withContentDescription() 接受一个 string 类型的参数,该参数引用视图的内容描述属性的值。它返回一个匹配器,该匹配器使用视图的描述来匹配视图。示例代码如下:

onView(withContentDescription("blah"))

我们还可以传递文本值的资源 ID 而不是文本本身。

onView(withContentDescription(R.id.res_id_blah))

hasContentDescription()

hasContentDescription() 没有参数。它返回一个匹配器,该匹配器匹配具有任何内容描述的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), hasContentDescription()))

withTagKey()

withTagKey() 接受一个 string 类型的参数,该参数引用视图的标签键。它返回一个匹配器,该匹配器使用其标签键来匹配视图。示例代码如下:

onView(withTagKey("blah"))

我们还可以传递标签名称的资源 ID 而不是标签名称本身。

onView(withTagKey(R.id.res_id_blah))

withTagValue()

withTagValue() 接受一个 Matcher 类型的参数,该参数引用视图的标签值。它返回一个匹配器,该匹配器使用其标签值来匹配视图。示例代码如下:

onView(withTagValue(is((Object) "blah")))

这里,is 是 Hamcrest 匹配器。

withClassName()

withClassName() 接受一个 Matcher 类型的参数,该参数引用视图的类名值。它返回一个匹配器,该匹配器使用其类名来匹配视图。示例代码如下:

onView(withClassName(endsWith("EditText")))

这里,endsWith 是 Hamcrest 匹配器并返回 Matcher

withHint()

withHint() 接受一个 Matcher 类型的参数,该参数引用视图的提示值。它返回一个匹配器,该匹配器使用视图的提示来匹配视图。示例代码如下:

onView(withClassName(endsWith("Enter name")))

withInputType()

withInputType() 接受一个 int 类型的参数,该参数引用视图的输入类型。它返回一个匹配器,该匹配器使用其输入类型来匹配视图。示例代码如下:

onView(withInputType(TYPE_CLASS_DATETIME))

这里,TYPE_CLASS_DATETIME 指的是支持日期和时间的编辑视图。

withResourceName()

withResourceName() 接受一个 Matcher 类型的参数,该参数引用视图的类名值。它返回一个匹配器,该匹配器使用视图的资源名称来匹配视图。示例代码如下:

onView(withResourceName(endsWith("res_name")))

它也接受字符串参数。示例代码如下:

onView(withResourceName("my_res_name"))

withAlpha()

withAlpha() 接受一个 float 类型的参数,该参数引用视图的 alpha 值。它返回一个匹配器,该匹配器使用视图的 alpha 值来匹配视图。示例代码如下:

onView(withAlpha(0.8))

withEffectiveVisibility()

withEffectiveVisibility() 接受一个 ViewMatchers.Visibility 类型的参数,该参数引用视图的有效可见性。它返回一个匹配器,该匹配器使用视图的可见性来匹配视图。示例代码如下:

onView(withEffectiveVisibility(withEffectiveVisibility.INVISIBLE))

withSpinnerText()

withSpinnerText() 接受一个 Matcher 类型的参数,该参数引用 Spinner 当前选定视图的值。它返回一个匹配器,该匹配器根据其选定项目的 toString 值来匹配 Spinner。示例代码如下:

onView(withSpinnerText(endsWith("USA")))

它也接受字符串参数或字符串的资源 ID。示例代码如下:

onView(withResourceName("USA"))
onView(withResourceName(R.string.res_usa))

withSubstring()

withSubString()withText() 类似,不同之处在于它有助于测试视图文本值的子字符串。

onView(withSubString("Hello"))

hasLinks()

hasLinks() 没有参数,它返回一个匹配器,该匹配器匹配具有链接的视图。它仅适用于 TextView。示例代码如下:

onView(allOf(withSubString("Hello"), hasLinks()))

这里,allOf 是一个 Hamcrest 匹配器。allOf 返回一个匹配器,该匹配器匹配所有传入的匹配器,在这里,它用于匹配视图以及检查视图的文本值中是否包含链接。

hasTextColor()

hasTextColor() 接受一个 int 类型的参数,该参数引用颜色的资源 ID。它返回一个匹配器,该匹配器根据其颜色匹配 TextView。它仅适用于 TextView。示例代码如下:

onView(allOf(withSubString("Hello"), hasTextColor(R.color.Red)))

hasEllipsizedText()

hasEllipsizedText() 没有参数。它返回一个匹配器,该匹配器匹配具有长文本且已省略号显示(开头…中间…结尾)或被截断(开头…)的 TextView。示例代码如下:

onView(allOf(withId(R.id.my_text_view_id), hasEllipsizedText()))

hasMultilineText()

hasMultilineText() 没有参数。它返回一个匹配器,该匹配器匹配具有任何多行文本的 TextView。示例代码如下:

onView(allOf(withId(R.id.my_test_view_id), hasMultilineText()))

hasBackground()

hasBackground() 接受一个 int 类型的参数,该参数引用背景资源的资源 ID。它返回一个匹配器,该匹配器根据其背景资源匹配视图。示例代码如下:

onView(allOf(withId("image"), hasBackground(R.drawable.your_drawable)))

hasErrorText()

hasErrorText() 接受一个 Matcher 类型的参数,该参数引用视图(EditText)的错误字符串值。它返回一个匹配器,该匹配器使用视图的错误字符串来匹配视图。这仅适用于 EditText。示例代码如下:

onView(allOf(withId(R.id.editText_name), hasErrorText(is("name is required"))))

它也接受字符串参数。示例代码如下:

onView(allOf(withId(R.id.editText_name), hasErrorText("name is required")))

hasImeAction()

hasImeAction() 接受一个 Matcher 类型的参数,该参数引用视图(EditText)支持的输入方法。它返回一个匹配器,该匹配器使用视图支持的输入方法来匹配视图。这仅适用于 EditText。示例代码如下:

onView(allOf(withId(R.id.editText_name),
hasImeAction(is(EditorInfo.IME_ACTION_GO))))

这里,EditorInfo.IME_ACTION_GO 是输入方法选项之一。hasImeAction() 也接受整数参数。示例代码如下:

onView(allOf(withId(R.id.editText_name),
hasImeAction(EditorInfo.IME_ACTION_GO)))

supportsInputMethods()

supportsInputMethods() 没有参数。如果视图支持输入方法,它将返回一个匹配该视图的匹配器。示例代码如下:

onView(allOf(withId(R.id.editText_name), supportsInputMethods()))

isRoot()

isRoot() 没有参数。它返回一个匹配根视图的匹配器。示例代码如下:

onView(allOf(withId(R.id.my_root_id), isRoot()))

isDisplayed()

isDisplayed() 没有参数。它返回一个匹配当前显示的视图的匹配器。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isDisplayed()))

isDisplayingAtLeast()

isDisplayingAtLeast() 接受一个 int 类型的参数。它返回一个匹配器,该匹配器匹配当前至少显示指定百分比的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isDisplayingAtLeast(75)))

isCompletelyDisplayed()

isCompletelyDisplayed() 没有参数。它返回一个匹配器,该匹配器匹配当前完全显示在屏幕上的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isCompletelyDisplayed()))

isEnabled()

isEnabled() 没有参数。它返回一个匹配已启用视图的匹配器。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isEnabled()))

isFocusable()

isFocusable() 没有参数。它返回一个匹配具有焦点选项的视图的匹配器。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isFocusable()))

hasFocus()

hasFocus() 没有参数。它返回一个匹配器,匹配当前获得焦点的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), hasFocus()))

isClickable()

isClickable() 没有参数。它返回一个匹配器,匹配具有点击选项的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isClickable()))

isSelected()

isSelected() 没有参数。它返回一个匹配器,匹配当前选中的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isSelected()))

isChecked()

isChecked() 没有参数。它返回一个匹配器,匹配类型为CompoundButton(或其子类型)且处于选中状态的视图。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isChecked()))

isNotChecked()

isNotChecked() 与isChecked正好相反。示例代码如下:

onView(allOf(withId(R.id.my_view_id), isNotChecked()))

isJavascriptEnabled()

isJavascriptEnabled() 没有参数。它返回一个匹配器,匹配正在执行JavaScript的WebView。示例代码如下:

onView(allOf(withId(R.id.my_webview_id), isJavascriptEnabled()))

withParent()

withParent() 接受一个类型为Matcher<View>的参数。该参数指的是一个视图。它返回一个匹配器,匹配指定视图作为父视图的视图。示例代码如下:

onView(allOf(withId(R.id.childView), withParent(withId(R.id.parentView))))

hasSibling()

hasSibling() 接受一个类型为Matcher<View>的参数。该参数指的是一个视图。它返回一个匹配器,匹配传入视图是其兄弟视图之一的视图。示例代码如下:

onView(hasSibling(withId(R.id.siblingView)))

withChild()

withChild() 接受一个类型为Matcher<View>的参数。该参数指的是一个视图。它返回一个匹配器,匹配传入视图是子视图的视图。示例代码如下:

onView(allOf(withId(R.id.parentView), withChild(withId(R.id.childView))))

hasChildCount()

hasChildCount() 接受一个类型为int的参数。该参数指的是视图的子视图数量。它返回一个匹配器,匹配子视图数量与参数中指定的数量完全相同的视图。示例代码如下:

onView(hasChildCount(4))

hasMinimumChildCount()

hasMinimumChildCount() 接受一个类型为int的参数。该参数指的是视图的子视图数量。它返回一个匹配器,匹配子视图数量至少与参数中指定的数量相同的视图。示例代码如下:

onView(hasMinimumChildCount(4))

hasDescendant()

hasDescendant() 接受一个类型为Matcher<View>的参数。该参数指的是一个视图。它返回一个匹配器,匹配传入视图是视图层次结构中某个后代视图的视图。示例代码如下:

onView(hasDescendant(withId(R.id.descendantView)))

isDescendantOfA()

isDescendantOfA() 接受一个类型为Matcher<View>的参数。该参数指的是一个视图。它返回一个匹配器,匹配传入视图是视图层次结构中某个祖先视图的视图。示例代码如下:

onView(allOf(withId(R.id.myView), isDescendantOfA(withId(R.id.parentView))))
广告
© . All rights reserved.