Appium 微信小程序 webview 自动化测试介绍

小飞哥 · 2018年09月12日 · 最后由 小小阿狸、 回复于 2019年02月01日 · 5799 次阅读

前言

最近研究搭建了微信小程序的自动化测试方法和框架,本篇纯为总结篇。

一、运行环境
appium1.6.5
jdk1.8
nodejs 8.9.4
chromedriver 2.26
android 6.0
android system webview 55
微信版本 6.7.2

1、环境搭配关系
appium 版本需要与 android sdk、nodejs 版本匹配,android system webview 版本需要与 chromedriver 版本、微信版本匹配,jdk 版本主要与工程 jar 包的版本匹配。一般情况下高版本兼容低版本,要使用高版本的 appium,那就需要匹配高版本的 android sdk 和 nodejs,道理一样,android 系统版本高, android system webview 版本自然也会高, 要测试微信应用,关键得看 chromedriver 版本。
2、查看软件版本
jdk:cmd –java –version

appium server:cmdappium –version

appium-desktop:安装了 appium-desktop 版本后,版本号自然就会看到
nodejs:cmd  node –v

android system webview:手机设置 –应用管理 –全部应用,找到 Android System WebView 查看应用信息
其它 chrome 浏览器版本、微信版本、android 系统版本如何查看不再介绍。

二、Webview
1、什么是 webview?
Webview 是用来展示网页的 view 组件,使用 webkit 渲染引擎来展示内容,可以简单理解为手机中的一个高性能内核浏览器的组件,微信自带浏览器用的是 QQ 浏览器 X5 内核,因此小程序依赖于微信存在,自然会涉及到 webview。
要想调试 webview 页面,需要先打开 x5 内核调试开关
2、如何打开 x5 内核调试开关?
在微信任意聊天窗口输入 debugx5.qq.com,打开页面勾选 ‘打开 TBS 内核 Inspector 调试功能’,重启后自动生效

3、查看 webview 页面元素的三种方法
3.1、 chrome 浏览器访问 chrome://inspect
打开 chrome 浏览器,访问 chrome://inspect,此时会看到目前手机访问的 webview 页面,从图中可以看到 com.tencent.mm 进程下有 2 个 handle,而括号中标记的数字则代表当前系统的 chrome 版本号

点击 inspect,则可查看到打开的 webview 页面元素(此方法需要 google*
附 如何

方法一:在 C:\Windows\System32\drivers\etc\hosts 文件中添加配置
61.91.161.217 chrome-devtools-frontend.appspot.com
61.91.161.217 chrometophone.appspot.com
方法二:使用
软件,例如:*
3.2、 通过高版本的 appium 查看
启动 appium 服务(以 appium1.6.5 为例),点击 start new version


选择一个添加好的设备,Start Session,接下来的查看方法就跟 uiautomator 一样了
3.3、 使用腾讯 TBS 调试工具
具体安装与调试详见:https://x5.tencent.com/tbs/guide/debug/season1.html
安装后调试页面如图

附 chromedriver 与 chrome 版本映射关系

chromedriver 下载链接:
https://chromedriver.storage.googleapis.com/index.html

http://npm.taobao.org/mirrors/chromedriver/
根据映射关系,不同的 chrome 版本下载不同的 chromedriver

三、小程序
写测试代码之前,先要学会如何查看小程序在微信中的运行进程
1、如何查看小程序进程?
我们分别在打开微信不打开小程序和打开微信并打开小程序两种情况下查看当前活动的进程


通过以上可以看到,打开小程序后当前活动的进程号为 7671,查看 7671 对应的进程是 com.tencent.mm:toolsmp,因此 toolsmp 就是
2、ChromeOptions 设置
上面我们查看到当前小程序的活动进程是 com.tencent.mm:toolsmp,因此 toolsmp 就是 ChromeOptions 中的要设置的值。
具体在初始化 driver 时要添加如下代码:
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess", "com.tencent.mm:toolsmp");
caps.setCapability(ChromeOptions.CAPABILITY, options);

四、测试脚本
测试中我用的 jar 包版本为 java-client 5.0、selenium 3.0

话不多说直接上代码:
1、初始化 driver
private AndroidDriver driver;

@BeforeMethod
public void beforeMethod() {
try {
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(MobileCapabilityType.DEVICE_NAME, "A2J0215C25003726");
caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 600);
caps.setCapability(AndroidMobileCapabilityType.NO_SIGN, true);
caps.setCapability(AndroidMobileCapabilityType.UNICODE_KEYBOARD, true);
caps.setCapability(AndroidMobileCapabilityType.RESET_KEYBOARD, true);
caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.tencent.mm");
caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".ui.LauncherUI");
caps.setCapability(MobileCapabilityType.NO_RESET, true);
caps.setCapability(AndroidMobileCapabilityType.RECREATE_CHROME_DRIVER_SESSIONS, true);
// File chromedriver = new File("D://mywork//autotest//chromedriver//chromedriver(2.20).exe");
// caps.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE, chromedriver.getAbsolutePath());
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess", "com.tencent.mm:toolsmp");
caps.setCapability(ChromeOptions.CAPABILITY, options);
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), caps);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}

