前言:

运行环境:

Android 7.0
+Appium 1.6.3

微信小程序是啥?

我们一个 app 里面除了 native 页面,还有 H5 页面,那么其实小程序也不过是正常的webview(webview 是一个基于 webkit 引擎、展现 web 页面的控件),本质还是H5(H5 是 HTML5 的简称)。我们对 app 做 UI 自动化时,可以操作 app 的 H5 页面,那么同样的我们也可以操作微信 app 的小程序。

webview 和 H5 的关系?

app 里面可以打开一个 webview,webview 中加载 H5 页面,即包含关系是:app > webview > H5。

一.打开微信的调试功能

通过在微信中点击打开http://debugx5.qq.com,或者直接扫下面二维码
,进入微信 X5 调试页面的配置


点击信息,然后勾选【打开 TBS 内核 Inspector 调试功能】

打开后我们对于微信就有更多的操作性,在chrome://inspect/#devices中也能看到更多的页面

二. Chrome 查看页面元素

手机连接电脑,终端输入:adb devices,查看是否连接成功。如下展示设备号则为连接成功


进入小程序,以【天天连连线】为例,在 Chrome 浏览器访问chrome://inspect/#devices(温馨提示:需要 *** 才能查看页面元素)

有没有小伙伴想问 57.0.2987.132 是什么意思,这是android system Webview的版本。android system Webview是安卓的一个浏览器内核,手机上的应用可以通过调用它来直接显示网页内容。那么对我们有什么影响吗,我们可以把它当成我们的 Chrome 浏览器版本 chrome=57.0.2987.132,它要跟我们的 chromedriver 版本对应 (如果不对应会导致上下文切换失败,无法进行后面的操作),我们才能正常操作 webview。我们可以理解为 appium 会调 chromedriver,chromedriver 去调 android system Webview,最后 android system Webview 可以控制我们小程序的 webview。

上面两张图好像是一个页面,但是显示不一样?左边的图是 macaca 的 app-inspector 中的,它显示的跟我手机页面一致,右边是 Chrome 的 inspect 页面,地址是:https://servicewechat.com/wxbc6682586d0990ea/14/page-frame.html,即是个 HTML 页面。所以如果小程序页面中用 native 写出来的控件,在 Chrome 的 inspect 页面是显示不出来的,因为它只显示 HTML 元素,也支持我们定位 HTML 元素。左边的 macaca 的 app-inspector 对于 native 元素的定位是肯定没问题的,但是如果有些 HTML 元素我们用 app-inspector 不好定位时,可以选择 Chrome 的 inspect。

三、查找小程序的进程

为什么要知道微信小程序的进程呢?

微信里面的小程序多不胜数,不同的小程序可能运行在不同的进程中。我们知道 app 的页面层会分 native 和 webview,像上一张图中,小程序 webview 页面地址https://servicewechat.com/wxbc6682586d0990ea/14/page-frame.html后缀是 html,即是一个 webview。我们使用 appium 做 UI 自动化时默认上下文是NATIVE_APP

如何查看【天天连连线】运行在哪个进程中?

adb shell dumpsys activity top | grep ACTIVITY
adb shell ps 23498

我们可以看到,当前的小程序运行在com.tencent.mm:appbrand0中,记住这个进程,记住啦。

四、Appium 控制小程序的 demo

appium 控制小程序,跟我们正常不同的一点就是:需要添加chromeoptions,值为{'androidProcess': 'com.tencent.mm:appbrand0'}androidProcess的值就是com.tencent.mm:appbrand0,即小程序的进程。

附:python 写的一个简单 demo

from appium import webdriver
desired_caps = {
            'platformName': 'Android',
            'fastReset': 'false',
            'noReset': True,
            'platformVersion': '7.0',
            'deviceName': '58d1a05c',
            'appPackage': 'com.tencent.mm',
            'appActivity': 'com.tencent.mm.ui.LauncherUI',
            'fullReset': 'false',
            # 'unicodeKeyboard': 'True',
            # 'resetKeyboard': 'True',
            'chromeOptions': {
                'androidProcess': 'com.tencent.mm:appbrand0'
                }
            }
driver = webdriver.Remote('http://0.0.0.0:4723/wd/hub', desired_caps)
driver.find_element_by_android_uiautomator('text("微信")').click() #点击微信Tab
# 定义一个滑动屏幕的方法
def swipeDown(t):
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    x1 = int(x * 0.5)  # x坐标
    y1 = int(y * 0.25)  # 起始y坐标
    y2 = int(y * (0.25 + t))  # 终点y坐标
    driver.swipe(x1, y1, x1, y2, 500)
swipeDown(0.4) # 向下滑动屏幕的40%,准备从顶部进入小程序
driver.find_element_by_android_uiautomator('text("天天连连线")').click() #点击顶部的图标进入小程序
print driver.contexts  # 打印当前所有的上下文
# [u'NATIVE_APP', u'WEBVIEW_com.tencent.mm:appbrand0', u'WEBVIEW_com.tencent.mm:support', u'WEBVIEW_com.tencent.mm:tools', u'WEBVIEW_com.tencent.mm:appbrand1']
driver.switch_to.context('WEBVIEW_com.tencent.mm:appbrand0') #切换上下文为WEBVIEW_com.tencent.mm:appbrand0
driver.find_element_by_xpath("/html/body/wx-view/wx-view[4]/wx-form/span/wx-button").click() # 这个是HTML页面的元素

最后关于 switch_to.context 上下文切换的问题,我想说一下的就是,最开始自己用的一个乐视超级手机,想操作 webview 页面,切换上下文偶尔切换成功,这个偶尔很致命,找了很久没找到原因,然后不经意间换了一台小米手机,代码没变,但切换失败?不存在的。
还有就是自己看过不少 appium 操作 webview 的文章,基本都是说操作 webview 前要切换上下文,有些说划重点说不需要切换 webview,我亲身感受是,是的,有些 webview 元素不切换也可以操作,但是有些 webview 不切换就操作不了,坑挺多的。建议就是操作 H5 前首先确认chromedriver 版本对应,不切上下文能操作就不切 (因为个人觉得 native 稳定一点),切了上下文还不好使,那就换手机试试吧。

欢迎交流指正,感谢阅读。


↙↙↙阅读原文可查看相关链接,并与作者交流