公开课_webview 与微信小程序_20190911

课前准备

社区推广



appium的初体验

使用appium server或者appium desktop

appium server

npm install -g cnpm
cnpm install -g appium

appium desktop:https://github.com/appium/appium-desktop/releases
同屏工具:https://github.com/Genymobile/scrcpy

手机浏览器的自动化测试

from appium import webdriver
import pytest

class TestChrome:
def setup(self):

caps = {}
caps["platformName"] = "android"
caps["browserName"] = "chrome"
caps["deviceName"] = "hogwarts"

self.driver = webdriver.Remote("http://localhost:5723/wd/hub", caps)
self.driver.implicitly_wait(6)
self.driver.get("https://testerhome.com")

def test_topic(self):
self.driver.find_element_by_partial_link_text("教师节").click()

def teardown(self):
pass
#self.driver.quit()

相关命令

 /usr/local/lib/node_modules/appium/node_modules/_appium-chromedriver@4.14.0@appium-chromedriver/chromedriver/mac/chromedriver --url-base=wd/hub --port=8000 --adb-port=5037 --verbose

adb shell cat /proc/net/unix | grep chrome
adb forward tcp:7770 localabstract:chrome_devtools_remote
curl http://127.0.0.1:7770

手机浏览器

微信的内置浏览器

微信TBS内核

手机浏览器里的任意聊天窗口(推荐是文件传输助手),输入 debugtbs.qq.com

微信小程序分析

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,此次可以使用seleniumcss定位
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转化为原生控件来表示

小程序

  • debugtbs.qq.com

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 pagesn  (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 来渲染的,环境有 iOS8iOS9iOS10

Android 上,

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

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

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