Appium Uiautomator2 Server源码调试指南

120 阅读4分钟

appium-uiautomator2-server 是Appium在安卓端实现自动化能力的核心,上层脚本的所有操作,最终都转换成基于 appium-uiautomator2-server 提供的HTTP接口进行调用。本篇讲述该模块的调试方法,帮助读者更好的理解Appium在安卓上是如何实现自动化的。

本文配套工程链接

1.uiautomator与uiautomator2-server的关系

UI Automator 是google官方提供的一个用于编写自动化测试的官方库,其优势主要为:

官方目前大力支持的框架之一(另外一个是Expresso),

基于安卓原生控件解析,比坐标类型的兼容性更好

提供了丰富的等待机制

不依赖源码(纯黑盒)

可以跨应用。

市面上的诸多安卓测试工具(Appium,Minitest,ATX)等基本都绕不开对uiautomator库的依赖。

但如果直接使用uiautomator进行自动化测试,需要编写原生的java或kotlin代码,成本较高。uiautomator2-server的作用,就是对uiautomator的API做进一步的封装,将UI自动化常用的操作,通过HTTP接口的方式提供出来。使用者只需要把Appium Uiautomator2 Server在手机上运行起来,就可以通过给它发送各种HTTP请求,驱动自动化流程的进行。也正是得益于uiautomator2-server这层HTTP服务封装,Appium的上层脚本才可以支持多种编程语言(Ruby,Python,JS,Java),最终都会把上层业务的各种指令转换成uiautomator2-server的接口请求。

为方便学习,本文配套工程链接 以源代码形式引入了uiautomator,在config.gradle文件中,将useRemoteSDKLibrary设置为false即为源码依赖模式。

2.调试Appium自带的APK

Appium官方针对Appium Uiautomator2 Server编写了一系列的E2E测试代码,并提供了一个单独的APK。

APi_demo.png

测试工程将该apk文件放到了项目的目录下,并修改了运行脚本。

run_e2e_test.png

androidTest目录下的用例,可以直接点红框的按钮运行起来。覆盖了Appium Uiautomator2 Server基本的接口调用。

debug_e2e_test.png

也可以在代码中设置断点,以debug的方式单步调试运行。

3.调试设备上的其他应用

由于Appium Uiautomator2 Server编写的E2E测试代码,会默认拉起ApiDemos-debug.apk应用。如果期望验证其他的应用,可以通过设置 配置文件 中的 runApiDemoApk 字段为false。

后续的E2E测试用例将不再拉起默认的应用,可以自己编写针对目标App的测试代码。

4.基于HTTP请求的方式运行Appium Uiautomator2 Server

(1) 打包Appium Uiautomator2 Server 工程

在项目根目录下运行打包命令:

./gradlew clean assembleServerDebug assembleServerDebugAndroidTest

注意打包环境的jdk版本必须>=11以上,最终的打包产物为如下的两个apk:

uia_server_apks.png

正式安装之前,可以将之前的e2e相关测试apk卸载掉,执行如下命令:

adb uninstall io.appium.uiautomator2.server.test
adb uninstall io.appium.uiautomator2.server
adb uninstall io.appium.uiautomator2.e2etest.test
adb uninstall io.appium.uiautomator2.e2etest
adb uninstall io.appium.espressoserver.test

之后通过 adb install -r 将上面的两个产物apk完成路径拼入,执行安装即可。

(2) 启动 Appium Uiautomator2 Server 服务

step1:本地先做端口转发:

adb forward tcp:65272 tcp:6790

其中 65272 可以换为其他的端口号,不冲突即可。

step2:控制台基于instrument启动服务

adb shell am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner

(3) 给服务发送请求

(1) 建立连接

curl -d '{"capabilities":{}}' -X POST "http://127.0.0.1:65272/session"

返回:

{"sessionId":"ccf6f9e5-4e53-41a3-8212-61ba80a23ed4","value":{"capabilities":{},"sessionId":"ccf6f9e5-4e53-41a3-8212-61ba80a23ed4"}}%

表示成功建立了一个会话连接请求。

这里定义变量记录下sessionID,方便后续进一步的调试

CUR_SESSION_ID='ccf6f9e5-4e53-41a3-8212-61ba80a23ed4'

(2) 获取视图操作

curl -X GET "http://127.0.0.1:65272/session/$CUR_SESSION_ID/source"

输出即为当前界面的完整xml结构。

(3) 滑动操作

curl -d '{"endY":200,"endX":540,"startY":1710,"startX":540,"steps":100}' -X POST "http://127.0.0.1:65272/session/$CUR_SESSION_ID/touch/perform"

触发一个滑动的操作,[startX, startY][endX,endY] 分别表示滑动手势的开始位置与结束位置。step用于控制滑动操作整体的耗时。steps设置为100表示在0.5秒内完成。

(4) 查找操作

curl -d '{"selector":"更多信息","strategy":"accessibility id"}' -X POST "http://127.0.0.1:65272/session/$CUR_SESSION_ID/elements"

会查找当前界面 accessibility id更多信息的元素,结果为:

{"sessionId":"ccf6f9e5-4e53-41a3-8212-61ba80a23ed4","value":[{"ELEMENT":"00000000-0000-03af-ffff-ffff0000039a","element-6066-11e4-a52e-4f735466cecf":"00000000-0000-03af-ffff-ffff0000039a"}]}%

value部分为一个数组,表示查找到了目标元素信息。可以把元素id缓存起来:

CUR_ELELMENT_ID='00000000-0000-03af-ffff-ffff0000039a'

之后基于元素id,实现点击的操作:

curl -X POST "http://127.0.0.1:65272/session/$CUR_SESSION_ID/element/$CUR_ELELMENT_ID/click"

当前界面 accessibility id更多信息的元素就会被点击。

(5) 其他更多操作

Appium-Server的所有接口定义,均在AppiumServlet.java 文件中,按照上述的思路,拼接指定的参数,即可完成各个操作的测试流程。

5.参考

1. 使用 UI Automator 编写自动化测试

2. AndroidX UI Automator 代码库