espresso 基础架构与 API 分析

阅读 537
收藏 25
2016-12-06
原文链接:qaseven.github.io

Espresso测试框架提供了一组API来构建UI测试,以测试应用程序内的用户流。 这些API让您能够编写简洁,运行可靠的自动化UI测试。 Espresso非常适合编写白盒式自动化测试,其中测试代码使用来自所测试的应用程序的实现代码细节。

Espresso测试框架的主要功能包括:

用于在目标应用程序中查看和适配器匹配的灵活API。 有关详细信息,请参阅View matching
一组广泛的操作API,用于自动化UI交互。 有关更多信息,请参阅 Action APIs
UI线程同步提高测试的可靠性。 有关更多信息,请参阅 UI thread synchronization
可以作为参数传入 ​ViewInteraction.check()​方法中的 ViewAssertion 的集合。通常,你会使用带有视图匹配器的匹配断言来判断当前被选中视图的状态,请参阅ViewAssertions
需要Android 2.2(API级别8)或更高版本。

View matching

onView()

Espresso.onView()方法允许您访问目标应用程序中的UI组件并与其进行交互。 该方法接受Matcher参数并搜索视图层次以定位满足某些给定标准的对应View实例。 您可以通过指定以下条件来优化搜索:

  • 视图的类名
  • 视图的内容描述
  • 视图的R.id
  • 视图中显示的文本
    例如,要定位ID值为my_button的按钮,您可以指定一个匹配器,如下所示:

onView(withId(R.id.my_button));
如果搜索成功,onView()方法返回一个引用,该引用允许您对目标视图执行用户操作和测试断言。

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

ViewMatchers

onView方法需要传入类型为Matcher泛型viewMatcher对象.

ViewMatchers类中方法有

isAssignableFrom,withClassName,isDisplayed,isCompletelyDisplayed,isDisplayingAtLeast,isEnabled,isFocusable,hasFocus,isSelected,hasSibling,withContentDescription,withContentDescription,withContentDescription,withId,withResourceName,withTagKey,withTagValue,withText,withCharSequence,withHint,isChecked,isNotChecked,withCheckBoxState,hasContentDescription,hasDescendant,isClickable,isDescendantOfA,withEffectiveVisibility,withParent,withChild,isRoot,supportsInputMethods,hasImeAction,hasImeAction,hasLinks,assertThat,withSpinnerText,isJavascriptEnabled,hasErrorText,withInputType。

这些方法能够帮助我们快速定位到特定的视图。 我们来看看常用的几个方法 withId 返回基于资源ids匹配视图的匹配器。 withText 返回基于TextView的文本属性值匹配TextView的匹配器。

onView(allOf(withId(R.id.my_view), withText("Hello!")))

isDisplayed 返回与当前显示在屏幕上的视图匹配的匹配器给用户。

如下

Espresso.onView(ViewMatchers.withId(R.id.mpu_summary_send_receipt_button)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));其他API方法可以在以下文档中找到具体用法和解释,我们并不需要记住每个方法,遇到具体的场景的时候再过来查询也来得及

viewmatchers-API

ViewMatchers与hamcrest匹配器配合使用

什么是hamcrest?

Hamcrest框架是junit4框架新引入的断言框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活。我们可以通过各种viewmatchers与Hamcrest组合匹配器来缩小搜索的范围。

如以下示例所示:

onView(allOf(withId(R.id.button_signin), withText("Sign-in")));

你也可以使用 ​not​ 反转匹配:

onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));
注意:
一个工程化的应用中,所有用户可与之交互的视图都应该包含说明文字或有一个内容描述(参考 Android 可访问性指导)。如果你不能通过使用 ‘withText’ 或 ‘withContentDescripiton’ 来缩小onView的搜索范围,可以认为这是一个可访问性的 bug。

请使用最少的匹配器来定位视图。不要过指定,因为这将强制框架做无用功。例如,如果一个视图可以通过它的文字唯一确定,你不需要说明该视图也可以通过 ​TextView​ 指定。对许多视图而言,使用它的​R.id​值就足够了。

更多的hamcrest api请查看
hamcrest api

