第十期_appium 进阶_20190825

课前准备

WebView认知

控件树里有没有对应的class

  • android.webkit.WebView
  • com.tencent.tbs.core.webkit.WebView

webview的组件的class多数都是android.view.View

webview组件分析

  • uiautomatorviewer
  • chrome://inspect

  • chrome从62版本开始引入了css标签解析的bug,导致无法很好的去inspect web页面
  • chrome://inspect需要翻x 需要下载62版本的chrome

自动化注意事项

  • 合理的使用显式等待
  • accessibility xpath定位

webview的调试

  • 模拟器默认开启webview的debug开关。网易mumu模拟器除外

chromedriver相关的配置

  • chromedriverUseSystemExecutable=true 默认使用/usr/local/lib/node_modules/appium/node_modules/_appium-chromedriver@4.14.0@appium-chromedriver/chromedriver/mac/chromedriver
  • chromedriverExecutableDir指向chromedriver的存放目录,目前不生效
  • chromedriverExecutable执行chromedriver的绝对路径

示例代码

    def test_webview(self):
        self.driver.find_element(MobileBy.XPATH, "//*[@text='交易']").click()
        #返回的是不带webview的组件,默认是找不到webview内的元素,除非设置了等待
        print(self.driver.page_source)
        #原生定位
        self.driver.find_element(MobileBy.ID, 'page_type_fund').click()

        WebDriverWait(self.driver, 10, 1).until(lambda x: "WEBVIEW_com.xueqiu.android" in self.driver.contexts)
        print("=======webview load")
        #返回的是带有webview组件树,此时可以使用原生定位去定位webview内的元素
        print(self.driver.page_source)
        #使用原生定位方式定位webview控件
        self.driver.find_element(MobileBy.ACCESSIBILITY_ID, "蛋卷基金安全开户").click()

        self.driver.switch_to.context("WEBVIEW_com.xueqiu.android")
        print("======webview enter")
        #返回的是html,此次可以使用selenium的css定位
        print(self.driver.page_source)
        self.driver.find_element(By.NAME, "tel").send_keys("15600534760")
        self.driver.find_element(By.NAME, "captcha").send_keys("1234")
        self.driver.find_element(By.CSS_SELECTOR, ".dj-button").click()

Webview识别原理

  • appium会启动chromedriver /Users/seveniruby/projects/chromedriver/2.20/chromedriver --url-base=wd/hub --port=8000 --adb-port=5037 --verbose
  • app或者浏览器,底层使用的是android的webview组件,webview组件有一个debug特性,可以在启动的时候,写入一个domain socket记录, webview_devtools_remote_3548
  • adb -P 5037 -s emulator-5554 shell cat /proc/net/unix 找到对应的webview调试入口
  • adb forward tcp:$port localabstract:webview_devtools_remote_$pid
  • curl http://localhost:7770/json/version
  • curl http://localhost:7770/json

自动寻找webview并分析

list_webview ()
{
    port=$1;
    adb shell cat /proc/net/unix | grep -a webview | awk -F_ '{print $NF}' | tr -d '\\r' | while read pid; do
        port=$((port+=1));
        adb forward tcp:$port localabstract:webview_devtools_remote_$pid;
        curl http://localhost:$port/json/version;
        curl http://localhost:$port/json;
    done
}
list_webview 7770

真机为了提高性能,默认不开启webview的debug属性,需要研发在webview的组件上调用debug开关
https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews?hl=zh-cn

adb network功能

networking:
 connect HOST[:PORT]      connect to a device via TCP/IP [default port=5555]
 disconnect [HOST[:PORT]]
     disconnect from given TCP/IP device [default port=5555], or all
 forward --list           list all forward socket connections
 forward [--no-rebind] LOCAL REMOTE
     forward socket connection using:
       tcp:<port> (<local> may be "tcp:0" to pick any open port)
       localabstract:<unix domain socket name>
       localreserved:<unix domain socket name>
       localfilesystem:<unix domain socket name>
       dev:<character device name>
       jdwp:<process pid> (remote only)
 forward --remove LOCAL   remove specific forward socket connection
 forward --remove-all     remove all forward socket connections

为什么uiautomator可以识别webview组件

  • 本来是不可识别的
  • 从android的高版本6.0之后uiautomator已经可以识别webview了,他会把webview转化为原生控件来表示

小程序

todo:

  • 44813内核不支持调试
  • appium无法识别小程序内的控件,但是uiautomatorviewer却可以

测试策略

  • 使用原生定位方式,通用性比较好
  • 把内嵌的网页使用手机浏览器代替测试
  • 如果还搞不定,模拟器上进行测试

腾讯FAT

常见错误

An unknown server-side error occurred while processing the command. Original error: No Chromedriver found that can automate Chrome '44.0.2403'. See https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md for more details. You could also try to enable automated chromedrivers download server feature

微信小程序无法切换context

[debug] [WD Proxy] Got response with status 200: {"sessionId":"960cbe136b1e6a12c5a4b574d0bfd9ca","status":13,"value":{"message":"unknown error: unable to discover open pages\\n  (Driver info: chromedriver=2.39.562713 (dd642283e958a93ebf6891600db055f1f1b4f3b2),platform=Mac OS X 10.14.5 x86_64)"}}
[debug] [WD Proxy] Determined the downstream protocol as 'MJSONWP' per session creation request
[WD Proxy] The response has an unknown format
[debug] [MJSONWP] Matched JSONWP error code 13 to UnknownError
[Chromedriver] Failed to start Chromedriver session: An unknown server-side error occurred while processing the command. Original error: unknown error: unable to discover open pages
[Chromedriver]   (Driver info: chromedriver=2.39.562713 (dd642283e958a93ebf6891600db055f1f1b4f3b2),platform=Mac OS X 10.14.5 x86_64)
[debug] [WD Proxy] Matched '/session' to command name 'createSession'
[debug] [WD Proxy] Proxying [POST /session] to [POST http://127.0.0.1:8000/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.tencent.mm","androidUseRunningApp":true,"androidDeviceSerial":"SWYDU16524028640"},"loggingPrefs":{"browser":"ALL"}}}
[debug] [Chromedriver] Webview version: 'Chrome/66.0.3359.126'

三端的脚本执行环境以及用于渲染非原生组件的环境是各不相同的:

在 iOS 上,小程序逻辑层的 javascript 代码运行在 JavaScriptCore 中,视图层是由 WKWebView 来渲染的,环境有 iOS8、iOS9、iOS10;

在 Android 上,

旧版本,小程序逻辑层的 javascript 代码运行中 X5 JSCore 中,视图层是由 X5 基于 Mobile Chrome 57 内核来渲染的;

新版本,小程序逻辑层的 javascript 代码运行在 V8 中,视图层是由自研 XWeb 引擎基于 Mobile Chrome 67 内核来渲染的;

在 开发工具上,小程序逻辑层的 javascript 代码是运行在 NW.js 中,视图层是由 Chromium 60 Webview 来渲染的。


1 个赞