在不插USB的情况下对设备远程操作/启动测试任务一直是一个非常有用的功能,因为公司里的测试设备总是分散的,而且一堆USB线连测试设备总是非常麻烦。ATX项目组提供的 uiautomator2 借助了一系列的工具,使得能够用Python编写自动化脚本,同时可以脚本可以通过WiFi直接操控同WiFi下的设备。另一方面 Maxim 提供了一个非常稳定而且高效的UI全自动话压力/稳定性/遍历测试。两者如果能结合,效果可观。作为同时两个项目的贡献者,分享调和两者的成果以及方案。

背景介绍

uiautomator2有如下组件:

设备端大管家是atx-agent,必须有adb shell运行权限,保活其他三个,同时是设备端HTTP服务器入口,负责路由HTTP请求给另外三个部件

https://testerhome.com/uploads/photo/2018/6740ed05-ad1a-4498-8878-aeb44bdd638d.png!large

Maxim有两个组件framework.jarmonkey.jar,都是设备端的,其中framework.jar是一个定制的AccessibilityService,而monkey.jar大改自Google原生monkey,实现遍历逻辑等。一般通过adb shell命令行启动,必须有adb shell(同android-uiautomator-server,这样才能操作其他APP),可以脱机运行(类似nohup),即启动后可以关掉命令行进程不会被杀直到运行完成。

结合方案设计

矛盾点: uiautomator2和Maxim工作时都需要连接系统的AccessibilityService,而AccessibilityService只能单连接;所以启动了uiautomator2才有免USB操作的能力,但是占用了AccessibilityService,如果通过uiautomator2启动Maxim会挂。

经过研究,android-uiautomator-server只是uiautomator2中与selector,click等相关的服务;atx-agent提供执行设备端shell命令的功能(fork,执行,因为fork自atx-agent所以有adb shell权限),所以可以首先启动所有uiautomator2组件待WiFi无线操作可用后,暂时关闭android-uiautomator-server,然后通过atx-agent启动Maxim,执行完成后再通过atx-agent重新拉活android-uiautomator-server恢复uiautomator2的功能,相关片段整理如下:

import uiautomator2 as u2

d = u2.connect('192.168.0.149') # 连接设备
print(d.info)
# 启动前关闭atx-agent守护的uiautomator-server进程
d.service('uiautomator').stop()
# Maxim正常运行
task = d.shell("CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.Monkey -p com.hotbitmapgg.ohmybilibili --running-minutes 2 --throttle 1500 --uiautomatormix --output-directory /sdcard/max-output", stream=True) # stream模式,保证不会timeout导致杀掉,底层上是一个requests库提供的streaming 模式的response
try:
    for line in task.iter_lines():
        print(line)
finally:
    task.close()
print('Done')
# 重新让atx-agent拉活uiautomator-server进程,或者执行下一条需要uiautomator-server的命令也会自行拉活
d.service('uiautomator').start()
d.press('home')