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

小飞哥 · September 12, 2018 · Last by 小小阿狸、 replied at February 01, 2019 · 7994 hits

前言

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

一、运行环境
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、代码添加位置

楼主我这个小程序首页能获取到元素,也能通过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无效

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up