测试人社区

[求助] appium 测试微信小程序时,安卓高版本,预套接字文件名称由 webview 改为 xweb,导致切换 webview 失败,请问有什么好的解决方案

在执行webview上下文切换的时候,appium报错,发现是 chromedriver会根据传入的进程自己在进程号前拼接 @ webview_devtools_remote_.*
看了下chromedriver的源码,确实是这样
image
这里试了下安卓5.1.1版本是没问题的,
在试安卓6.0.0,9.0.0,10.0.0版本的时候发现文件名称是 @ xweb_devtools_remote
导致appium在调用chromedriver切换context的时候找不到 @ webview_devtools_remote文件,切换失败
请问有什么好的解决方案么

首先,你的 app 开启了 webview 调试开关了吗,如果没有,这个问题课上应该强调过很多次了

切换webview时,可以自己使用adb forward命令重定向你实际的名称,而不是chromedriver拼接的名称,可以参考我直之前写的帖子的解决方案

2 Likes

解决了,用python写了一个简单的tcp代理只用于chromedriver执行adb命令部分,修改appium源码中chromedriver的adb端口5038,用于做转发,监听来自chromedriver的adb命令,当是webvie_devtools_remote的时候,修改掉,再转给5037端口

附上tcp代理代码,比较简陋 :joy:
# coding=utf-8

import threading
import socket
import time

socket_list = []

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 5038))
# server.setblocking(False)
socket.setdefaulttimeout(2)
server.listen(5)


def read_from_client(s):
    buffer = b''
    s.settimeout(0.1)
    try:
        data_len = 1
        while data_len:
            data = s.recv(4096)
            data_len = len(data)
            buffer += data
            if data_len < 4096:
                break
    except Exception as e:
        pass
    return buffer


def read_from_server(s):
    buffer = b''
    # s.settimeout(2)
    try:
        data_len = 1
        while data_len:
            data = s.recv(4096)
            data_len = len(data)
            buffer += data
            if data_len < 4096:
                break
    except Exception as e:
        pass
    return buffer


def send_to_client(s, data: bytes):
    s.send(data)


while True:
    s, addr = server.accept()
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', 5037))
    print('got connected from', addr)
    while True:
        msg = read_from_client(s)
        print('msg:' + repr(msg))
        if msg == b'':
            break
        elif '@webview_devtools_remote_' in msg.decode('utf-8'):
            print("Get:" + repr(msg) + "\r\n")
            msg_rep = msg.decode('utf-8').replace('@webview_devtools_remote_', '@.*_devtools_remote_')
            msg_rep = msg_rep[4:]
            msg_rep = str(hex(len(msg_rep))) + msg_rep
            msg_rep = msg_rep[:1] + '0' + msg_rep[2:]
            print('转化为:%s' % msg_rep)
            client.send(msg_rep.encode('utf-8'))
            print("Client send data %s to " % repr(msg_rep.encode('utf-8')))
            # time.sleep(10)
        elif msg != b'':
            print("Get:" + repr(msg) + "\r\n")
            client.send(msg)
            print("Client send data %s to " % repr(msg))
        while True:
            buf = read_from_server(client)
            print('buf: ' + repr(buf))
            if buf == b'':
                break
            send_to_client(s, buf)

    s.close()
    client.close()
1 Like

我之前写过一个java版本的。。。

判断webview进程的时候,chromedriver是走协议的,没有调用adb命令,只能通过代理解决,的确是一大坑。不过用mitmproxy做个tcp代理或许代码更好看些。

感谢,有时间试下,还有一个问题,模拟器貌似开启不了x5内核调试,debugmm.qq.com/?forcex5=true这个执行了也打不开tbs调试页面;所以appium小程序测试只能用真机测么(之前用真机,usb一直连着,电池炸了,公司现在只让用模拟器)

模拟器有root权限的话可以使用WebViewDebugHook强制开启debug模式。需要先安装 Xposed

嗯,试了一下,可以了