Appium 使用 appium 进行微信小程序的自动化测试

思寒_seveniruby · 2017年01月10日 · 最后由 TesterWa 回复于 2023年01月29日 · 14412 次阅读
本帖已被设为精华帖!

微信小程序结构

其实微信小程序不过是正常的 webview 而已. 只是产品概念上的不同. 本质还是 h5.
所以用 appium 是可以进行自动化的.

以我们美团外卖为例. 查看结构就可以看到小程序的 dom 结构.

欢迎大家使用美团外卖小程序 (此处应有广告词)

自动化用例的调整

  • webview 的进程名是 com.tencent.mm:appbrand1
  • webview 的 element 需要通过 devtool 等工具进行分析

具体的细节可参考我之前写过 微信 webview 的自动化技术

示例代码

简单写个 demo 给大家. 我本地是测试通过的. 代码是 scala. 大家自行用自己的语言去实现吧.
关键就是那句

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

测试用例代码

test("测试微信小程序") {
  val capability = new DesiredCapabilities()
  capability.setCapability("app", "")
  capability.setCapability("appPackage", "com.tencent.mm")
  capability.setCapability("appActivity", ".ui.LauncherUI")
  capability.setCapability("deviceName", "emulator-5554")
  capability.setCapability("fastReset", "false")
  capability.setCapability("fullReset", "false")
  capability.setCapability("noReset", "true")
  capability.setCapability("automationName", "appium")
  capability.setCapability("platformName", "android")

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

  val url = "http://127.0.0.1:4723/wd/hub"
  val driver = new AndroidDriver[WebElement](new URL(url), capability)
  driver.findElementByXPath("//*[@text='发现']").click
  driver.findElementByXPath("//*[@text='小程序']").click
  driver.findElementByXPath("//*[contains(@text, '美团外卖')]").click
  println(driver.getContextHandles)
  driver.context("WEBVIEW_com.tencent.mm:tools")
  Thread.sleep(5000)
  println(driver.getPageSource)
  driver.findElementByXPath("//*[contains(@url, '美食')]").click()
  driver.findElementByXPath("//*[contains(., '金百万')]").click()
}

后记

这是行业第一篇用 appium 进行微信小程序的自动化测试的例子.
转载请注明出自 testerhome 测试社区和原链 https://testerhome.com/topics/7053

TesterHome 微信小助手

TesterHome 微信公众号

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 56 条回复 时间 点赞

谢谢思寒分享,果断收藏

感谢思寒分享,神速啊👍

神速呐,👍

刚刚我还留言,说思寒分享过微信的测试,对小程序应该是没有问题的,没想到这么快就出成果了。。

#4 楼 @lose 抢个首发帮社区宣传下. 😀

666,刚打算写个~~

#6 楼 @joe_blue 写一个玩玩,用 macaca 可以不?

谁打赏的 20 啊, 谢谢啦. 告诉我小数点后的数字让我认识下土豪

#8 楼 @seveniruby 手工赞一个。 话说我上次打赏了一篇你的文章,是不是没收到提示啊

#10 楼 @jet 收到了. 目前不知道是谁打赏的. 所以只能问. 年后和恒温改进下. 正式支持下微信支付就好了

#6 楼 @joe_blue 你可以试试,尝试了 2 小时发现 macaca 不支持 chromeoptions 自定义参数,或许是我没整对,提了个 issue 给 macaca

这个真心要点赞

—— 来自 TesterHome 官方 安卓客户端

@seveniruby 楼主 appbrand1 和 appbrand2 appbrand3 这个是解释一下么 做微信自动化的时候 MAC 端需要启动 chrmedriver 吗 端口不设置要紧吗 ?

@seveniruby
代码如下:driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'美团外卖 +')]").click()
print driver.contexts

driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {'name': 'WEBVIEW_com.tencent.mm.tools'})

driver.context('WEBVIEW_com.tencent.mm:tools')
driver.find_element_by_xpath("//span[text() = '我的']").click()
报错:
[u'NATIVE_APP', u'WEBVIEW_com.tencent.mm:appbrand1', u'WEBVIEW_com.tencent.mm:tools']
Traceback (most recent call last):
File "D:/AutoTestStudy/pythonstudy/H5Test.py", line 90, in
driver.context('WEBVIEW_com.tencent.mm:tools')
TypeError: 'unicode' object is not callable

#15 楼 @si509429 python 编程的问题, 你自己查吧

