美文网首页
Android Uiautomator运行提速

Android Uiautomator运行提速

作者: 每天多一点 | 来源:发表于2016-11-08 20:22 被阅读1207次

    概要

    Android Uiautomator的运行速度一直很快, 但是在个别场合会发现执行的非常缓慢. 本文就是这样一个问题的调查过程.

    问题

    因为应用中需要登录, 所以我们编写了响应的测试用例. 因为存在登录/非登录这两种情况, 而且有时候测试时并不知道当前的登录状态. 在不借助其他后端接口的前提下, 只能通过Ui进行判断. 经过真机上的测试, 我们发现这个判断登录的用例常常需要数分钟来执行. 为什么这么慢呢?

    调查

    经过实际的测试, 从UI判断登录状态时, 时间大部分消耗在了判断一个UI widget是否存在的函数中. 也就是 UiObject的exists函数. 但是查看了Android的文档后,

    public boolean exists ()
    
    Check if view exists. This methods performs a [waitForExists(long)](http://developer.android.com/intl/zh-cn/reference/android/support/test/uiautomator/UiObject.html#waitForExists(long))
     with zero timeout. This basically returns immediately whether the view represented by this UiObject exists or not. If you need to wait longer for this view, then see [waitForExists(long)](http://developer.android.com/intl/zh-cn/reference/android/support/test/uiautomator/UiObject.html#waitForExists(long))
    .
    

    我们可以发现按照文档记载, 这个接口是可以 immediately 返回的. 虽然字面上可能会有偏差, 但是应该不会有几分钟的延迟吧?

    使用uiautomator的console出处看不出来太多问题, 我们想到了logcat的输出.
    另开启一个终端, 记录下测试运行时的logcat输出, 可以发现有几段非常明显的 timeout, 类似如下:

    java.util.concurrent.TimeoutException: No idle state with idle timeout: 500 within global timeout: 10000
                at android.app.UiAutomation.waitForIdle(UiAutomation.java:533)
                at android.support.test.uiautomator.UiAutomatorBridge.waitForIdle(UiAutomatorBridge.java:112)
                at android.support.test.uiautomator.UiAutomatorBridge.waitForIdle(UiAutomatorBridge.java:107)
                at android.support.test.uiautomator.QueryController.findAccessibilityNodeInfo(QueryController.java:143)
                at android.support.test.uiautomator.QueryController.findAccessibilityNodeInfo(QueryController.java:138)
                at android.support.test.uiautomator.UiObject.findAccessibilityNodeInfo(UiObject.java:188)
                at android.support.test.uiautomator.UiObject.waitForExists(UiObject.java:928)
                at android.support.test.uiautomator.UiObject.exists(UiObject.java:979)
                at com.milo.tests.UiTestCaseBase$6.checkForCondition(UiTestCaseBase.java:162)
                at android.support.test.uiautomator.UiDevice.runWatchers(UiDevice.java:705)
                at android.support.test.uiautomator.UiObject.findAccessibilityNodeInfo(UiObject.java:193)
                at android.support.test.uiautomator.UiObject.waitForExists(UiObject.java:928)
                at android.support.test.uiautomator.UiObject.exists(UiObject.java:979)
                at com.milo.MyTest.IsLoggedin(MyTestPage.java:107)
                at ...
    

    从log上看久很明显了, 在UiObject不存在的情况下, 框架会自动调用runWatchers. 虽然这种机制会避免因为意外的警告造成的用例运行失败, 但是会拖慢运行. 每一次判断widget是否存在的场合都会运行所有的watcher

    解决

    因为我们的用例中, 不得不有关于widget的逻辑分支判断, 所以只能在这个用例的开始处remove所有的watcher, 在用例执行的后半段再次恢复register之前的watcher.

    结论

    1. 自动化用例的设计前提是避免逻辑分支. 但是我们目前的业务场景还没有找到更好的办法.
    2. 在用例不得不包含逻辑分支时, 将逻辑分支的前后处理都变的更"轻".
    3. Uiautomator的使用上, 避免Watcher在不希望的场景下被自动唤起.

    相关文章

      网友评论

          本文标题:Android Uiautomator运行提速

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