Android为自动化测试提供了如下的API供我们使用:
AndroidJUnitRunner: 一个可以用来运行JUnit 3和JUnit 4样式的测试类的Test Runner;
Espresso: 提供了UI测试的API;
UI Automator: 提供了跨APP UI测试的API
AndroidJUnitRunner
AndroidJUnitRunner
是一个可以用来运行JUnit 3
和JUnit 4
样式的测试类的Test Runner,并且同时支持Espresso
和UI Automator
。这是对于之前的InstrumentationTestRunner
的一个升级,如果你去查看Gradle文档中对于Testing配置的说明,会发现推荐的Test Runner为InstrumentationTestRunner
。InstrumentationTestRunner
只支持JUnit 3
样式的测试用例,而我们在写Android测试用例时应该尽可能使用JUnit 4
样式来实现。
相对于Junit 3
, JUnit 4
有如下改进:
-
测试类不需要再继承
junit.framework.TestCase
类; -
测试方法名不再需要以
test
开头; -
可以使用类似
@Test
,@Before
,@After
等注解来管理自己的测试方法; -
增加了一些
Assert
方法; -
支持对
assert
方法的static
导入。
Espresso
谷歌13年的时候开源了espress,根据谷歌官方介绍,Espresso最关键的优势就是它能够检测到主线程空闲状态的时候,在适当的时候运行测试代码,这样就没必要通过Thread.sleep()去让主线程睡眠的方式去同步测试。说白了,就是Espresso框架在测试app时,不会通过阻塞主线程去同步UI测试。Espresso更多的用于开发人员的白盒测试。
Espresso测试是非常容易实现的,它由三部分组成:
UI测试三部曲
image.pngEspresso有三个重要的类
ViewMachers:寻找用来测试的View(匹配器)。
ViewActions:发送交互事件(界面行为)。
ViewAssertions:检验测试结果(界面判断)。
其中ViewMachers是常常是通过匹配条件来需找UI组件或过滤UI,而ViewAction是来模拟用户操作界面的行为,ViewAssertions对模拟行为操作的View进行变换和结果验证,其三者关系如图所示:
pdf 格式的离线版本在此:espersso-cheat-sheet-2.1.0.pdf
Android Studio中搭建步骤:
首先我们在Android Studio中新建一个项目,取名为EspressoTests,最终目录结构如下:
image.png在根目录的 build.gradle 文件中添加下面的引入:
添加testInstrumentationRunner:
为我们的工程指定一个TestInstrumentationRunner,TestInstrumentationRunner是用来跑我们所写的所有的测试用例的。当我们采用test的模式来构建工程时,这个Runner便会自动为我们执行所有的的测试用例,并且返回相应的测试结果。
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
添加编译依赖:
dependencies {
androidTestCompile 'com.android.support:support-annotations:23.1.1'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
}
我们在androidTest中创建测试
找元素
我们现在需要找页面中对应的元素了!Espresso
提供了一个onView()
方法用来寻找UI上指定的元素,该方法定义如下:
public static ViewInteraction onView(final Matcher<View> viewMatcher) {}
这个方法接收一个Matcher<View>
类型的入参,返回一个ViewInteraction
对象,其所做的事情就是根据Matcher<View>
所指定的条件,在当前UI页面上寻找符合条件的View
,并且把相应的View
返回出来。这样说还是比较抽象,我们可以用一个具体的例子加以说明。
当我们在实现布局的时候,每个控件都会有一些特殊的属性来确定其唯一性,比如最常用的R.id
。Matcher<View>
支持通过控件的唯一ID来从当前页面上寻找目标控件,对应的方法为withId()
,该方法定义如下:
public static Matcher<View> withId(final int id) {}
大家可以看到,该方法接收了一个int
类型的入参,返回了一个Matcher<View>
对象,于是,采用如下写法:
onView(withId(id));
我们就能在当前页面找到指定ID所对应的目标控件了。
再描述一遍这个流程以便更清晰:我现在要找一个R.id
为指定id
的控件,那么我就从我的这个id
出发,先生成一个查找匹配条件:withId(id)
。然后把这个条件传给onView()
方法:onView(withId(id))
,让onView()
方法根据这个条件找到我们想要的那个控件!实际上这行代码也是很符合我们的正常思维,可以读作:
Find a view with Id of the specific id.
实际上,Espresso
提供了很多方法来让我们自定义我们的查找条件。比如我们可以通过withText()
方法来寻找显示了指定文案的控件等等。具体支持的Matcher
类型可以参考Espresso cheat sheet。
需要提醒大家一点的是,onView()
方法在根据匹配条件进行查找时,它的目标是找到唯一的一个目标控件。如果我们制定的匹配条件有多个控件可以匹配(比如复用了layout
的布局,或者显示相同文字的TextView
等),该方法会抛出一个AmbiguousViewMatcherException
异常,因此我们在构造匹配条件时,一定要确保能查找到的目标控件是唯一的。如果单一的匹配条件无法精确地匹配出来唯一的控件,我们可能还需要额外的匹配条件,此时可以用allOf()
方法来进行复合匹配条件的构造:
onView(allOf(withId(id), withText(text)))
以上代码可以查找ID
为id
同时显示的文字内容为text
的控件。这里需要注意的是,为了保证自动化测试的效率,我们应尽可能减少匹配条件的数量。如果用一个匹配条件能够满足我们的需求,我们也就没有必要再用allOf()
来构造复合匹配条件了。
操作元素
找到了目标元素,接下来我们该针对该元素做一些操作了!
Espresso
提供了如下方法来对相应的元素做操作:
public ViewInteraction perform(final ViewAction... viewActions) {}
该方法定义在ViewInteraction
类里面。还记得onView()
方法的返回值么?yes,正是一个ViewInteraction
对象。因此,我们可以在onView()
方法找到的元素上直接调用perform()
方法进行一系列操作:
onView(withId(id)).perform(click())
如上代码对onView()
查询到的元素做了一次点击的操作。请注意,perform()
方法的入参是变长参数,也就意味着,我们可以依次对某个元素做多个操作:
onView(withId(id)).perform(click(), replaceText(text), closeSoftKeyboard())
以上代码对目标元素依次做了点击、输入文本、关闭输入法键盘的操作。这是一个典型的填写表单的行为。
检查结果
到目前为止,我们已经能找到元素,也能够对元素进行一些操作了!接下来我们需要检查一下这些操作的结果是否符合我们的预期。
Espresso
提供了一个check()
方法用来检测结果:
public ViewInteraction check(final ViewAssertion viewAssert) {}
该方法接收了一个ViewAssertion
的入参,该入参的作用就是检查结果是否符合我们的预期。一般来说,我们可以调用如下的方法来自定义一个ViewAssertion
:
public static ViewAssertion matches(final Matcher<? super View> viewMatcher) {}
这个方法接收了一个匹配规则,然后根据这个规则为我们生成了一个ViewAssertion
对象!还记得Matcher
这个类型么!!是的,这就是onView()
方法的入参!实际上他们是同一个类型,其使用方法也是完全一致的。
比如,我想检查一下指定id
的TextView
是否按照我的预期显示了一段text
文本,那么我就可以这样写:
onView(withId(id)).check(matches(withText(text)))
简洁明了。ViewAssertion
的支持也可以参照这个Espresso cheat sheet。
UI Automator
UI Automator是谷歌推出的,用于UI自动化测试的工具,也就是普通的手工测试,点击每个控件元素看看输出的结果是否符合预期。比如登陆界面分别输入正确和错误的用户名密码然后点击登陆按钮看看是否能否登陆以及是否有错误提示等。
注意:UI Automator测试框架是基于instrumentation的API,运行在Android JunitRunner 之上,同时UI Automator Test只运行在Android 4.3(API level 18)以上版本
UI元素查找---uiautomatorviewer工具
uiautomatorviewer工具位于Android SDK/tools/bin
HierarchyViewer默认只能在非加密设备使用,例如工程机,工程平板或者模拟器。如果要在手机上使用HierarchyViewer,你需要在你的应用中添加一个开源库View Server
链接地址:https://github.com/romainguy/ViewServer
该问题的详细原因:为什么HierachyViewer无法连接真机调试
image.png待续吧,我对python熟悉些,这个使用java写的测试用例,没有实际用过,等用过了,有经验了,在来写。。。
网友评论