今天按照@seveniruby 的方式尝试了一下,发现:
options.setExperimentalOption("androidProcess", "com.tencent.mm:appbrand2");//小程序
这里的 appbrand2 好像不是固定的,是不是和微信上添加了几个小程序有关呢?
另外,切换 context 的时候,是不是要使用:
driver.context("WEBVIEW_com.tencent.mm:appbrand2");
而不是:
driver.context("WEBVIEW_com.tencent.mm:tools");

在我的一个酷派手机上,这样操作才能执行成功

切换过去就没反应了,webvies 的东西操作不了,连 System.out.println("2222222"); 也打印不出来.用的是 java
代码:
dr.findElementByXPath("//[@text='小程序']").click();
dr.findElementByXPath("//
[contains(@text, 'money 计算器')]").click();
Thread.sleep(5000);
Set contexts = dr.getContextHandles();
for (String contextName : contexts) {
System.out.println(contextName);
}
dr.context("WEBVIEW_com.tencent.mm:appbrand0");
System.out.println("2222222");

#17 楼 @levinzhang1981 appbrand2 确实跟添加小程序的个数有关

46楼 已删除

#20 楼 @knight80829 广告内容, 删除

#18 楼 @ort886 已解决,chromedriver 的问题

思寒_seveniruby 将本帖设为了精华贴 01月12日 19:24

@ort886 chromedriver 的什么问题,如何解决的?

@ort886 我 chromedriver 提示 chrome not reachable 是什么情况?

@ort886 我 chrome not reachable 的问题解决了 现在就是跟你一样 切进去了 没任何反应 一会后元素点击报错... 我的 chromedriver2.25 chrome 版本 54 请问你怎么解决了?

@seveniruby 楼主 有个疑问 你 androidProcess 配置 填的是"com.tencent.mm:appbrand1" 为什么 driver.context("WEBVIEW_com.tencent.mm:tools") 而不是 driver.context(“com.tencent.mm:appbrand1”)?

我切换成功
[debug] [JSONWP Proxy] Proxying [GET /status] to [GET http://127.0.0.1:8000/wd/hub/status] with no b
ody
[debug] [JSONWP Proxy] Got response with status 200: "{\"sessionId\":\"\",\"status\":0,\"value\":{\"
build\":{\"version\":\"alpha\"},\"os\":{\"arch\":\"x86_64\",\"name\":\"Windows NT\",\"version\":\"6.
1.7601 SP1\"}}}"
[debug] [JSONWP Proxy] Proxying [POST /session] to [POST http://127.0.0.1:8000/wd/hub/session] with
body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.tencent.mm","androidUseRunningA
pp":true,"args":[],"androidProcess":"com.tencent.mm:appbrand0","extensions":[],"androidDeviceSerial"
:"ZX1G4294SH"}}}
[debug] [JSONWP Proxy] Got response with status 200: {"sessionId":"83a43f95f4d58aaa08c13278d617eb15"
,"status":0,"value":{"acceptSslCerts":true,"applicationCacheEnabled":false,"browserConnectionEnabled
":false,"browserName":"chrome","chrome":{"chromedriverVersion":"2.26.436362 (5476ec6bf7ccbada1734a0c
dec7d570bb042aa30)"},"cssSelectorsEnabled":true,"databaseEnabled":false,"handlesAlerts":true,"hasTou
chScreen":false,"javascriptEnabled":true,"locationContextEnabled":true,"mobileEmulationEnabled":fals
e,"nativeEvents":true,"pageLoadStrategy":"normal","platform":"ANDROID","rotatable":false,"takesHeapS
napshot":true,"takesScreenshot":true,"unexpectedAlertBehaviour":"","version":"37.0.0.0","webStorageE
nabled":true}}
[debug] [Chromedriver] Changed state to 'online'
[debug] [MJSONWP] Responding to client with driver.setContext() result: null
[HTTP] <-- POST /wd/hub/session/9a81663a-b01d-4846-90e0-779e160c4644/context 200 5078 ms - 76、

但是找元素时候提示这个

[debug] [JSONWP Proxy] Got response with status 200: {"sessionId":"83a43f95f4d58aaa08c13278d617eb15"
,"status":7,"value":{"message":"no such element: Unable to locate element: {\"method\":\"xpath\",\"s
elector\":\"//*[text()='机票']\"}\n (Session info: webview=37.0.0.0)\n (Driver info: chromedriver=
2.26.436362 (5476ec6bf7ccbada1734a0cdec7d570bb042aa30),platform=Windows NT 6.1.7601 SP1 x86_64)"}}

原因大概知道了,去哪儿出行页面显示很丰富,但是 getsource 看到 body 是空的
😂 😂 😂 😂 😂 😂 😂 😂 ,所以 xpath 什么也找不到
**


@seveniruby

楼主的例子能成功执行?还是只是提供一个思路

美团外卖首页,getsource ,也是


楼主是如何定位元素的
chrome://inspect/#devices 显示的元素能定位么

我试了这么多,source 的数据都是

形式的,这样的话不能支持自动化,还是我的方式错了

adfghzhang Macaca 微信公众号、小程序实践 中提及了此贴 01月17日 11:44
fir.im CI Weekly #12 | 微信小程序的自动化测试进阶 中提及了此贴 01月19日 10:57

#22 楼 @ort886 ChromeDriver 换成什么版本了?

我使用 contextNames = driver.getContextHandles(); 获取的只有 NATIVE_APP 一个,没有 WebView 相关的成员, 这个问题各位是怎么解决的,@seveniruby


请问楼主,这两种写法的区别是什么?

29楼 已删除
回复

contains 是包含的意思,这样 ‘美团外卖’ 四个字前或末尾有图标或字符时也可以被找到

Baozhida 回复

我也遇到了和你一样的问题,切是切过去了,但获取元素的时候就报错,不知道你解决了没?

请教下,已经切换到 webview,但是找不到元素,是怎么回事啊,谢谢

package com.demo;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.NoSuchContextException;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.MobileCapabilityType;

import java.io.File;
import java.net.URL;
import java.util.Set;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.Assert;
import org.testng.annotations.Test;

public class Demo {

@Test
public static void startapp() throws Exception{
AppiumDriver driver;

DesiredCapabilities capabilities=new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");

capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "127.0.0.1:21503");
// capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "192.168.154.101:5555");

capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "5.1.1");
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");

//启动应用的包名
capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.tencent.mm");
//启动应用的起始 ACTIVITY
capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY,".ui.LauncherUI");
//支持中文输入
capabilities.setCapability("unicodeKeyboard", "True");
//重置输入法为系统默认
capabilities.setCapability("resetKeyboard", "True");

ChromeOptions options = new ChromeOptions();
// options.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
options.setExperimentalOption("androidProcess", "com.tencent.mm:appbrand0");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);

// DesiredCapabilities option = new DesiredCapabilities();
// option.setCapability("androidProcess", "com.tencent.mm:appbrand0");
// capabilities.setCapability(ChromeOptions.CAPABILITY, option);

driver=new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
Thread.sleep(5000);
System.out.println("启动 app 成功");
Thread.sleep(5000);

driver.findElementByXPath("//[@text='发现']").click();
driver.findElementByXPath("//
[@text='小程序']").click();
Thread.sleep(2000);

// driver.findElementByXPath("//*[contains(@text, '京东购物')]").click();
// Thread.sleep(5000);
//

// try{
// Set contexts = driver.getContextHandles();
// for (String context : contexts) {
// //打印出来看看有哪些 context
// System.out.println(context);
// }
// driver.context("WEBVIEW_com.tencent.mm:appbrand0");
// }catch(NoSuchContextException nce){
// Assert.fail("没有这个 context:");
// }
// Thread.sleep(5000);
// driver.findElementByXPath("//span[contains(text(), '领优惠券')]").click();

// ---------------------------------------------------------------------------------------
driver.findElementByXPath("//*[contains(@text, '美团外卖')]").click();
Thread.sleep(5000);

try{
Set contexts = driver.getContextHandles();
for (String context : contexts) {
//打印出来看看有哪些 context
System.out.println(context);
}
driver.context("WEBVIEW_com.tencent.mm:appbrand0");
}catch(NoSuchContextException nce){
Assert.fail("没有这个 context:");
}

Thread.sleep(5000);
driver.findElementByXPath("//[contains(@url, '美食')]").click();
driver.findElementByXPath("//
[contains(., '金百万')]").click();

Thread.sleep(2000);
driver.quit();

}
}

App 更换了腾讯的 X5 浏览器内核,获取不到元素,该怎么解决呢

@chenxin 获取不到元素的问题 你解决了么

Baozhida 回复

哥们 跟你一样 可以切换到这也页面就是拿不到 div 里面的元素 现在你解决了吗

wangmcn 回复

你好,我也是用 java 写,参考你的代码我无法在真机上进入微信,小白求助~

public void setUp() throws Exception {
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "/Mall/src/main/java/apps/");
File app = new File(appDir, "weixin_1280.apk");

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("app",app.getAbsolutePath());

capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "DU2SSE15AH117303");
capabilities.setCapability("platformVersion", "4.4.2");

