干货|app自动化测试之Appium WebView 技术原理

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
日志服务 SLS,月写入数据量 50GB 1个月
简介: 混合应用测试或微信小程序测试,都会涉及到 WebView 组件,这节内容将分析一下 WebView 的技术原理。首先通过日志分析查看 Appium 的运行过程。## WebView日志分析要想查看 ChromeDriver 的日志,需要在 Capability 里开启 一个开关项 showChromedriverLog。让 Appium 运行测试用例时能够生成 ChromeDrive

混合应用测试或微信小程序测试,都会涉及到 WebView 组件,这节内容将分析一下 WebView 的技术原理。首先通过日志分析查看 Appium 的运行过程。

WebView日志分析

要想查看 ChromeDriver 的日志,需要在 Capability 里开启 一个开关项 showChromedriverLog。让 Appium 运行测试用例时能够生成 ChromeDriver 相关的日志(默认是不打印 ChromeDriver 这部分日志的)。代码如下:

capabilities['showChromedriverLog'] = True

启动 AppiumServer 并将生成的所有日志存储到文件 /tmp/appium.log 中:

appium -g /tmp/appium.log

关键日志分析

下面我们对 /tmp/appium.log 文件中的关键日志进行详细的分析。首先找到 Context 切换的日志,发现 Context 切换到 WEBVIEW_io.appium.android.apis 上下文中:

[HTTP] <-- GET /wd/hub/session/xx/contexts 200 99 ms - 145
[HTTP] --> POST /wd/hub/session/xx/context \
{"name":"WEBVIEW_io.appium.android.apis"}

Appium 在本地开启了两个 WebView 进程,进程号分别是 1271 和 26060。

[debug] [AndroidDriver] WEBVIEW_1271 mapped to pid 1271
[debug] [AndroidDriver] Getting process name for webview
[debug] [ADB] Getting connected devices...
[debug] [AndroidDriver] WEBVIEW_26060 mapped to pid 26060
[debug] [AndroidDriver] Getting process name for webview

然后,Appium 通过使用 adb 命令来查看 1271 和 26060 的进程信息。

[debug] [ADB] Running '/Users/xxxx/profile/android-sdk_r2.4.1-\
macosx/android-sdk-macosx/platform-tools/adb' with args: ["-P",5037,\
"-s","192.168.56.101:5555","shell","ps"]
[debug] [AndroidDriver] Parsed pid: '1271' pkg: 'cn.goapk.market' from
[debug] [AndroidDriver]     USER     PID   PPID  VSIZE  RSS     \
WCHAN \   PC         NAME
[debug] [AndroidDriver]     u0_a58    1271  192   606848 53268 \
ffffffff b76c707b S cn.goapk.market
[debug] [AndroidDriver] Returning process name: 'cn.goapk.market'
[debug] [AndroidDriver] Parsed pid: '26060' pkg: 'io.appium.android.\
apis'\ from
[debug] [AndroidDriver]     USER     PID   PPID  VSIZE  RSS   \
  WCHAN    PC         NAME
[debug] [AndroidDriver]     u0_a139   26060 192   649076 68004\
 ffffffff b76c6371 R io.appium.android.apis
[debug] [AndroidDriver] Returning process name:\
 'io.appium.android.apis'

Appium Server 列出通过进程查找到的所有 WebView 和可用 Context,如下:

[debug] [AndroidDriver] Found webviews: ["WEBVIEW_cn.goapk.market",\
"WEBVIEW_io.appium.android.apis"]
[debug] [AndroidDriver] Available contexts: ["NATIVE_APP",\
"WEBVIEW_cn.goapk.market","WEBVIEW_io.appium.android.apis"]

然后 Appium Server 尝试连接 ChromeDriver,由于我们没有设置 ChromeDriver 的端口,所以 Appium Server 默认启用 8000 端口与 WebView 通讯。Appium Server 通过 ChromeDriver 与 app WebView 通讯。

[debug] [AndroidDriver] Connecting to chrome-backed webview context\
 'WEBVIEW_io.appium.android.apis'
[debug] [AndroidDriver] A port was not given, using random port: 8000

然后,Appium 先杀掉 ChromeDriver 这个进程,清理 adb 映射端口数据,如下:

[debug] [Chromedriver] Killing any old chromedrivers, running: \
pkill -15 -f "/usr/local/lib/node_modules/appium/node_modules/\
_appium-chromedriver@3.1.3@appium-chromedriver/chromedriver/mac/\
chromedriver.*--port=8000"
[Chromedriver] No old chromedrivers seemed to exist
[debug] [Chromedriver] Cleaning any old adb forwarded port socket \
connections
[debug] [ADB] List forwarding ports
[debug] [ADB] Running '/Users/xxx/profile/android-sdk_r24.4.1-macosx\
/android-sdk-macosx/platform-tools/adb' with args: ["-P",5037,"-s","192.168.56.101:5555","forward","--list"]

