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. 运行测试前需关闭动画

五、内容推荐

《简书》

《Android ButterKnife入门到放弃》

《Android 10文档阅读总结》

《Android 学习资源收集》

《Android 自定义控件基础》

六、项目参考

单元测试、UI Automator与Espresso基础代码都放在下面的项目中,有兴趣的可以看下。

Github:https://github.com/DayorNight/BLCS

apk下载体验地址:https://www.pgyer.com/BLCS

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章