//将上面获取到的包名和 Activity 名设置为值
capabilities.setCapability("appPackage", "com.tencent.mm");
capabilities.setCapability("appActivity", ".ui.LauncherUI");

//支持中文
capabilities.setCapability("unicodeKeyboard" ,"True");
//capabilities.setCapability("resetKeyboard", "True");

//重签名
capabilities.setCapability("noSign","True");

capabilities.setCapability("sessionOverride", true);

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

driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub,capabilities"));
}

相同的代码两次执行不同的结果


@seveniruby 思寒,这个问题一直解决不了,能帮我看看吗?

debug 了一下,发现了问题~~~~
如下图,webview 是切换了,没问题,关键是切换后有两个句柄,遇到相同问题的同学可以注意一下。

现在这个方案应该不可行了吧?因为已经无法通过 chromedriver 拿到小程序的 webview

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("app","");
capabilities.setCapability("appPackage","com.tencent.mm");
capabilities.setCapability("appActivity", ".ui.LauncherUI");
capabilities.setCapability("deviceName","S889PBJR99999999");
capabilities.setCapability("fastReset","false");
capabilities.setCapability("fullRest","false");
capabilities.setCapability("noRest","true");
capabilities.setCapability("automationName","Appium");
capabilities.setCapability("platformName","Android");
capabilities.setCapability("platformVersion","5.1");
capabilities.setCapability("recreateChromeDriverSessions", "True");

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