Chromedriver 如何使用?
初始化 driver 时,加载 chromedriver 有两种方法:
方法一:打开 appium 路径 D:\software\Appium\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win,将下载好的 chromedriver.exe 替换旧的 chromedriver.exe
方法二:在测试代码中添加 chromedriver 文件引用

2、测试代码
建议进入小程序的入口为:微信发现—搜一搜—小程序

以上测试代码无需讲解,唯一需要注意的一点就是进入到小程序,切换到小程序 context 后,还需要切换到当前的 windowHandle,windowHandle 切换成功,正确的 webview 页面自然就能找到
执行后查看获取到的页面源码,此处正是我要找的小程序页面,说明页面查找、切换成功

接下来就可以愉快的开发你的第一个小程序自动化脚本了。
测试过程中如有任何疑问,欢迎探讨~ Q 641023468 v suizhibian015

共收到 20 条回复 时间 点赞

楼主请问一下,我这个为什么无法启动微信程序?跟 chromedriver 有关系吗?手机端需要安装 chrome 浏览器吗?
微信版本 6.7.2
java-client 6.1.0
chromedriver 2.29
java 语言

homer 回复

是的,手机也要安装 chrome 浏览器

小飞哥 回复

试了下 5.0.0 是没问题的,6.1.0 就是不行,请问楼主有解决方案吗?

homer 回复

无法启动是报错了吗?有没有日志?我这边 java-client 6.0 都是没问题的,启动微信主要是这两句代码:
caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.tencent.mm");
caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".ui.LauncherUI");
建议你把手机上安装过的 appium setting 和 unlock 这两个 apk 手动卸载掉再重新启动试一下

小飞哥 回复

感谢楼主回答,现在的问题是,我配置了
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess", "com.tencent.mm:toolsmp");
caps.setCapability(ChromeOptions.CAPABILITY, options);
如果手机上不安装 chrome 会直接报 session 的错误,如果手机上安装了 chrome,会直接把手机上的 chrome 打开,不会启动微信,
此时打印的 context 是 NATIVE_APP、CHROMIUM 这 2 个,无沦怎样操作,都不会出现我想要的 WEBVIEW_com.tencent.mm:toolsmp

环境:
java-client 6.1.0
chromedriver 2.29
java 语言
手机 chrome 是 67 版本

homer 回复

建议你把代码贴出来看下,直观判断
手机上安装了 chrome 执行时会打开 chrome 是因为你在初始化 driver 时添加了这一句:
caps.setCapability(MobileCapabilityType.BROWSER_NAME, "browser");
把这一句去掉应该就能解决问题你所说的 2 个问题

小飞哥 回复

感谢楼主解答,caps.setCapability(MobileCapabilityType.BROWSER_NAME, "browser") 这句提醒了我
发现是 java -client 6.1.0 在设置了
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess", "com.tencent.mm:toolsmp");
caps.setCapability(ChromeOptions.CAPABILITY, options) 后,会自动将 BROWSER_NAME 设置为 chrome,不知道是不是 bug