到这步是真正开启 ChromeDriver 服务,建立起 Appium Server 与 ChromeDriver 之间的通讯。

[Chromedriver] Spawning chromedriver with: /usr/local/lib/\
node_modules/appium/node_modules/_appium-chromedriver@3.1.3@\
appium-chromedriver/chromedriver/mac/chromedriver --url-base=wd/hub \
--port=8000 --adb-port=5037 --verbose

建立连接之后,Appium Server 先查看 ChromeDriver 版本号。

[debug] [Chromedriver] Chromedriver version: '2.33.506106'

ChromeDriver 打印启动日志,开始传输参数。

[debug] [Chromedriver] [STDOUT] Starting ChromeDriver 2.33.506106 \
(8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2) on port 8000
[debug] [Chromedriver] [STDOUT] Only local connections are allowed.
[debug] [JSONWP Proxy] Proxying [GET /status] to [GET\
 http://127.0.0.1:8000/wd/hub/status] with no body
[debug] [JSONWP Proxy] Got response with status 200:\
 "{\"sessionId\":\"\",\"status\":0,\"value\":{\"build\":{\"version
 \":\"alpha\"},\"os\":{\"arch\":\"x86_64\",\"name\":\"Mac OS X\",
 \"version\":\"10.12.6\"}}}"
[debug] [JSONWP Proxy] Proxying [POST /session] to [POST \
http://127.0.0.1:8000/wd/hub/session] with body: {"\
desiredCapabilities"\:{"chromeOptions":{"androidPackage":\
"io.appium.android.apis","androidUseRunningApp":true,"androidDeviceSerial":"192.168.56.101:5555"}}}

通过 ps 命令列出手机的进程列表,从中查找 WebView。

[Chromedriver] [STDERR] [0.349][DEBUG]: \
Sending adb command: \
host:transport:192.168.56.101:5555|shell:ps && ps -A

通过进程列表获取 WebView 的进程号,Appium 根据这些信息操作 WebView。

Chromedriver] [STDERR] [0.365][DEBUG]: \
Sending adb command: \
host-serial:192.168.56.101:5555:forward:tcp:12531;\
localabstract:webview_devtools_remote_26060

查看WebView

WebView 控件会被映射为原生控件,类型为 View,其中的文本内容会变成 content-desc(Android 6.0)或者 text(Android 9.0)。
打开雪球 APP,下面命令可以查看 Android 系统内的 WebView 进程:

Hogwarts $ adb shell cat /proc/net/unix | grep webview
0000000000000000: 00000002 00000000 00010000 0001 01 12863 /dev/socket/webview_zygote
0000000000000000: 00000002 00000000 00010000 0001 01 24703 @webview_devtools_remote_1758
0000000000000000: 00000003 00000000 00000000 0001 03 24672 /dev/socket/webview_zygote

上面的命令中,凡是名字前面有 @ 的都是套接字。套接字(Socket)是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
下面命令查看这个进程对应的应用:

Hogwarts $ adb shell ps |grep 1758

u0_a67        1758   211 1600592 333680 futex_wait_queue_me f016fbb9 S com.xueqiu.android

查看到是雪球 APP 的 WebView 进程。测试时,Appium Server 就利用这个端口实现与 WebView 的通讯。

Context切换

由于直接操作套接字很难,所以使用 adb forward 将它重定向到本地端口。

adb forward tcp:$port localabstract:webview_devtools_remote_$pid

例如:使用本地 7777 端口

Hogwarts $ adb forward tcp:7777 localabstract:webview_devtools_remote_1758

可以发送 http 请求实现相关操作,下面获取 WebView 组件版本(也可以直接在浏览器中访问 http://localhost:7777/json/version),命令如下:

Hogwarts $ curl http://localhost:7777/json/version
{
   "Android-Package": "com.xueqiu.android",
   "Browser": "Chrome/74.0.3729.186",
   "Protocol-Version": "1.3",
   "User-Agent": "Mozilla/5.0 (Linux; Android 8.1.0; Google Pixel_1 Build/OPM6.171019.030.E1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.186 Mobile Safari/537.36",
   "V8-Version": "7.4.288.28",
   "WebKit-Version": "537.36 (@99fc61ba7ee9c511608e5ea11edc2622ba3b8e3f)",
   "webSocketDebuggerUrl": "ws://localhost:7777/devtools/browser"
}

Chrome 的 devtools 协议是远程调试协议(https://chromedevtools.github.io/devtools-protocol/
http://127.0.0.1:7777/json/list 可以直接获取 devtoolsFrontendUrl 查看调试的远程重定向的页面详细信息。

[
    {
        "description": "{\"attached\":true,\"empty\":false,\"height\":1605,\"screenX\":0,\"screenY\":189,\"visible\":true,\"width\":1080}",
        "devtoolsFrontendUrl": "http://chrome-devtools-frontend.appspot.com/serve_rev/@99fc61ba7ee9c511608e5ea11edc2622ba3b8e3f/inspector.html?ws=127.0.0.1:7777/devtools/page/06840BED58C1415235EFC9817FFD472E",
        "faviconUrl": "https://assets.imedao.com/broker/static/images/favicon.8d2e0522.png",
        "id": "06840BED58C1415235EFC9817FFD472E",
        "title": "平安证券 极速开户",
        "type": "page",
        "url": "https://broker.xueqiu.com/open/pingan?snb_from=tab",
        "webSocketDebuggerUrl": "ws://127.0.0.1:7777/devtools/page/06840BED58C1415235EFC9817FFD472E"
    },
    ...

然后访问Chrome的调试页面 chrome://inspect/#devices,就可以获取到页面元素信息,从而完成对元素的定位。

内容全面升级,4 个月 20+ 项目实战强化训练,资深测试架构师、开源项目作者亲授 BAT 大厂前沿最佳实践,带你一站式掌握测试开发必备核心技能(对标阿里P6+,年薪50W+)!直推 BAT 名企测试经理,普遍涨薪 50%+!

⬇️ 点击“阅读原文”,提升测试核心竞争力!
原文链接

相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
4月前
|
Java Android开发
Rockchip系列之CAN APP测试应用实现(4)
Rockchip系列之CAN APP测试应用实现(4)
73 1
|
4月前
|
测试技术 API Python
Appium控件交互策略:优化自动化测试效率的关键方法
该文介绍了如何使用Selenium与APP进行交互,包括点击、输入和状态判断等操作。例如,通过element.click()点击控件,element.send_keys()输入文本,以及element.is_displayed()检查元素是否可见。还展示了如何获取元素属性,如resource-id、text和class,并提供了Python代码示例来定位并操作APP元素,如滑动条的显示、可点击性检测及点击滑动条中心位置。在编写测试脚本时,应注意元素定位和状态验证以确保测试稳定性。
80 1
|
17天前
【Azure App Service】同一个App Service下创建多个测试站点的方式
【Azure App Service】同一个App Service下创建多个测试站点的方式
|
20天前
|
网络协议 安全 前端开发
【应用服务 App Service】Azure 应用服务测试网络访问其他域名及请求超时限制(4分钟 ≈ 230秒)
【应用服务 App Service】Azure 应用服务测试网络访问其他域名及请求超时限制(4分钟 ≈ 230秒)
|
22天前
|
测试技术 Android开发 iOS开发
Appium 是一个开源的自动化测试框架,它支持多种平台和多种编程语言
Appium是一款开源自动化测试框架,支持iOS和Android多平台及多种编程语言。通过WebDriver协议,开发者可编写自动化测试脚本。在iPhone上实现屏幕点击等操作需安装Appium及其依赖,启动服务器,并设置所需的测试环境参数。利用Python等语言编写测试脚本,模拟用户交互行为,最后运行测试脚本来验证应用功能。对于iPhone测试,需准备真实设备或Xcode模拟器。
55 1
|
11天前
|
Java 测试技术 API
探索自动化测试的奥秘:从Selenium到Appium
【8月更文挑战第31天】本文旨在引导读者理解自动化测试的重要性,并逐步深入介绍如何利用Selenium和Appium这两个强大的工具来提升测试效率和质量。文章不仅分享理论知识,还通过具体代码示例,展示如何在Web应用和移动应用测试中实施自动化策略。
|
11天前
|
测试技术 Android开发 iOS开发
探索自动化测试的奥秘:从Selenium到Appium
【8月更文挑战第31天】在软件测试的海洋中,自动化测试如同一艘快艇,带领我们高效地穿越波涛汹涌的手动测试海域。本文将带你从Selenium的网页自动化测试出发,一路驶向Appium的移动应用自动化测试岛屿,揭秘这两种工具如何改变软件测试的航向。你将看到代码示例的灯塔,指引你理解它们如何在实战中发挥作用,以及为什么掌握这些技能对于测试人员来说至关重要。
|
12天前
|
Java 测试技术 Android开发
探索自动化测试之美:从Selenium到Appium
【8月更文挑战第31天】在软件开发的世界中,测试是确保产品质量的关键步骤。随着技术的发展,自动化测试工具如Selenium和Appium成为了开发者的得力助手。本文将通过一个简单的代码示例,带领读者了解如何利用这些工具进行高效的自动化测试,确保软件的稳定性和可靠性,同时也让测试过程变得更加轻松有趣。
|
14天前
|
测试技术
一款功能完善的智能匹配1V1视频聊天App应该通过的测试CASE
文章列举了一系列针对1V1视频聊天App的测试用例,包括UI样式、权限请求、登录流程、匹配逻辑、消息处理、充值功能等多个方面的测试点,并标注了每个测试用例的执行状态,如通过(PASS)、失败(FAIL)或需要进一步处理(延期修改、待定、方案再定等)。
24 0
|
20天前
|
Linux C#
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application