AndroidDriver driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);

//等待元素加载出来
Thread.sleep(5000);
driver.findElement(By.xpath("//*[@text='发现']")).click();
int width = driver.manage().window().getSize().width;
int height = driver.manage().window().getSize().height;
Thread.sleep(2000);
driver.swipe(width /2, height / 4 + 200,width / 2,height / 4,200);
Thread.sleep(2000);
driver.findElement(By.xpath("//*[@text='小程序']")).click();
Thread.sleep(2000);
driver.findElement(By.xpath("//*[@text='京东秒杀']")).click();
System.out.println("所有上下文" + driver.getContext());
System.out.println("所有句柄" + driver.getContextHandles());
driver.context("WEBVIEW_com.tencent.mm:tools");
Thread.sleep(6000);
System.out.println("已经进入webview");
System.out.println(driver.getPageSource());
System.out.println(driver.getContext());
driver.quit();

切换微信小程序的 webview 的时候报错 我真的很疑惑,楼主帮帮我

haleli 回复

我也觉得是这样 我昨天尝试切换上下文但是始终切换不过去

Tank 回复

我现在一切都 OK 的,就是拿不到页面元素。

15楼 已删除
kukaka 回复

现在测试是 ok 的 只要能调试微信的小程序的页面就可以对小程序做自动化了,你有什么难题 我可以帮助你 踩了好多坑😀

报错:

已尝试解决方案:
1.关闭代理,不可行
2.换 appium 下的 chrome 版本,使之与手机浏览器内核一致,不可行
3.加代码 ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess","WEBVIEW_com.tencent.mm:tools");
capabilities.setCapability("ChromeOptions", options);混合 app 通过,微信自动化仍然报错
4.注释 android-hybrid.js 相关语句,不可行
求大神解决!!!

报错:

已尝试解决方案:
1.关闭代理,不可行
2.换 appium 下的 chrome 版本,使之与手机浏览器内核一致,不可行
3.加代码 ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidProcess","WEBVIEW_com.tencent.mm:tools");
capabilities.setCapability("ChromeOptions", options);混合 app 通过,微信自动化仍然报错
4.注释 android-hybrid.js 相关语句,不可行
求大神解决!!!

Tank 回复

你好,请问如果是别的 app(不是 wechat),如何设置 androidProcess 呢?我获取的 webview 进程名只是"WEBVIEW_chrome"

启动了 chromedriver 之后就无法启动 adb,有没有人遇到过

Tank 回复

你好,Chromedriver 启动了就无法启动 adb,不知道你有没有遇到过

info: [debug] ["WEBVIEW_com.tencent.mm:appbrand0","WEBVIEW_com.tencent.mm:appbrand1","WEBVIEW_com.tencent.mm:support","WEBVIEW_com.tencent.mm:tools"]