解决办法:
在添加完 caps.setCapability(ChromeOptions.CAPABILITY, options) 后,需要将浏览器重新设置为空 caps.setBrowserName("");
这样就可以吊起微信了! 再次感谢楼主耐心解答!!!

homer 回复

请问代码在哪添加,我的连接之后,打开 chrome,地址栏输入 chrome://inspect/#devices,我打开的是微信小程序,看不到设备或者访问的资源,打开手机谷歌的话,才有一个 Chrome 显示,也没有显示小程序的 Webview 页面

z1073336883 回复

1、浏览器看不到设备或访问资源
确保打开 x5 内核调试开关
2、代码添加位置

匿名 #11 · 2018年10月30日

楼主我这个小程序首页能获取到元素,也能通过 claseename 点击,但是跳转到小程序的第二个页面的时候,不知道怎么切换 windowhandles,可以解答一下吗?

通过 driver.context("WEBVIEW_xxx");切换到小程序的 webview,要是在小程序的内部页面间操作还需要继续切换 window_handle,窗体切换只存在上一个页面和当前页面的概念,比如使用下面两种方式切换 window_handle
// 切换到小程序的当前页的 windowhandle
public void switch_window_to_xcx(AndroidDriver driver) {
// 切换 windowHandle
Set winHandles = driver.getWindowHandles();
List list = new ArrayList(winHandles);
driver.switchTo().window(list.get(1).toString());
}
// 切换到小程序的第一个 windowhandle
public void switch_window_to_first(AndroidDriver driver) {
// 切换 windowHandle
Set winHandles = driver.getWindowHandles();
List list = new ArrayList(winHandles);
driver.switchTo().window(list.get(0).toString());
}

org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: The desired should not include both of an 'appPackage' and a 'browserName'
Build info: version: '3.8.1', revision: '6e95a6684b', time: '2017-12-01T19:05:32.194Z'
System info: host: 'BAC1600674', ip: '30.39.52.46', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_181'
Driver info: driver.version: AndroidDriver

楼主,我加上这 3 行,就会报如上的错误,是因为 selenium 的版本问题吗

ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess", "com.tencent.mm:appbrand1");
capability.setCapability(ChromeOptions.CAPABILITY, options);

我从 webview 切换回 native 后,再次切换到 webview,日志:Found existing Chromedriver for context 'WEBVIEW_com.tencent.mm:appbrand0',然后 appium 长时间无响应,请问有遇到过这样的问题么?

lofbat 回复

已解决,增加配置 recreateChromeDriverSessions=true 后解决,现在 appium 再次获取已存在的 chromedriver session 似乎是有个 bug,有没英语好的大佬去提个 issue

sukie 回复

include both of an 'appPackage' and a 'browserName' ,这两个属性不能同时配置,chromedriver 中会自动配置这条属性,需要手动配置为空

chromeOptions.setCapability("browserName","");
lofbat 回复

谢谢了!手动配置为空后确实不会报错了 (o゚▽゚) o

我使用的 appium 是 v1.8.1 的
appium-desktop v1.8.1
java-client-5.0.0
selenium-server-standalone-3.8.1
小白想请教一下,为什么需要用到这段代码切换到小程序的 contexts 和当前 handles 吖。我切的时候报错了,不切直接继续写脚本操作小程序,反而没有问题,所以可以直接不切吗。
Set contexts = driver.getContextHandles();
for(String s : contexts) {
System.out.println("当前 contexts:"+s);
}
driver.context("WEBVIEW_com.tencent.mm:toolsmp");
Set windowsHandles=driver.getWindowHandles();
for(String s : windowsHandles) {
System.out.println("当前 Handles:"+s);
driver.switchTo().window(s);
Thread.sleep(2000);
}

appium -v

driver.find_element_by_id("com.tencent.mm:id/ekn").send_keys("摩拜单车")
微信的 send_keys 无效

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册