Appium测试微信小程序时报错

帖子内容

问题描述:使用Appium测试微信小程序时报错,在进入微信小程序之前的搜索小程序页面,获取pageSource就会报错,获取不了页面的元素

  • 环境:
  • 移动端型号:华为DUB-AL00
  • 移动端系统:Android 8.1.0
  • 微信版本:8.0.16
  • appium版本:1.22.0
  • 问题复述:打开微信向下滑动时,运行到这个搜索小程序页面时,想要定位该页面的取消元素时就报错
    image

报错Log

[debug] [W3C (759cdbdc)] io.appium.uiautomator2.common.exceptions.UiAutomator2Exception: Timed out after 15524ms waiting for the root AccessibilityNodeInfo in the active window. Make sure the active window is not constantly hogging the main UI thread (e.g. the application is being idle long enough), so the accessibility manager could do its work
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.utils.AXWindowHelpers.getActiveWindowRoot(AXWindowHelpers.java:79)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.utils.AXWindowHelpers.getCachedWindowRoots(AXWindowHelpers.java:117)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.model.internal.CustomUiDevice.findObject(CustomUiDevice.java:114)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.handler.FindElement.findElement(FindElement.java:82)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.handler.FindElement.safeHandle(FindElement.java:67)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:264)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:258)
[debug] [W3C (759cdbdc)]  at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
[debug] [W3C (759cdbdc)]  at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
[debug] [W3C (759cdbdc)]  at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
[debug] [W3C (759cdbdc)]  at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
[debug] [W3C (759cdbdc)]  at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
[debug] [W3C (759cdbdc)]  at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
[debug] [W3C (759cdbdc)]  at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
[debug] [W3C (759cdbdc)]  at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
[debug] [W3C (759cdbdc)]  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
[debug] [W3C (759cdbdc)]  at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
[debug] [W3C (759cdbdc)]  at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
[debug] [W3C (759cdbdc)]  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
[debug] [W3C (759cdbdc)]  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
[debug] [W3C (759cdbdc)]  at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
[debug] [W3C (759cdbdc)]  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
[debug] [W3C (759cdbdc)]  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
[debug] [W3C (759cdbdc)]  at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
[debug] [W3C (759cdbdc)]  at java.lang.Thread.run(Thread.java:784)

相关代码

public class SnowBallTest {

    public static AppiumDriver driver;

    public static WebDriverWait driverWait;

    public static int index = 0;

    @BeforeAll
    public static void setUp() throws MalformedURLException {
        DesiredCapabilities caps = new DesiredCapabilities();

        caps.setCapability("platformName", "Android");
        caps.setCapability("udid", "C2UBB19529202846"); //设备的id,与在线设备一致
        caps.setCapability("deviceName", "yy"); //可任意命名
        caps.setCapability("appPackage", "com.tencent.mm"); //启动app包名
        caps.setCapability("appActivity", "com.tencent.mm.ui.LauncherUI"); //启动的activity页面
        //caps.setCapability("unicodeKeyboard", true);
        //caps.setCapability("resetKeyboard", true);
        caps.setCapability("noReset", "true"); //是否在测试前后重置相关环境,可跳过启动页面弹框功能

        //1、设置正确webview的chromedriver
        caps.setCapability("chromedriverExecutable", "/Library/selenium/webDriver/chrome_2.40/chromedriver");

        //打印更多的chromedriver log便于定位问题
        caps.setCapability("showChromedriverLog", true);

        //2、设置ChromeOptions传递给chromedriver
        //因为小程序的进程名和包名不一致,需要加上这个参数
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.setExperimentalOption("androidProcess", "com.tencent.mm:appbrand0");
        caps.setCapability("goog:chromeOptions", chromeOptions);
        //必须得加上,因为默认生成browserName=chrome设置,需要去掉
        caps.setCapability("browserName", "");

        //todo: 3、设置adb proxy

        //建立session
        driver = new AndroidDriver<>(new URL("http://localhost:4723/wd/hub"), caps);

        //隐式等待
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        driverWait = new WebDriverWait(driver, 60);
        driverWait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//*[@text='通讯录']")));
    }

    @Test
    void wxMicroApplication() {
        //获取窗口大小 向下滑动
        Dimension size = driver.manage().window().getSize();
        new TouchAction<>(driver)
                .longPress(LongPressOptions.longPressOptions()
                                .withDuration(Duration.ofSeconds(2))
                                .withPosition(PointOption.point(size.width / 2, size.height / 3)))
                .moveTo(PointOption.point(size.width / 2, size.height / 10 * 9))
                .release().perform();

        wait(ExpectedConditions.visibilityOfElementLocated(By.id("com.tencent.mm:id/nr")), 10).click();

       //getPageSource 会报错
        System.out.println(driver.getPageSource());
        wait(ExpectedConditions.visibilityOfElementLocated(By.id("com.tencent.mm:id/aib")), 10); //取消按钮

    }
}

代码地址:https://gitee.com/alice_yy/DemoWorkSpace/blob/master/AppiumTestDemo/src/test/java/com/demo/testcase/mini_app/SnowBallTest.java

分析

网上自己也找了一下原因,正好看到了思寒老师的帖子https://ceshiren.com/t/topic/14684,说是uiautomator2的一个bug,想确认一下是这个bug导致无法获取小程序的页面元素吗?
还有看到说是微信8以上版本导致的,由于真机不太方便降低微信版本测试,所以还未尝试该方法 https://developers.weixin.qq.com/community/develop/doc/00064e2c288520f14e0b5305c56400

是uiautomator底层的一个bug,需要给底层打补丁。这块的技术比较敏感,有些客户购买了我们的这块的技术,因为涉及商业技术秘密容易引发纠纷,我们不能开放。我这边只能给你几个方向引导

  • 想办法注入js,采用webview的方式去测试
  • 使用微信提供的那个很挫的测试框架,minitest,不过可以深挖下那个框架,从里面把他们的技术提炼抽取到appium里
  • 绕过UIAutomator基于AccessibilityNodeInfo去获取信息,或者给appium打补丁
  • 等微信出新版本或者降低版本,这本质是微信开发的bug

微信小程序这块的历史问题太多了,一言难尽,可能降低版本对所有人来说是最简单的。

1 个赞