Android record espresso 自动化UI单元测

作者: zhongjh | 来源:发表于2020-05-12 12:11 被阅读0次

    该文章记录的是我做日记diary的record espresso UI单元测试过程中所碰到的问题。进行录像单元测试后,有些操作是本身没问题,但是因为Android Studio工具本身没完善record espresso,需要进行代码微调才能达到你想要的效果,下面讲的对应场景的解决方法。

    效果图:

    效果图.gif

    什么是单元测试?什么是espresso?这些有很好的讲述了
    csdn上的一个博客
    官方例子

    启动单元测试之前关闭动画

    Espresso的同步,如果您在测试设备上允许动画,则不知道如何等待动画完成,可能导致某些测试失败。要关闭测试设备上的动画,请转到“设置” >“ 开发人员选项”,然后关闭“绘图”部分下的所有以下选项:

    • 窗口动画比例
    • 过渡动画比例
    • 动画师持续时间刻度

    场景1:文本框按下回车进行系列事件

    有个场景是文本框输入某些文字后,按下回车后会生成一个标签出来。

    使用record espresso生成的代码如下

            ViewInteraction mEditTextRightClick2 = onView(
                    allOf(withId(R.id.etTag),
                            childAtPosition(
                                    allOf(withId(R.id.flowLayoutTag),
                                            childAtPosition(
                                                    withClassName(is("android.widget.LinearLayout")),
                                                    1)),
                                    0),
                            isDisplayed()));
            mEditTextRightClick2.perform(replaceText("qww\n"), closeSoftKeyboard());
    

    会发现\n,因为录像识别出我们确实是按的回车,但我们要的并不是文本框显示回车,而是需要回车之后生成标签,那么我们这里代码则需要调整成这样:

    ViewInteraction mEditTextRightClick = onView(
                    allOf(withId(R.id.etTag),
                            childAtPosition(
                                    allOf(withId(R.id.flowLayoutTag),
                                            childAtPosition(
                                                    withClassName(is("android.widget.LinearLayout")),
                                                    1)),
                                    0),
                            isDisplayed()));
    mEditTextRightClick.perform(click());
    mEditTextRightClick.perform(replaceText("qwe"), pressKey(KeyEvent.KEYCODE_ENTER));
    

    唯一区别是这段代码

    mEditTextRightClick.perform(click());
    mEditTextRightClick.perform(replaceText("qwe"), pressKey(KeyEvent.KEYCODE_ENTER));
    

    这段代码意思就是点击该文本框,然后输入qwe文字之后回车。

    场景2:因为特殊事件(比如上面回车系列事件)导致点击无效

    使用record espresso生成的代码如下:

            ViewInteraction appCompatTextView = onView(
                    allOf(withText("qww"),
                            childAtPosition(
                                    allOf(withId(R.id.flowLayoutTag),
                                            childAtPosition(
                                                    withClassName(is("android.widget.LinearLayout")),
                                                    1)),
                                    1),
                            isDisplayed()));
            appCompatTextView.perform(longClick());
    

    这个长按事件是基于上面的生成标签后,并且长按他,但是录像生成的此代码会报错,长按的是flowLayoutTag本身,而不是child,至于这个问题可能是没进入焦点,所以我们就加入perform(click());来进入焦点,如下代码所示:

            ViewInteraction appCompatTextView = onView(
                    allOf(withText("qww"),
                            childAtPosition(
                                    allOf(withId(R.id.flowLayoutTag),
                                            childAtPosition(
                                                    withClassName(is("android.widget.LinearLayout")),
                                                    1)),
                                    1),
                            isDisplayed()));
            appCompatTextView.perform(click());
            appCompatTextView.perform(longClick());
    

    场景3:判断是否第一次界面

    这个每次record后都会类似于重新安装一次app,也就是会变成第一次运行app,大部分app在第一次运行后都会有“首次广告界面”的,那么就要在代码里面动态的判断是否运行那些广告界面的录制

    场景4:类似ViewPager选择事件

    报错:
    'has parent matching: with id: xxxx matches multiple views in the hierarchy.
    google后有很多类似这样的问题,字面上意思是这个xxxxid存在多个视图。

    这个场景是ViewPager每一个页面是个ListView,点击ViewPager
    生成的代码比较简单,可能是嵌套层数太多,导致record并不无法精确的知道你点击的是哪个控件。

    接下来就是看看如何精确获取控件,那么我们就需要在record过程中,点击如下图


    image.png 1.先点击该表情 2.再点击Save and Add Another按钮即可

    生成代码如下:

            ViewInteraction appCompatImageView = onView(
                    allOf(withId(R.id.imgAddFunctionFace),
                            childAtPosition(
                                    childAtPosition(
                                            withClassName(is("android.widget.LinearLayout")),
                                            0),
                                    0),
                            isDisplayed()));
            appCompatImageView.perform(click());
    

    场景4.1:

    也会出现过基于上面获取控件后,实际上运行还是会报错,找不到此控件,那么这里有个小诀窍,就是在你想找到的控件的同层结构上,随便添加一个控件,例如EditText,录制测试时对它进行文本编辑操作,然后在你生成代码后,将这个生成的EditText控件换成你想获取的控件即可。

    场景5:滑动事件

    当你滑动后,record是不会为你生成代码的,所以这方面需要我们微调代码,在需要滑动的地方添加以下代码:

    // 往右滑动
    onView(withId(R.id.viewPager)).perform(swipeRight());
    

    场景5.1:滑动事件不生效

    有时候perform(swipeRight())并没有往右边滑动,用perform(swipeLeft())却能往右边滑动。具体原因还找不到,后面找到了再补充

    同理,swipeDown()也会存在一样的问题,需要使用swipeUp()

    场景6:自制view不会自动生成测试代码

    用代替控件方式比较好,因为直接用Add xxx方式,拿到的索引值,在真实测试中是不行的

    场景7:一些固定动画自行添加延迟时间

    因为即使关闭了动画,但是一些自制自定义view的一些动画延迟还是存在的,所以我们需要自行添加延迟时间,不然会找不到控件。

            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    

    场景8:recyclerView点击某个position的代码

    录制代码生成是不会对recyclerView特殊对待的,需要自己写一个这样的点击代码

    recyclerView.perform(RecyclerViewActions.actionOnItemAtPosition(10, click()));
    

    相关文章

      网友评论

        本文标题:Android record espresso 自动化UI单元测

        本文链接:https://www.haomeiwen.com/subject/nmnlvhtx.html