一、写在前面
本文分析的 Appium Server 运行日志基于 Appium2.0 版本,以 Android 平台为例。
官方参考文档:
https://github.com/Appium/Appium-uiautomator2-server/wiki
https://github.com/appium/appium-uiautomator2-server/wiki/How-Server-module-works
https://github.com/appium/appium-uiautomator2-server
二、日志分析
# 启动Appium Server,并加载uiautomator2 driver [Appium] Welcome to Appium v2.2.2 [Appium] Attempting to load driver uiautomator2... [Appium] Requiring driver at C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver # Appium 已成功启动,使用4723端口监听来自客户端的http请求 [Appium] Appium REST http interface listener started on http://0.0.0.0:4723 [Appium] You can provide the following URLs in your client code to connect to this server: [Appium] http://192.168.2.108:4723/ [Appium] http://169.254.53.195:4723/ [Appium] http://169.254.122.200:4723/ [Appium] http://127.0.0.1:4723/ (only accessible from the same host) # Appium的可用驱动 [Appium] Available drivers: [Appium] - uiautomator2@2.34.1 (automationName 'UiAutomator2') [Appium] No plugins have been installed. Use the "Appium plugin" command to install the one(s) you want to use. # 客户端发起get请求获取当前会话的信息,以避免重复创建相同的会话 [HTTP] --> GET /sessions [HTTP] {} # Server调用AppiumDriver获取会话信息(AppiumDriver充当客户端和移动设备之间的桥梁,它是一个抽象类,具体实现取决于目标移动平台。比如,对于 Android 应用,可以使用 AndroidDriver;对于 iOS 应用,可以使用 IOSDriver。) [AppiumDriver@6243] Calling AppiumDriver.getSessions() with args: [] [AppiumDriver@6243] Responding to client with driver.getSessions() result: [] [HTTP] <-- GET /sessions 304 14 ms - - # Request idempotency key 用于确保请求的幂等性,如果创建会话的请求由于某些原因失败,系统可以使用相同的 idempotency key 重试该请求,而无需担心产生意外的副作用。 [HTTP] [HTTP] Request idempotency key: 863f3b69-42b2-4563-9f91-500d0e25b038 # Appium 客户端发起post请求,创建一个新的会话(请求主体中,指定了自动化引擎为 "uiautomator2"等信息) [HTTP] --> POST /session [HTTP] {"capabilities":{"firstMatch":[{}],"alwaysMatch":{"Appium:automationName":"uiautomator2","platformName":"Android","Appium:deviceName":"127.0.0.1:62001","Appium:app":"D:\\resources\\imooc.apk"}}} [AppiumDriver@6243] Calling AppiumDriver.createSession() with args: [null,null,{"firstMatch":[{}],"alwaysMatch":{"Appium:automationName":"uiautomator2","platformName":"Android","Appium:deviceName":"127.0.0.1:62001","Appium:app":"D:\\resources\\imooc.apk"}}] [AppiumDriver@6243] Event 'newSessionRequested' logged at 1700836362705 (22:32:42 GMT+0800 (中国标准时间)) # 根据automationName='uiautomator2',指定使用的驱动为Appium-uiautomator2-driver [Appium] Attempting to find matching driver for automationName 'uiautomator2' and platformName 'Android' [Appium] The 'uiautomator2' driver was installed and matched caps. [Appium] Will require it at C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver [Appium] Requiring driver at C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver # 成功创建AndroidUiautomator2Driver会话,session id: 05578622-580d-43b4-9fbf-9fe9411f9f4b,注意这个session id 是维持Appium Server 与 Appium Client 之间的会话关系,当下次客户端发出请求时就会自带session id为唯一标识。 [AppiumDriver@6243] Appium v2.2.2 creating new AndroidUiautomator2Driver (v2.34.1) session [AppiumDriver@6243] Checking BaseDriver versions for Appium and AndroidUiautomator2Driver [AppiumDriver@6243] Appium's BaseDriver version is 9.4.2 [AppiumDriver@6243] AndroidUiautomator2Driver's BaseDriver version is 9.4.2 [AndroidUiautomator2Driver@f1aa] Creating session with W3C capabilities: { [AndroidUiautomator2Driver@f1aa] "alwaysMatch": { [AndroidUiautomator2Driver@f1aa] "platformName": "Android", [AndroidUiautomator2Driver@f1aa] "Appium:automationName": "uiautomator2", [AndroidUiautomator2Driver@f1aa] "Appium:deviceName": "127.0.0.1:62001", [AndroidUiautomator2Driver@f1aa] "Appium:app": "D:\\resources\\imooc.apk" [AndroidUiautomator2Driver@f1aa] }, [AndroidUiautomator2Driver@f1aa] "firstMatch": [ [AndroidUiautomator2Driver@f1aa] {} [AndroidUiautomator2Driver@f1aa] ] [AndroidUiautomator2Driver@f1aa] } [AndroidUiautomator2Driver@f1aa (05578622)] Session created with session id: 05578622-580d-43b4-9fbf-9fe9411f9f4b # 使用adb命令,将imooc.apk推送至Android设备(adb是一个C/S架构的应用程序,由三部分组成:adb客户端、adb服务端、adbd守护进程。adb客户端和adb服务端运行开发者的计算机上。当启动某个 adb 客户端时,该客户端会先检查是否有 adb 服务器进程已在运行。如果没有,它会启动服务器进程。服务器在启动后会与本地 TCP 端口 5037 绑定,并监听 adb 客户端发出的命令。adbd作为后台守护进程运行在Android设备上,Andorid设备通过usb或远程方式连接计算机。adb客户端将指令发送至adb服务端,adb服务端将来自客户端的指令传递给Android设备上的adbd,从而完成Android设备的交互和调试。) [BaseDriver] Using local app 'D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk' [AndroidUiautomator2Driver@f1aa (05578622)] Checking whether app is actually present [ADB] Found 3 'build-tools' folders under 'D:\ProgramFiles\Android\android-sdk' (newest first): [ADB] D:\ProgramFiles\Android\android-sdk\build-tools\30.0.0-preview [ADB] D:\ProgramFiles\Android\android-sdk\build-tools\29.0.3 [ADB] D:\ProgramFiles\Android\android-sdk\build-tools\26.0.0-preview [ADB] Using 'adb.exe' from 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 start-server' [AndroidDriver] Retrieving device list [ADB] Trying to find connected Android devices [ADB] Getting connected devices [ADB] Connected devices: [{"udid":"127.0.0.1:62001","state":"device"}] [AndroidDriver] Using device: 127.0.0.1:62001 [ADB] Using 'adb.exe' from 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 start-server' [ADB] Setting device id to 127.0.0.1:62001 [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell getprop ro.build.version.sdk' [ADB] Current device property 'ro.build.version.sdk': 25 [ADB] Device API level: 25 [AndroidDriver] Parsing package and activity from app manifest [ADB] Package name: 'cn.com.open.mooc' [ADB] Main activity name: 'cn.com.open.mooc.index.splash.MCSplashActivity' [AndroidDriver] Parsed package and activity are: cn.com.open.mooc/cn.com.open.mooc.index.splash.MCSplashActivity # 使用adb命令,将settings_apk-debug.apk安装至Android设备(io.Appium.settings 是 Appium 提供的一个用于配置测试会话的应用程序,可以模拟网络连接、定位服务等测试环境) [AndroidDriver] Pushing settings apk to device... [ADB] Getting package info for 'io.Appium.settings' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell dumpsys package io.Appium.settings' [ADB] App 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\io.Appium.settings\apks\settings_apk-debug.apk' is not installed [ADB] Installing 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\io.Appium.settings\apks\settings_apk-debug.apk' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 help' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 features' [ADB] The application at 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\io.Appium.settings\apks\settings_apk-debug.apk' will not be cached, because the device under test has confirmed the support of streamed installs [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 install -g C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\io.Appium.settings\apks\settings_apk-debug.apk' [ADB] The installation of 'settings_apk-debug.apk' took 1382ms [ADB] Install command stdout: Performing Streamed Install [ADB] Success [ADB] Getting IDs of all 'io.Appium.settings' processes [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1\:62001 shell 'pgrep --help; echo $?'' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1\:62001 shell 'pgrep ^Appium\\.settings$ || pgrep ^io\\.Appium\\.setti$'' [ADB] Getting IDs of all 'io.Appium.settings' processes [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1\:62001 shell 'pgrep ^Appium\\.settings$ || pgrep ^io\\.Appium\\.setti$'' # 启动Appium Settings app [ADB] Starting Appium Settings app [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell am start -n io.Appium.settings/.Settings -a android.intent.action.MAIN -c android.intent.category.LAUNCHER' [ADB] Getting IDs of all 'io.Appium.settings' processes [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1\:62001 shell 'pgrep ^Appium\\.settings$ || pgrep ^io\\.Appium\\.setti$'' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell appops set io.Appium.settings android:mock_location allow' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1\:62001 shell "[ -e '/data/local/tmp/mock_apps.json' ] && echo __PASS__"' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell cat /data/local/tmp/mock_apps.json' [Logcat] Starting logs capture with command: D:\\ProgramFiles\\Android\\android-sdk\\platform-tools\\adb.exe -P 5037 -s 127.0.0.1\:62001 logcat -v threadtime # 将UiAutomator2 Server的端口 6790 绑定至本地端口 8200(UiAutomator2 Server运行在Android设备上,将 UiAutomator2 Server的端口 6790 绑定至本地端口 8200,可以使Appium在本地使用该端口上监听并接收从UiAutomator2 Server发出的请求) [AndroidUiautomator2Driver@f1aa (05578622)] Forwarding UiAutomator2 Server port 6790 to local port 8200 [ADB] Forwarding system: 8200 to device: 6790 [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 forward tcp:8200 tcp:6790' # 使用 apksigner 工具验证Appium-uiautomator2-server-v5.12.16.apk和Appium-uiautomator2-server-debug-androidTest.apk的签名证书,确保其完整性和可信度 [ADB] Checking app cert for C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\Appium-uiautomator2-server\apks\Appium-uiautomator2-server-v5.12.16.apk [ADB] Checking app cert for C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\Appium-uiautomator2-server\apks\Appium-uiautomator2-server-debug-androidTest.apk [ADB] Using 'apksigner.jar' from 'D:\ProgramFiles\Android\android-sdk\build-tools\30.0.0-preview\lib\apksigner.jar' [ADB] Starting apksigner: 'C:\\Program Files\\Java\\jdk-21\\bin\\java.exe' -Xmx1024M -Xss1m -jar D:\\ProgramFiles\\Android\\android-sdk\\build-tools\\30.0.0-preview\\lib\\apksigner.jar verify --print-certs C:\\Users\\xyouw\\.Appium\\node_modules\\Appium-uiautomator2-driver\\node_modules\\Appium-uiautomator2-server\\apks\\Appium-uiautomator2-server-debug-androidTest.apk [ADB] Starting apksigner: 'C:\\Program Files\\Java\\jdk-21\\bin\\java.exe' -Xmx1024M -Xss1m -jar D:\\ProgramFiles\\Android\\android-sdk\\build-tools\\30.0.0-preview\\lib\\apksigner.jar verify --print-certs C:\\Users\\xyouw\\.Appium\\node_modules\\Appium-uiautomator2-driver\\node_modules\\Appium-uiautomator2-server\\apks\\Appium-uiautomator2-server-v5.12.16.apk [ADB] apksigner stdout: Signer #1 certificate DN: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US [ADB] Signer #1 certificate SHA-256 digest: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc [ADB] Signer #1 certificate SHA-1 digest: 61ed377e85d386a8dfee6b864bd85b0bfaa5af81 [ADB] Signer #1 certificate MD5 digest: e89b158e4bcf988ebd09eb83f5378e87 [ADB] [ADB] sha256 hash did match for 'Appium-uiautomator2-server-debug-androidTest.apk' [ADB] 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\Appium-uiautomator2-server\apks\Appium-uiautomator2-server-debug-androidTest.apk' is signed with the default certificate # 检查 appium-uiautomator2-server端的两个apk的安装状态(Appium-uiautomator2-server-v5.12.16.apk已安装,负责在设备上执行相应的 UI 自动化操作;Appium-uiautomator2-server-debug-androidTest.apk已安装,它包含一个单独的测试来启动server。官方文档说明:https://github.com/appium/appium-uiautomator2-server/wiki/How-Server-module-works) [ADB] Getting install status for io.Appium.uiautomator2.server.test [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell pm path io.Appium.uiautomator2.server.test' [ADB] apksigner stdout: Signer #1 certificate DN: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US [ADB] Signer #1 certificate SHA-256 digest: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc [ADB] Signer #1 certificate SHA-1 digest: 61ed377e85d386a8dfee6b864bd85b0bfaa5af81 [ADB] Signer #1 certificate MD5 digest: e89b158e4bcf988ebd09eb83f5378e87 [ADB] [ADB] sha256 hash did match for 'Appium-uiautomator2-server-v5.12.16.apk' [ADB] 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\Appium-uiautomator2-server\apks\Appium-uiautomator2-server-v5.12.16.apk' is signed with the default certificate [ADB] Getting package info for 'io.Appium.uiautomator2.server' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell dumpsys package io.Appium.uiautomator2.server' [ADB] The version name of the installed 'io.Appium.uiautomator2.server' is greater or equal to the application version name ('5.12.16' >= '5.12.16') [ADB] 'io.Appium.uiautomator2.server.test' is installed [AndroidUiautomator2Driver@f1aa (05578622)] Server packages status: [{"wasSigned":true,"installState":"sameVersionInstalled","appPath":"C:\\Users\\xyouw\\.Appium\\node_modules\\Appium-uiautomator2-driver\\node_modules\\Appium-uiautomator2-server\\apks\\Appium-uiautomator2-server-v5.12.16.apk","appId":"io.Appium.uiautomator2.server"},{"wasSigned":true,"installState":"sameVersionInstalled","appPath":"C:\\Users\\xyouw\\.Appium\\node_modules\\Appium-uiautomator2-driver\\node_modules\\Appium-uiautomator2-server\\apks\\Appium-uiautomator2-server-debug-androidTest.apk","appId":"io.Appium.uiautomator2.server.test"}] [AndroidUiautomator2Driver@f1aa (05578622)] Server packages are not going to be (re)installed [AndroidUiautomator2Driver@f1aa (05578622)] Waiting up to 30000ms for services to be available # 检查androidx.test.runner.AndroidJUnitRunner是否可用,它用于启动Appium-uiautomator2-server(官方文档:https://github.com/appium/appium-uiautomator2-server) [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell pm list instrumentation' [AndroidUiautomator2Driver@f1aa (05578622)] Instrumentation target 'io.Appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner' is available # 将Appium的这3个apk添加至 Doze 白名单,确保省电模式下可用 [ADB] Adding packages ["io.Appium.settings","io.Appium.uiautomator2.server","io.Appium.uiautomator2.server.test"] to Doze whitelist [ADB] Got the following command chunks to execute: [["dumpsys","deviceidle","whitelist","+io.Appium.settings",";","dumpsys","deviceidle","whitelist","+io.Appium.uiautomator2.server",";","dumpsys","deviceidle","whitelist","+io.Appium.uiautomator2.server.test",";"]] [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell dumpsys deviceidle whitelist +io.Appium.settings ; dumpsys deviceidle whitelist +io.Appium.uiautomator2.server ; dumpsys deviceidle whitelist +io.Appium.uiautomator2.server.test ;' # 检查imooc.apk的签名证书,确保其完整性和可信度 [ADB] Checking app cert for D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk [ADB] Starting apksigner: 'C:\\Program Files\\Java\\jdk-21\\bin\\java.exe' -Xmx1024M -Xss1m -jar D:\\ProgramFiles\\Android\\android-sdk\\build-tools\\30.0.0-preview\\lib\\apksigner.jar verify --print-certs D:\\resources\\imooc.apk [ADB] apksigner stdout: Signer #1 certificate DN: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US [ADB] Signer #1 certificate SHA-256 digest: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc [ADB] Signer #1 certificate SHA-1 digest: 61ed377e85d386a8dfee6b864bd85b0bfaa5af81 [ADB] Signer #1 certificate MD5 digest: e89b158e4bcf988ebd09eb83f5378e87 [ADB] [ADB] sha256 hash did match for 'imooc.apk' [ADB] 'D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk' is signed with the default certificate # 安装imooc.apk [ADB] Getting package info for 'cn.com.open.mooc' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell dumpsys package cn.com.open.mooc' [ADB] App 'D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk' is not installed [ADB] Installing 'D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk' [ADB] The application at 'D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk' will not be cached, because the device under test has confirmed the support of streamed installs [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 install D:\BaiduSyncdisk\xyouwen-workspace\ddautotest\resources\imooc.apk' [ADB] The installation of 'imooc.apk' took 3258ms [ADB] Install command stdout: Performing Streamed Install [ADB] Success # Android Uiautomator2 驱动执行浅层清理(shallow cleanup),检查是否存在不再需要的测试会话(obsolete sessions) [AndroidUiautomator2Driver@f1aa (05578622)] Performing shallow cleanup of automation leftovers [AndroidUiautomator2Driver@f1aa (05578622)] No obsolete sessions have been detected (socket hang up) [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell am force-stop io.Appium.uiautomator2.server.test' # AndroidUiautomator2Driver发出指令,启动UIAutomator2 server [AndroidUiautomator2Driver@f1aa (05578622)] Starting UIAutomator2 server 5.12.16 [AndroidUiautomator2Driver@f1aa (05578622)] Using UIAutomator2 server from 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\Appium-uiautomator2-server\apks\Appium-uiautomator2-server-v5.12.16.apk' and test from 'C:\Users\xyouw\.Appium\node_modules\Appium-uiautomator2-driver\node_modules\Appium-uiautomator2-server\apks\Appium-uiautomator2-server-debug-androidTest.apk' [AndroidUiautomator2Driver@f1aa (05578622)] Waiting up to 30000ms for UiAutomator2 to be online... # 通过 ADB 创建了一个子进程,这条命令是真正启动UIAutomator2 server的命令(官方文档:https://github.com/appium/appium-uiautomator2-server, 启动server的命令是:adb shell am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner) [ADB] Creating ADB subprocess with args: ["-P","5037","-s","127.0.0.1:62001","shell","am","instrument","-w","-e","disableAnalytics","true","io.Appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner"] # AndroidUiautomator2Driver 尝试通过 HTTP 请求检查 UiAutomator2 Server 的状态,UiAutomator2 server 初始化耗时3051ms [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/status' to command name 'getStatus' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /status] to [GET http://127.0.0.1:8200/status] with no body [AndroidUiautomator2Driver@f1aa (05578622)] socket hang up [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/status' to command name 'getStatus' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /status] to [GET http://127.0.0.1:8200/status] with no body [AndroidUiautomator2Driver@f1aa (05578622)] socket hang up [Instrumentation] io.Appium.uiautomator2.server.test.AppiumUiAutomator2Server: [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/status' to command name 'getStatus' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /status] to [GET http://127.0.0.1:8200/status] with no body [AndroidUiautomator2Driver@f1aa (05578622)] socket hang up [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/status' to command name 'getStatus' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /status] to [GET http://127.0.0.1:8200/status] with no body [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"None","value":{"message":"UiAutomator2 Server is ready to accept commands","ready":true}} [AndroidUiautomator2Driver@f1aa (05578622)] The initialization of the instrumentation process took 3051ms # AndroidUiautomator2Driver将来自客户端的请求(POST /session),代理至 UiAutomator2 Server [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/session' to command name 'createSession' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [POST /session] to [POST http://127.0.0.1:8200/session] with body: {"capabilities":{"firstMatch":[{"platformName":"Android","automationName":"uiautomator2","deviceName":"127.0.0.1:62001","app":"D:\\resources\\imooc.apk","platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"Android","automationName":"uiautomator2","deviceName":"127.0.0.1:62001","app":"D:\\resources\\imooc.apk"},"deviceUDID":"127.0.0.1:62001","appPackage":"cn.com.open.mooc"}],"alwaysMatch":{}}} # UiAutomator2 Server成功创建会话并返回相信信息,sessionId":"b339ede2-f5e2-4b68-b794-512addf83270,这个 sessionId 用来维护 AndroidUiautomator2Driver 与 UiAutomator2 Server之间的会话关系 [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":{"capabilities":{"firstMatch":[{"platformName":"Android","automationName":"uiautomator2","deviceName":"127.0.0.1:62001","app":"D:\\resources\\imooc.apk","platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"Android","automationName":"uiautomator2","deviceName":"127.0.0.1:62001","app":"D:\\resources\\imooc.apk"},"deviceUDID":"127.0.0.1:62001","appPackage":"cn.com.open.mooc"}],"alwaysMatch":{}},"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270"}} [AndroidUiautomator2Driver@f1aa (05578622)] Determined the downstream protocol as 'W3C' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /Appium/device/pixel_ratio] to [GET http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/Appium/device/pixel_ratio] with no body [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/Appium/device/system_bars' to command name 'getSystemBars' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /Appium/device/system_bars] to [GET http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/Appium/device/system_bars] with no body [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/window/current/size' to command name 'getWindowSize' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /window/current/size] to [GET http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/window/current/size] with no body [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /Appium/device/info] to [GET http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/Appium/device/info] with no body [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell dumpsys window' [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":2} [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":{"statusBar":48}} [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":{"height":1920,"width":1080}} [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":{"androidId":"10cb49a7464148e8","apiVersion":"25","bluetooth":{"state":"OFF"},"brand":"HUAWEI","carrierName":"CMCC","displayDensity":320,"locale":"zh_CN","manufacturer":"HUAWEI","model":"TAS-AN00","networks":[{"capabilities":{"SSID":null,"linkDownBandwidthKbps":1048576,"linkUpstreamBandwidthKbps":1048576,"networkCapabilities":"NET_CAPABILITY_NOT_METERED,NET_CAPABILITY_NOT_RESTRICTED,NET_CAPABILITY_NOT_VPN,NET_CAPABILITY_NOT_ROAMING,NET_CAPABILITY_INTERNET,NET_CAPABILITY_TRUSTED,NET_CAPABILITY_VALIDATED","signalStrength":-55,"transportTypes":"TRANSPORT_WIFI"},"detailedState":"CONNECTED","extraInfo":"\"WiredSSID\"","isAvailable":true,"isConnected":true,"isFailover":false,"isRoaming":false,"state":"CONNECTED","subtype":0,"subtypeName":"","type":1,"typeName":"WIFI"}],"platformVersion":"7.1.2","realDisplaySize":"1080x1920","timeZone":"Asia/Shanghai"}} # AndroidUiautomator2Driver调用adb命令启动被测应用并等待特定页面“cn.com.open.mooc/cn.com.open.mooc.index.splash.MCSplashActivity”被加载 [AndroidDriver] Screen already unlocked, doing nothing [AndroidUiautomator2Driver@f1aa (05578622)] Starting 'cn.com.open.mooc/cn.com.open.mooc.index.splash.MCSplashActivity and waiting for 'cn.com.open.mooc/cn.com.open.mooc.index.splash.MCSplashActivity' [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell am start -W -n cn.com.open.mooc/cn.com.open.mooc.index.splash.MCSplashActivity -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000' [ADB] Waiting up to 20000ms for activity matching pkg: 'cn.com.open.mooc' and activity: 'cn.com.open.mooc.index.splash.MCSplashActivity' to be focused [ADB] Possible activities, to be checked: 'cn.com.open.mooc.index.splash.MCSplashActivity', 'cn.com.open.mooc.cn.com.open.mooc.index.splash.MCSplashActivity' [ADB] Getting focused package and activity [ADB] Running 'D:\ProgramFiles\Android\android-sdk\platform-tools\adb.exe -P 5037 -s 127.0.0.1:62001 shell dumpsys window windows' [ADB] Found package: 'cn.com.open.mooc' and fully qualified activity name : 'cn.com.open.mooc.index.splash.MCSplashActivity' [AppiumDriver@6243] New AndroidUiautomator2Driver session created successfully, session 05578622-580d-43b4-9fbf-9fe9411f9f4b added to master session list [AppiumDriver@6243] Event 'newSessionStarted' logged at 1700836380436 (22:33:00 GMT+0800 (中国标准时间)) [AndroidUiautomator2Driver@f1aa (05578622)] Cached the protocol value 'W3C' for the new session 05578622-580d-43b4-9fbf-9fe9411f9f4b # 将响应结果返回给客户端 [AndroidUiautomator2Driver@f1aa (05578622)] Responding to client with driver.createSession() result: {"capabilities":{"platformName":"Android","automationName":"uiautomator2","deviceName":"127.0.0.1:62001","app":"D:\\resources\\imooc.apk","platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"Android","automationName":"uiautomator2","deviceName":"127.0.0.1:62001","app":"D:\\resources\\imooc.apk"},"deviceUDID":"127.0.0.1:62001","appPackage":"cn.com.open.mooc","pixelRatio":"2","statBarHeight":48,"viewportRect":{"left":0,"top":48,"width":1080,"height":1872},"deviceApiLevel":25,"platformVersion":"7.1.2","deviceManufacturer":"HUAWEI","deviceModel":"TAS-AN00","deviceScreenSize":"1080x1920","deviceScreenDensity":320}} [HTTP] <-- POST /session 200 17736 ms - 944 # 客户端发送“获取窗口尺寸”的请求,AndroidUiautomator2Driver携带表示与客户端关系的sessionid,将请求代理至UIAutomator2 Server [HTTP] [HTTP] --> GET /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/window/rect [HTTP] {} [AndroidUiautomator2Driver@f1aa (05578622)] Calling AppiumDriver.getWindowRect() with args: ["05578622-580d-43b4-9fbf-9fe9411f9f4b"] [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/window/current/size' to command name 'getWindowSize' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [GET /window/current/size] to [GET http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/window/current/size] with no body [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":{"height":1920,"width":1080}} # UIAutomator2 Server将响应结果,返回给AndroidUiautomator2Driver [AndroidUiautomator2Driver@f1aa (05578622)] Responding to client with driver.getWindowRect() result: {"width":1080,"height":1920,"x":0,"y":0} [HTTP] <-- GET /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/window/rect 200 14 ms - 50 # 客户端发送“滑动页面”请求,AndroidUiautomator2Driver携带表示与客户端关系的sessionid,将请求代理至UIAutomator2 Server [HTTP] [HTTP] --> POST /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/actions [HTTP] {"actions":[{"type":"pointer","parameters":{"pointerType":"touch"},"id":"touch","actions":[{"type":"pointerMove","duration":250,"x":810,"y":960,"origin":"viewport"},{"type":"pointerDown","duration":0,"button":0},{"type":"pointerMove","duration":500,"x":54,"y":960,"origin":"viewport"},{"type":"pointerUp","duration":0,"button":0}]}]} [AndroidUiautomator2Driver@f1aa (05578622)] Calling AppiumDriver.performActions() with args: [[{"type":"pointer","parameters":{"pointerType":"touch"},"id":"touch","actions":[{"type":"pointerMove","duration":250,"x":810,"y":960,"origin":"viewport"},{"type":"pointerDown","duration":0,"button":0},{"type":"pointerMove","duration":500,"x":54,"y":960,"origin":"viewport"},{"type":"pointerUp","duration":0,"button":0}]}],"05578622-580d-43b4-9fbf-9fe9411f9f4b"] [AndroidUiautomator2Driver@f1aa (05578622)] Received the following W3C actions: [ [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointer", [AndroidUiautomator2Driver@f1aa (05578622)] "parameters": { [AndroidUiautomator2Driver@f1aa (05578622)] "pointerType": "touch" [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] "id": "touch", [AndroidUiautomator2Driver@f1aa (05578622)] "actions": [ [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerMove", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 250, [AndroidUiautomator2Driver@f1aa (05578622)] "x": 810, [AndroidUiautomator2Driver@f1aa (05578622)] "y": 960, [AndroidUiautomator2Driver@f1aa (05578622)] "origin": "viewport" [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerDown", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 0, [AndroidUiautomator2Driver@f1aa (05578622)] "button": 0 [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerMove", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 500, [AndroidUiautomator2Driver@f1aa (05578622)] "x": 54, [AndroidUiautomator2Driver@f1aa (05578622)] "y": 960, [AndroidUiautomator2Driver@f1aa (05578622)] "origin": "viewport" [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerUp", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 0, [AndroidUiautomator2Driver@f1aa (05578622)] "button": 0 [AndroidUiautomator2Driver@f1aa (05578622)] } [AndroidUiautomator2Driver@f1aa (05578622)] ] [AndroidUiautomator2Driver@f1aa (05578622)] } [AndroidUiautomator2Driver@f1aa (05578622)] ] [AndroidUiautomator2Driver@f1aa (05578622)] Preprocessed actions: [ [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointer", [AndroidUiautomator2Driver@f1aa (05578622)] "parameters": { [AndroidUiautomator2Driver@f1aa (05578622)] "pointerType": "touch" [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] "id": "touch", [AndroidUiautomator2Driver@f1aa (05578622)] "actions": [ [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerMove", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 250, [AndroidUiautomator2Driver@f1aa (05578622)] "x": 810, [AndroidUiautomator2Driver@f1aa (05578622)] "y": 960, [AndroidUiautomator2Driver@f1aa (05578622)] "origin": "viewport" [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerDown", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 0, [AndroidUiautomator2Driver@f1aa (05578622)] "button": 0 [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerMove", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 500, [AndroidUiautomator2Driver@f1aa (05578622)] "x": 54, [AndroidUiautomator2Driver@f1aa (05578622)] "y": 960, [AndroidUiautomator2Driver@f1aa (05578622)] "origin": "viewport" [AndroidUiautomator2Driver@f1aa (05578622)] }, [AndroidUiautomator2Driver@f1aa (05578622)] { [AndroidUiautomator2Driver@f1aa (05578622)] "type": "pointerUp", [AndroidUiautomator2Driver@f1aa (05578622)] "duration": 0, [AndroidUiautomator2Driver@f1aa (05578622)] "button": 0 [AndroidUiautomator2Driver@f1aa (05578622)] } [AndroidUiautomator2Driver@f1aa (05578622)] ] [AndroidUiautomator2Driver@f1aa (05578622)] } [AndroidUiautomator2Driver@f1aa (05578622)] ] [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/actions' to command name 'performActions' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [POST /actions] to [POST http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/actions] with body: {"actions":[{"type":"pointer","parameters":{"pointerType":"touch"},"id":"touch","actions":[{"type":"pointerMove","duration":250,"x":810,"y":960,"origin":"viewport"},{"type":"pointerDown","duration":0,"button":0},{"type":"pointerMove","duration":500,"x":54,"y":960,"origin":"viewport"},{"type":"pointerUp","duration":0,"button":0}]}]} # UIAutomator2 Server将响应结果,返回给AndroidUiautomator2Driver [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":null} [AndroidUiautomator2Driver@f1aa (05578622)] Responding to client with driver.performActions() result: null [HTTP] <-- POST /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/actions 200 876 ms - 14 # 客户端发送“定位元素”的请求,AndroidUiautomator2Driver携带表示与客户端关系的sessionid,将请求代理至UIAutomator2 Server [HTTP] [HTTP] --> POST /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/element [HTTP] {"using":"id","value":"cn.com.open.mooc:id/viewpager"} [AndroidUiautomator2Driver@f1aa (05578622)] Calling AppiumDriver.findElement() with args: ["id","cn.com.open.mooc:id/viewpager","05578622-580d-43b4-9fbf-9fe9411f9f4b"] [AndroidUiautomator2Driver@f1aa (05578622)] Valid locator strategies for this request: xpath, id, class name, accessibility id, css selector, -android uiautomator [AndroidUiautomator2Driver@f1aa (05578622)] Waiting up to 0 ms for condition [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/element' to command name 'findElement' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [POST /element] to [POST http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/element] with body: {"strategy":"id","selector":"cn.com.open.mooc:id/viewpager","context":"","multiple":false} [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":{"ELEMENT":"00000000-0000-0006-7fff-ffff00000003","element-6066-11e4-a52e-4f735466cecf":"00000000-0000-0006-7fff-ffff00000003"}} # UIAutomator2 Server将响应结果,返回给AndroidUiautomator2Driver [AndroidUiautomator2Driver@f1aa (05578622)] Responding to client with driver.findElement() result: {"element-6066-11e4-a52e-4f735466cecf":"00000000-0000-0006-7fff-ffff00000003","ELEMENT":"00000000-0000-0006-7fff-ffff00000003"} [HTTP] <-- POST /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/element 200 123 ms - 137 # 客户端发送“点击元素”的请求,AndroidUiautomator2Driver携带表示与客户端关系的sessionid,将请求代理至UIAutomator2 Server [HTTP] [HTTP] --> POST /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/element/00000000-0000-0006-7fff-ffff00000003/click [HTTP] {} [AndroidUiautomator2Driver@f1aa (05578622)] Calling AppiumDriver.click() with args: ["00000000-0000-0006-7fff-ffff00000003","05578622-580d-43b4-9fbf-9fe9411f9f4b"] [AndroidUiautomator2Driver@f1aa (05578622)] Matched '/element/00000000-0000-0006-7fff-ffff00000003/click' to command name 'click' [AndroidUiautomator2Driver@f1aa (05578622)] Proxying [POST /element/00000000-0000-0006-7fff-ffff00000003/click] to [POST http://127.0.0.1:8200/session/b339ede2-f5e2-4b68-b794-512addf83270/element/00000000-0000-0006-7fff-ffff00000003/click] with body: {"element":"00000000-0000-0006-7fff-ffff00000003"} # UIAutomator2 Server将响应结果,返回给AndroidUiautomator2Driver [AndroidUiautomator2Driver@f1aa (05578622)] Got response with status 200: {"sessionId":"b339ede2-f5e2-4b68-b794-512addf83270","value":null} [AndroidUiautomator2Driver@f1aa (05578622)] Responding to client with driver.click() result: null [HTTP] <-- POST /session/05578622-580d-43b4-9fbf-9fe9411f9f4b/element/00000000-0000-0006-7fff-ffff00000003/click 200 19 ms - 14
三、总结
1、Appium 是一个 C/S 架构的自动化框架
几个核心概念:
1)Appium Client,它是使用 Appium API 编写和运行脚本的地方,比如我们使用 python 编写的自动化脚本。
2)Appium Server,它负责代理来自 Appium Client 的测试请求,调用 Google UIAutomator 与移动设备进行通信。Appium2.0 包括两个核心模块:
- UIAutomator2 Driver模块,它负责与 Appium Client 通信创建会话,使用 adb 将 uiautomtor2 server 的两个 APK 包安装至 Android 设备上,启动 UIAutomator2 Server;
- UIAutomator2 Server 模块,它负责处理来自 uiautomtor2 driver 的请求,调用调用 Google UIAutomator 与移动设备进行通信完成测试。
2、Appium2.0 的工作流程
1)Appium Server, 开启 4723 端口,监听来自 Appium Client 的请求;
2)Appium Client 发起 Post 请求,Appium Server 根据请求体中的 automationName 参数来启动相应的 driver(默认是 Appium-android-driver;如果 automationName 为 UIAutomator2,则启动 appium-uiautomator2-driver);
3)AndroidUiautomator2Driver 创建 session,并将 session id 返回给 Appium Client,当下次 Client 发出请求时就会携带 session id 为唯一标识;
4)AndroidUiautomator2Driver 调用 adb 命令将相关 apk 文件推送至 Android 设备,包括:imooc.apk(测试包)、settings_apk-debug.apk(用于模拟网络连接、定位服务等测试环境)、appium-uiautomator2-server-v5.12.16.apk(负责执行自动化操作)appium-uiautomator2-server-debug-androidTest.apk(用于启动 uiautomator2 server),使用 apksigner 签名验证后,安装至设备
5)AndroidUiautomator2Driver 创建 adb 子进程,执行命令 adb shell am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner
启动 uiautomator2 server,并将 UiAutomator2 Server 的端口 6790 绑定至本地端口 8200,使 Appium Server 在 8200 端口上监听并接收从 UiAutomator2 Server 发出的请求;
6)AndroidUiautomator2Driver 携带 sessiond id 将来自客户端的请求,代理转至 UiAutomator2 Server,UiAutomator2 Server 创建 session 与 AndroidUiautomator2Driver 建立连接;
7)UiAutomator2 Server 调用底层的 Google UIAutomator V2 在 Android 设备上执行操作,并将响应结果返回给 AndroidUiautomator2Driver;
8)AndroidUiautomator2Driver 将响应结果,返回给 Appium Client,完成闭环。