Android Espresso入门到自动搞定

没有捕抓不到的猎物,就看你有没有野心去捕抓;没有完成不了的事情,就看你有没有野心去做。 ————《狼道》

目录
一、前言
二、简介
(1)是什么
(2)有什么用
(3)怎么用
1.添加依赖
2.基本使用
3.基础知识
4.方法介绍
5.错误处理
6.自动生成测试用例
三、原理
(4)原理是什么
四、总结
(5)优点与缺点
五、内容推荐
六、项目参考


一、前言

很早之前写过一篇《JUnit单元测试》,比较简单常用的测试方法。写的只能算是入门知识也不算很细。后面又用过UI Automator与Espresso,不过都没好好总结。最近刚好需要重新回顾了一下,顺便也做下记录。UI Automator与Espresso都是Android自动化测试框架,各有优缺点,不过个人相比起来更喜欢后者。这里就给大家简单介绍下Espresso,整体大纲如下

二、简介

相关文档:Google文档其他网站

(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.记录界面交互

  1. 依次点击 Run > Record Espresso Test。
  2. 在 Run > Select Deployment Target 窗口中,选择要在哪个设备上记录测试。
  3. Record Your Test 窗口将在应用启动后显示

2.添加断言以验证界面元素

  1. text is:检查选定 View 元素的文本内容
  2. exists:检查 View 元素是否存在于屏幕上可见的当前 View 层次结构中
  3. does not exist:检查 View 元素是否不存在于当前 View 层次结构中

操作步骤:

  1. 点击 Add Assertion
  2. 当前屏幕的布局将显示在 Record Your Test 窗口右侧的面板中
  3. 从 Edit assertion 框的第二个下拉菜单中选择要使用的断言
  4. 点击 Save and Add Another 以再创建一个断言,或点击 Save Assertion 以关闭断言面板

3.保存记录

  1. 点击 Complete Recording。此时将显示 Pick a test class name for your test 窗口
  2. Espresso 测试记录器会根据已启动 Activity 的名称在软件包内为您的测试提供一个唯一的名称
  3. 文件将在 Espresso 测试记录器生成它后自动打开,Android Studio 将显示在 IDE 的 Project 窗口中选择的测试类

最后一点很好用,不想写代码的可以好好利用。但是不一定比自己写的快,只要把基础代码封装好。编写起来也很快。

三、原理

(4)原理是什么

因为是测试方面的框架,所以分析起来对我来说还是有点难度。所以这里就不献丑了,网上看到过一篇就推荐给大家,想更详细了解的可以看看https://www.jianshu.com/p/1fb248b77b36

四、总结

(5)优缺点

个人使用过程中与UI Automator做了些对比。

  1. API接口比较少,代码简洁,使用方便,运行速度快
  2. AS提供可自动生成编码测试的工具
  3. 适合由熟悉项目人来编写,自动生成除外
  4. 无需主动写Sleep等待UI事件的执行和UI的绘制
  5. 运行测试前需关闭动画

五、内容推荐

《CSDN》
《Android ButterKnife入门到放弃》​​​​​​​
《Android 10文档阅读总结》
《Android 自定义控件基础》
《Android 数据库知识回顾》​​​​​​​

六、项目参考

单元测试、UI Automator与Espresso基础代码都放在下面的项目中,有兴趣的可以看下。
Github:BLCS —— apk下载体验地址

若您发现文章中存在错误或不足的地方,希望您能指出!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容