###onData
当espresso在AdapterView中查找视图时需要用onData方法,例如在AdapterView小部件中,视图在运行时动态填充子视图。如果要测试的目标视图位于AdapterView(例如ListView,GridView或Spinner)中,则onView()方法可能无法工作,因为只有一部分视图可能会加载到当前视图层次结构中。

相反,调用onData()方法可获取DataInteraction对象以访问目标视图元素。 Espresso处理将目标视图元素加载到当前视图层次结构中。 Espresso还负责滚动到目标元素,并将放在焦点元素。

注意:onData()方法不检查您指定的项目是否与视图对应。 Espresso仅搜索当前视图层次结构。如果没有找到匹配,该方法将抛出NoMatchingViewException异常。

下面的代码片段展示了如何使用onData()方法和Hamcrest匹配来搜索包含给定字符串的列表中的特定行。在此示例中,LongListActivity类包含通过SimpleAdapter公开的字符串列表。

onData(allOf(is(instanceOf(Map.class)),
        hasEntry(equalTo(LongListActivity.ROW_TEXT), is("test input")));

Performing Actions

调用ViewInteraction.perform()或DataInteraction.perform()方法来模拟UI组件上的用户交互。您必须传入一个或多个ViewAction对象作为参数。Espresso按照给定的顺序依次触发每个动作,并在主线程中执行它们。
ViewActions类提供了指定常用操作的帮助方法列表。您可以使用这些方法作为方便的快捷方式,而不是创建和配置单个ViewAction对象。您可以指定以下操作:

  • ViewActions.click():点击视图。
  • ViewActions.typeText():点击视图并输入指定的字符串。
  • ViewActions.scrollTo():滚动到视图。目标视图必须是来自ScrollView的子类,它的android:visibility属性的值必须是VISIBLE。对于扩展AdapterView(例如,ListView)的视图,onData()方法为您处理滚动。
  • ViewActions.pressKey():使用指定的键码执行键按下。
  • ViewActions.clearText():清除目标视图中的文本。
    如果目标视图位于ScrollView内部,请先执行ViewActions.scrollTo()操作,以在其他操作进行之前在屏幕中显示视图。如果视图已显示,ViewActions.scrollTo()操作将不起作用。

例如,要模拟输入字符串值并按按钮提交值,您可以编写类似这样的自动测试脚本。 ViewInteraction.perform()和DataInteraction.perform()方法采用一个或多个ViewAction参数,并按提供的顺序运行操作。

//将文本键入EditText视图,然后关闭软键盘

onView(withId(R.id.editTextUserInput))
     .perform(typeText(STRING_TO_BE_TYPED),closeSoftKeyboard());

//按按钮提交文本更改
onView(withId(R.id.changeTextBt)).perform(click());

其他action api 请查看
developer.android.com/reference/a…

Verifying Results

调用ViewInteraction.check()或DataInteraction.check()方法来断言UI中的视图匹配一些预期状态。 您必须传递一个ViewAssertion对象作为参数。 如果断言失败,Espresso会抛出一个AssertionFailedError。ViewAssertions类提供了用于指定公共断言的帮助程序方法的列表。 您可以使用的断言包括:doesNotExist:断言没有与当前视图层次结构中指定的条件匹配的视图。matches:断言指定视图存在于当前视图层次结构中,并且其状态与某个给定的Hamcrest匹配器匹配。

selectedDescendentsMatch:存在指定的孩子为父视图查看的声明,它们的状态与某个给定的Hamcrest匹配器匹配。

以下代码段显示了如何检查UI中显示的文本的值与之前在EditText字段中输入的文本的值相同。

public void testChangeText_sameActivity() {
    // Type text and then press the button.
    ...
    onView(withText(R.string.item_1_text))
            .check(doesNotExist());
    // Check that the text was changed.
    onView(withId(R.id.textToBeChanged))
            .check(matches(withText(STRING_TO_BE_TYPED)));
}

ViewMatchers, ViewActions, ViewAssertions 组成了espresso的基础架构,所以要真正的掌握espresso必须将这3部分基础熟悉。
上一节espresso基础

评论