没有捕抓不到的猎物,就看你有没有野心去捕抓;没有完成不了的事情,就看你有没有野心去做。 ————《狼道》
目录
一、前言
二、简介
(1)是什么
(2)有什么用
(3)怎么用
1.添加依赖
2.基本使用
3.基础知识
4.方法介绍
5.错误处理
6.自动生成测试用例
三、原理
(4)原理是什么
四、总结
(5)优点与缺点
五、内容推荐
六、项目参考
一、前言
很早之前写过一篇《JUnit单元测试》,比较简单常用的测试方法。写的只能算是入门知识也不算很细。后面又用过UI Automator与Espresso,不过都没好好总结。最近刚好需要重新回顾了一下,顺便也做下记录。UI Automator与Espresso都是Android自动化测试框架,各有优缺点,不过个人相比起来更喜欢后者。这里就给大家简单介绍下Espresso,整体大纲如下
二、简介
(1)是什么
Espresso是一个非常强大的Android UI测试框架。功能类似于ui Automator,但测试由熟悉被测代码库的人来编写最好。
(2)有什么用
使用Espresso可模拟用户操作、检测数据编写简洁、漂亮、可靠的Android UI测试。
(3)怎么用
1.添加依赖
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
//可选 提供ApplicationProvider.getApplicationContext()
androidTestImplementation 'androidx.test:core:1.2.0'
2.基本使用
//公式:
onView(withId(R.id.greet_button)).perform(ViewAction).check(ViewAssertion);
onData(ObjectMatcher).DataOptions.perform(ViewAction).check(ViewAssertion);
根据下面例子,给大家简单解释下这些方法的作用
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
//启动Activity 不懂Rule可查阅junit.@Rule类似于@Before
@Rule
public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
@Test
public void mainActivityTest() {
//2.withId()匹配控件(View)id,其它匹配方法可在ViewMatchers类中获得,如:withText()
Matcher<View> viewMatcher = withId(R.id.xxx);
//1.onView()、onData()是启动测试的入口 ,通过传入匹配器(Matcher)获取ViewInteraction实例来执行一些测试操作
ViewInteraction viewInteraction = onView(viewMatcher);
//3.通过ViewInteraction.perform() 执行操作。操作的方法在 ViewActions中,如:click()点击
viewInteraction.perform(click());
//5.通过通过ViewInteractions类获取到viewInteraction对象
ViewAssertion viewAssertion = doesNotExist();//表示不存
ViewAssertions.matches(withText("xxx"));//表示匹配"xxx"等文字内容
//4.通过ViewInteraction.check()执行检测ViewAssertion对象
viewInteraction.check(viewAssertion);
//简单写法: 表示根据ID找到指定控件后执行点击操作并匹配文本是不是“关闭”内容
onView(withId(R.id.btn_close)).perform(click()).check(matches(withText("关闭")));
//表示根据文本找到指定控件后执行点击操作并匹配是否可点击
onView(withText("关闭")).perform(click()).check(matches(isClickable()));
}
}
看了上面例子基本可以操作大部分的控件了,但是仍有个别的控件得需要特殊对待。如ListView
@Test
public void mainActivityTest() {
// ListView 来自https://academy.realm.io/posts/chiu-ki-chan-advanced-android-espresso-testing/
onData(withValue(27)).inAdapterView(withId(R.id.list)).perform(click());
}
//定义匹配器 不了解的可以看看这篇https://www.jianshu.com/p/662a07e5e828
public static Matcher<Object> withValue(final int value) {
return new BoundedMatcher<Object, MainActivity.Item>(MainActivity.Item.class) {
@Override public void describeTo(Description description) {
description.appendText("has value" + value);
}
@Override public boolean matchesSafely(MainActivity.Item item) {
return item.toString().equals(String.valueOf(value));
}
};
}
更多特别的使用这里就不举例了。写起来可能有点多
3.基础知识
①基本组成部分
- Espresso:与视图交互的入口点(通过onView()和onData())
- ViewMatchers:在当前View层级去匹配指定的View。您可以将其中一个或多个传递给onView()方法
- ViewActions:执行Views的某些行为,如点击事件
- ViewAssertions:检查Views的某些状态,如是否显示
②执行操作
- 点击事件:onView(...).perform(click());
- 执行多个操作:onView(...).perform(typeText("Hello"), click());
- 检查是否匹配文本:onView(...).check(matches(withText("Hello!")));
- 适配器相关操作:onData(allOf(is(instanceOf(String.class)), is("Americano"))).perform(click());
- onView(withId(R.id.spinnertext_simple)).check(matches(withText(containsString("Americano"))));
③获取控件
- 具有唯一ID:onView(withId(R.id.my_view));
- 具有多个相同ID根据属性:onView(allOf(withId(R.id.my_view), withText("Hello!")));
- 无法具体匹配情况下:onView(allOf(withId(R.id.my_view), not(withText("Unwanted"))));
注意事项:
- 如果无法使用withText()或withContentDescription()缩小搜索范围,可以考虑将其视为可访问性错误
- 使用最不具描述性的匹配器来查找要查找的视图。不要过度指定,因为这将迫使框架做更多不必要的工作
- 如果目标视图位于adapterview(如ListView、GridView或spinner)中,则onView()方法可能无法工作。在这些情况下,应该使用onData()
4.方法介绍
①常用方法:
public void fun(){
1.Espresso类
//测试入口
onData(Matcher<? extends Object> dataMatcher)、onView(Matcher<View> viewMatcher)
//关闭软键盘
closeSoftKeyboard();
//循环主线程,直到应用程序空闲 onIdle();
onIdle(Callable<T> action)
//打开在ActionBar中显示的溢出菜单
openActionBarOverflowOrOptionsMenu(this);
openContextualActionModeOverflowMenu();
//按下后退按钮。
pressBack();
//与pressBack()类似,但当Espresso导航到应用程序或测试中的进程之外时,不会抛出异常
pressBackUnconditionally();
//将默认的FailureHandler更改为给定的
setFailureHandler();
2.ViewMatchers类 与onData、onView配合定位view
//匹配文本
withText(Matcher<String> stringMatcher)
withText(String text)
withText(int resourceId)
//匹配背景
hasBackground(int drawableId)
//匹配子元素数目
hasChildCount(int childCount)
//匹配id
withId(Matcher<Integer> integerMatcher)
withId(int id)
//匹配类名字
withClassName(Matcher<String> classNameMatcher)
//匹配资源名
withResourceName(String name)
//匹配具有焦点、选中状态、可单击、显示状态
hasFocus()/isChecked()/isClickable()/isDisplayed()
3.ViewActions类 模拟用户操作 与Espresso.perform(ViewAction... viewActions)
//点击、双击、点击长按
click()、 doubleClick()、longClick()
//关闭软键盘、滚动视图
closeSoftKeyboard()、scrollTo()
//向下滑动、向左滑动、向右滑动、向上滑动
swipeDown()、swipeLeft()、swipeRight()、 swipeUp()
//输入文本
typeText(String stringToBeTyped)
4.ViewAssertions类 断言
//返回一个断言,该断言确保视图匹配器在层次结构中没有找到任何匹配的视图
doesNotExist()
//断言视图存在于视图层次结构中,并由给定的视图匹配器匹配
matches(Matcher<? super View> viewMatcher)
}
②方法介绍 ③多进程测试 ④无障碍功能检测 ⑤WebView测试 ⑥基础代码封装
5.错误处理
@Before
public void setUp() throws Exception {
//ApplicationProvider需要androidTestImplementation 'androidx.test:core:1.2.0'
setFailureHandler(new
CustomFailureHandler(ApplicationProvider.getApplicationContext()));
}
private static class CustomFailureHandler implements FailureHandler {
private final FailureHandler delegate;
public CustomFailureHandler(Context targetContext) {
delegate = new DefaultFailureHandler(targetContext);
}
@Override
public void handle(Throwable error, Matcher<View> viewMatcher) {
try {
delegate.handle(error, viewMatcher);
} catch (NoMatchingViewException e) {
// throw new MySpecialException(e);
System.out.println("打印异常:"+e.getMessage());
}
}
}
6.自动生成测试用例
注意:在您的测试设备上关闭动画
①组成部分 1.界面交互 2.View 元素断言
②生成步骤
1.记录界面交互
- 依次点击 Run > Record Espresso Test。
- 在 Run > Select Deployment Target 窗口中,选择要在哪个设备上记录测试。
- Record Your Test 窗口将在应用启动后显示
2.添加断言以验证界面元素
- text is:检查选定 View 元素的文本内容
- exists:检查 View 元素是否存在于屏幕上可见的当前 View 层次结构中
- does not exist:检查 View 元素是否不存在于当前 View 层次结构中
操作步骤:
- 点击 Add Assertion
- 当前屏幕的布局将显示在 Record Your Test 窗口右侧的面板中
- 从 Edit assertion 框的第二个下拉菜单中选择要使用的断言
- 点击 Save and Add Another 以再创建一个断言,或点击 Save Assertion 以关闭断言面板
3.保存记录
- 点击 Complete Recording。此时将显示 Pick a test class name for your test 窗口
- Espresso 测试记录器会根据已启动 Activity 的名称在软件包内为您的测试提供一个唯一的名称
- 文件将在 Espresso 测试记录器生成它后自动打开,Android Studio 将显示在 IDE 的 Project 窗口中选择的测试类
最后一点很好用,不想写代码的可以好好利用。但是不一定比自己写的快,只要把基础代码封装好。编写起来也很快。
三、原理
(4)原理是什么
因为是测试方面的框架,所以分析起来对我来说还是有点难度。所以这里就不献丑了,网上看到过一篇就推荐给大家,想更详细了解的可以看看https://www.jianshu.com/p/1fb248b77b36
四、总结
(5)优缺点
个人使用过程中与UI Automator做了些对比。
- API接口比较少,代码简洁,使用方便,运行速度快
- AS提供可自动生成编码测试的工具
- 适合由熟悉项目人来编写,自动生成除外
- 无需主动写Sleep等待UI事件的执行和UI的绘制
- 运行测试前需关闭动画
五、内容推荐
《CSDN》
《Android ButterKnife入门到放弃》
《Android 10文档阅读总结》
《Android 自定义控件基础》
《Android 数据库知识回顾》
六、项目参考
单元测试、UI Automator与Espresso基础代码都放在下面的项目中,有兴趣的可以看下。
Github:BLCS —— apk下载体验地址
若您发现文章中存在错误或不足的地方,希望您能指出!