Appium 小程序测试 Appium 支持 Java-Client6+ 解决方案

hello · 2018年11月12日 · 最后由 hello 回复于 2019年08月20日 · 2598 次阅读

入门踏坑

人类历史上第一篇小程序测试布道贴 使用 appium 进行微信小程序的自动化测试推出至今,已有近两年时间了。而我们才刚刚研究小程序测试,谁知道刚还没入门,就从踏坑开始了,也怪我为了兼容 IOS 测试,升级了 Java-Client.jar。17 年至今 Appium,Java-Client 也发行好几个版本了,肯定有不少人升级了 Java-Client.jar 到 6+,升级后应该会遇到小程序测试时报异常。Python,和使用 Java-Client5 没有问题。Log 我就不贴了,不服升级一下 Appium 和 Java-Client 到最新版试试。

异常调查

发生异常后,分别使用 Python 和 Java 用不同的版本做了测试分析。发现 Py 一直是可以的,用最新的 pyClient,和上一个版本都没有问题的。Java 的 Client 升级到 5.0.4 后就开始报错了。明明代码里没有设置 browserName 选项,但是程序运行时,会自动化启动谷歌浏览器,然后小程序测试就异常了。以下是 Java Client 不同版本的调查结果。

  • Java Client 5.0.0 --> selenium-java 3.5.2 --> OK

  • Java Client 5.0.1 --> selenium-java 3.5.2 --> OK

  • Java Client 5.0.2 --> selenium-java 3.5.3 --> OK

  • Java Client 5.0.3 --> selenium-java 3.5.3 --> OK

  • Java Client 5.0.4 --> selenium-java 3.6.0 --> Error

  • Java Client 6.0.0 --> selenium-java 3.12.0 --> Error

场外求助

经过调查,确定以及肯定不是我代码程序的问题,因为同样的设置 Py 和低版本的 Java-Client 都可以正常运行。只好跑去用撇脚的英语给 Appium 提 ISSUE 了😂

不得不说 Appium 的团队还是很热心的,提供 log 后,很快得到了回应。非常感谢他们开源贡献!

Selenium 的坑

Appium 的大神说这是 Selenium 的锅。已经有小伙伴去给 SeleniumHQ 提 Issue 了。不知道 SeleniumHQ 会不会认领这个锅,也不知道这个问题改正还需要多久。这里把大神给的方案贴一下,传递开源精神。

我的码,拿去不谢

环境:
1.Java-client : 6.1.0
2.Android System WebView : 57.0
3.chromedriver : 2.29
4.Appium server:1.8.1
5.Mobile : Android 6.0

package com.lvmama.testcase;

import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.MobileCapabilityType;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Set;

import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;

public class WeXinTest {

    static AndroidDriver<MobileElement> driver = null;

    public static void main(String[] args) throws Exception {


            DesiredCapabilities desired_capabilities = new DesiredCapabilities();
            ChromeOptions chrome_options = new ChromeOptions();
            chrome_options.setExperimentalOption("androidProcess", "com.tencent.mm:tools");

            desired_capabilities.setCapability(ChromeOptions.CAPABILITY, chrome_options);
            desired_capabilities.setCapability(AndroidMobileCapabilityType.PLATFORM, "Android");
            desired_capabilities.setCapability(AndroidMobileCapabilityType.VERSION, "6.0");
            desired_capabilities.setCapability("deviceName", "a6990c40");
            desired_capabilities.setCapability(MobileCapabilityType.FORCE_MJSONWP, true);
            desired_capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.tencent.mm");
            desired_capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "ui.LauncherUI");
            desired_capabilities.setCapability("showChromedriverLog", true);
            desired_capabilities.setCapability(AndroidMobileCapabilityType.AUTO_GRANT_PERMISSIONS, true);
            desired_capabilities.setCapability("noReset", true);
                desired_capabilities.setCapability(MobileCapabilityType.BROWSER_NAME,"");
            desired_capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator2");


        try {
            driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"),desired_capabilities);

            Thread.sleep(2000);
            driver.findElementByXPath("//*[@text='发现']").click();
            Thread.sleep(2000);
            driver.findElementByXPath("//*[@text='小程序']").click();
            Thread.sleep(2000);
            driver.findElementByXPath("//*[@text='驴妈妈门票预订']").click();
            Thread.sleep(5000);
            Set<String>  contextNames = driver.getContextHandles();
            for(String contextName : contextNames) {
            lvmama:if(contextName.contains("tencent.mm:appbrand0")){
                    driver.context(contextName);
                    Set<String> winHandles = driver.getWindowHandles();
                    for(String wid : winHandles) {
                        driver.switchTo().window(wid);
                        String source = driver.getPageSource();
                        if (source.contains("票")) {//好粗暴
                            break lvmama;
                        }
                    }
                }
            }
            Thread.sleep(5000);
            System.out.println(driver.getPageSource());


        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }
}

心得

ChromeOptions 的设置:chrome_options.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
这个"com.tencent.mm:tools"可以是 “com.tencent.mm:appbrand0” 但是设置成 “com.tencent.mm:appbrand1” 就不一定对了。

  • 设置时一定要看 Webview 的进程名,这个蛋疼的 appbrandX 的 X 是会变的,切莫生搬套用。
    当前 Webview 的进程名查看方法,详尽方法参考这个 使用 Appium 测试微信小程序 Webview

  • 进入小程序页面时要切上下文,老规矩看上一步,查清楚自己 Webview 的进程名

    if(contextName.contains("tencent.mm:appbrandX")){//appbrand0,appbrand1,appbrand2。。。都有可能。
    driver.context(contextName);
    }
    
  • 切完上下文,注意要切换 WindowHandle,判断确实是自己的页面再退出循环。(我这个判断是否进入自己页面用的是 getPageSource() 有点挫,不知道大家有啥好方法,欢迎留言讨论,谢谢)

    Set<String> winHandles = driver.getWindowHandles();
                    for(String wid : winHandles) {
                        driver.switchTo().window(wid);
                        String source = driver.getPageSource();
                                    if (source.contains("票")) {
                                   break;
    }
                        }
    

后记

现在各大门派都要搞小程序(BAT T..),我这还没入门就入坑了,大家有啥好方案,欢迎留言不吝赐教。最后感谢社区很多优秀的帖子给予参考,感谢 Appium 调查解决。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 10 条回复 时间 点赞
hello 2018 年 度个人测开账单 中提及了此贴 01月25日 18:37

升级 Java-Client6+ 后原来的 android 脚本运行成功不影响,iOS 运行打开应用后就报错了,排查了很久

阿三 回复

WDA 的问题好像,WAD 重新编译一下,试试看

hello 回复

github 上有人提出一样问题,我也尝试了各种 WDA 重新编译安装,都没有解决掉

阿三 回复

不应该啊,我这边升级后安卓/IOS 都可以的

12楼 已删除
hello 回复

已经解决!
如果在设备上缓存的先前 Appium 版本中存在过时的 WebDriverAgent,则通常会发生此异常。从设备中手动删除它并清除 Xcode 缓存
重新安装 appium 并使用 appium 附带的 WebDriverAgent

阿三 回复

👍

hello 回复

现在有个问题 uiautomator2 模式下,name 不支持安卓,iOS 可以(已改源码)

楼主的分享太棒啦,解决了我一天多没有解决的问题,非常感谢,
提个建议,可以根据 currentUrl 或者 getTile 定位是不是需要的 window,pagesourse 太慢啦

hello #12 · 2019年08月20日 Author
木头人 回复

currentUrl 或者 getTile 定位不错的选择

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