info: [debug] Available contexts: NATIVE_APP,WEBVIEW_com.tencent.mm:appbrand0,WEBVIEW_com.tencent.mm:appbrand1,WEBVIEW_com.tencent.mm:support,WEBVIEW_com.tencent.mm:tools
info: [debug] Connecting to chrome-backed webview
info: Set chromedriver binary as: C:\Program Files (x86)\Appium\node_modules\appium\build\chromedriver\windows\chromedriver.exe
info: Killing any old chromedrivers, running: FOR /F "usebackq tokens=5" %a in (netstat -nao ^| findstr /R /C:"9515 ") do (FOR /F "usebackq" %b in (TASKLIST /FI "PID eq %a" ^| findstr /I chromedriver.exe) do (IF NOT %b=="" TASKKILL /F /PID %a))
info: No old chromedrivers seemed to exist
info: Spawning chromedriver with: C:\Program Files (x86)\Appium\node_modules\appium\build\chromedriver\windows\chromedriver.exe --url-base=wd/hub --port=9515
info: [CHROMEDRIVER STDOUT] Starting ChromeDriver 2.35.528161 (5b82f2d2aae0ca24b877009200ced9065a772e73) on port 9515
Only local connections are allowed.
info: Proxying [GET /status] to [GET http://127.0.0.1:9515/wd/hub/status] with no body
info: Got response with status 200: {"sessionId":"","status":0,"value":{"build":{"version":"alpha"},"os":{"arch":"x86_64","name":"Windows NT","version":"10.0.16299"}}}
info: Proxying [POST /session] to [POST http://127.0.0.1:9515/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"com.tencent.mm","androidUseRunningApp":true,"androidDeviceSerial":"98d0f5b6"}}}
info: Got response with status 200: {"sessionId":"e46dab3cfa7d7d8a585ed7424fb2e70e","status":13,"value":{"message":"unknown error: Failed to run adb command, is the adb server running?\n (Driver info: chromedriver=2.35.528161 (5b82f2d2...

Tank 回复

你好,以美团外卖小程序为例,如果在 NATIVE_APP 情况下 (不切换 webview 进入小程序反而可以识别对象),用 driver.find_element_by_xpath("//*[contains(@content-desc,'美食')]").click() 可以发现对象并点击。

但是如果在进入小程序后,切换到 WEBVIEW_com.tencent.mm:appbrand1(我觉得应该是切换成功的 appium log: [debug] [Chromedriver] Changed state to 'online'),用 chrome://inspect/#devices 得到 “美食” 的 xpath,然后
driver.find_element_by_xpath("/html/body/wx-view/wx-view/wx-swiper[1]/div/div[1]/div/wx-swiper-item[1]/wx-view[1]").click() 就会报错找不到对象。

请问:

  1. WEBVIEW_com.tencent.mm:appbrand1 和 WEBVIEW_com.tencent.mm:appbrand0 有什么区别吗?
  2. 是我 context 切换错了吗?应该切换成哪个 context 代表的是小程序?不过 0 和 1 我都试过了都找不到对象
  3. 你说的:“只要能调试微信的小程序的页面就可以对小程序做自动化了” 是指能用 uiautomatorviewer 得到小程序页面元素吗?但是我发现 uiautomatorviewer 不是所有 webview 的元素都可以识别。
匿名 #7 · 2018年09月13日
meizifighting 回复

你好,为什么你的 contexts 这么多,感觉又小程序的,我的只有三个:
Available contexts: ["NATIVE_APP","WEBVIEW_com.tencent.mm:toolsmp","WEBVIEW_com.tencent.mm:tools"]
我切换到 webveiw,是微信打开 H5 的 webview,不是小程序的 webview,怎么弄

想问一下各位大大 现在这种方案还可行吗 我看文章发表的时间是 17 年 1 月,已经一年多过去了

hello 小程序测试 Appium 支持 Java-Client6+ 解决方案 中提及了此贴 11月12日 19:36

我也是切换成功以后,获取不到页面的元素,切换页面的 current_context,里面都是 CSS 的内容。

求助!
无法找到小程序底部导航栏的元素,导致无法切换,所有 contexts、handles 都循环切换过、试过了,还是找不到。
用 chrome://inspect 工具打开小程序页面 也是不显示这个导航栏,只显示导航栏上面的页面,不知道是小程序本身的问题还是其他原因导致的。
page_source 也只能看到导航栏【首页】里的页面元素。

回复内容未通过审核,暂不显示
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册