Airtest之用装饰器重试解决Poco RpcTimeoutError

上期回顾:Airtest自动化多设备测试框架DreamMultiDevices


以下基于
python3.8;airtestIDE1.2.14;airtest1.2.6;pocoui1.0.87

运行Poco脚本的时候,有没有遇到过RpcTimeout的报错,形如:

File "poco\proxy.py"line 23in wrapped
File "poco\proxy.py"line 283in click
File "poco\proxy.py"line 563in get_position
File "poco\proxy.py"line 39in wrapped
File "poco\proxy.py"line 684in attr
File "poco\proxy.py"line 819in _do_query
File "poco\freezeui\hierarchy.py"line 89in select
File "poco\sdk\Selector.py"line 77in select
File "poco\sdk\Selector.py"line 70in getRoot
File "poco\freezeui\hierarchy.py"line 35in getRoot
File "poco\utils\simplerpc\utils.py"line 13in new_func
File "poco\utils\simplerpc\simplerpc.py"line 78in wait
poco.utils.simplerpc.simplerpc.RpcTimeoutError: <poco.utils.simplerpc.simplerpc.Callback object at 0x000001D120A1E8D0>(rid=41e44621-1ba7-423d-a6b2-e46ba46f0f79)

Python Poco库是通过RPC与接了Poco SDK的游戏进行通信,我们做任何操作的时候,都会先从游戏中拉取整个Hierarchy(UI树)的信息到PC上,然后Python Poco库再去匹配到需要的信息。所以在这个链条上,任何一个节点出错,都可能导致RpcTimeoutError,比如USB供电不稳定、USB线有问题、ADB有问题、各种环境版本问题、游戏内SDK传输有问题等等。但最有可能的还是场景Hierarchy(UI树)中的GameObject(元素)数量过大,导致传输UI信息的时候,adb无法及时做转发,信息丢失,进而出现了超时。游戏界面越复杂、元素越多,越容易出现这个问题。

什么意思呢,比如你的Hierarchy信息一共有几MB,你频繁的wait或click等操作,在Poco底层都会造成一次或多次的DUMP,从而频繁去拉取Hierarchy,造成RpcTimeoutError,严重的话可能还会卡死游戏内的Poco Server。类似于测试的压力测试,当压力小时,一切正常,当压力到达顶端时,各种性能指标都会下降,有些请求可能会失败,但整体还能工作。当压力超出顶点,导致链条上某个节点卡死或崩溃,整个系统就都不能工作了。

网上有人通过添加RPC的方法解决这个问题,我们看下他遇到的问题和解决方案:
https://answer.uwa4d.com/question/5dabdb05efeb9d3d55d15ab0


问题

airtest在战场中的卡顿问题

测试设备是华为荣耀10

在测试中需要等待战斗结束,代码中是用poco(‘UIRoot’).child(‘BattleEnd’).wait_for_appearance(100000)实现的,但是我发现执行到这段代码开始,每隔一两秒画面就会卡顿一次,然后我把"Poco辅助窗"改成"Stop",把Device窗口也关掉,卡顿依然存在,这个卡顿是怎么造成的,有什么方法可以解决么?

解决方案

自问自答一下,项目有管理ui的管理器,所以在PocoManager添加了rpc方法

[RPC]
    private object IsModuleVisible(List<object> param)

然后air代码里添加

from poco.utils.simplerpc.utils import sync_wrapper
from poco.drivers.unity3d import UnityPoco
import time;
from poco.exceptions import PocoTargetTimeout
auto_setup(__file__)
poco = UnityPoco()

@sync_wrapper
def IsModuleVisible(module):
    return poco.agent.c.call("IsModuleVisible"module)

def WaitForAppearance(module, timeout = 120):
    start = time.time()
    while not IsModuleVisible(module):
        poco.sleep_for_polling_interval();
        if time.time() - start > timeout:
            raise PocoTargetTimeout('Appearance'module)

然后调用这个自定义的WaitForAppearance就没有卡顿了,不知道还有什么更简单的解决方法?


他在Poco SDK端添加了一个新的RPC接口IsModuleVisible,这样等待元素的时候,通过调用这个接口,返回True或False,来判断元素是否出现。因为只返回一个布尔值,所以很快。当元素出现的时候,再去调用如click()方法,此时会用Poco原有的拉取整个Hierarchy的逻辑。这样一来,整个过程只拉取了一次全量Hierarchy。需要同时修改Python Poco源码和Poco SDK源码,如果能力有限,可以请开发帮忙修改。

但是,如果你游戏的Hierarchy真的超大,还是会出现问题。所以更彻底的优化方案是,Python Poco库发送拉取请求,游戏Poco服务做处理只返回相关的元素信息,而不是整个Hierarchy,这将是一袋大米和一粒大米的区别。当然,将比上面的修改更复杂,可能需要开发1-2周的工作量来熟悉/开发/调试。

好了,如果开发不帮忙修改,那只能自救了,虽然不治本但治标啊。Airtest图片查找是自带重试的,那Poco我们能不能也加个重试呢?

在不修改Poco源码的情况下,我们可以通过装饰器来解决。

不熟悉装饰器的可以先学习一下:python装饰器这一篇就够了python装饰器实现自动化失败后重试;进阶:Python三大器之装饰器

直接上代码:

# qasite_lib.py

from functools import wraps
from poco.utils.simplerpc.simplerpc import RpcTimeoutError

def qasite_retry(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        for i in range(2):
            try:
                return func(*args, **kwargs)
            except RpcTimeoutError:
                print(f'{func.__name__} 连接超时,重试一次')
        return func(*args, **kwargs)
    return wrapper

很简单,就是通过try发现RpcTimeoutError时,则忽略,重试一次。重试次数大家可以调整。

接着去二次封装各种操作,以上面网友遇到的wait_for_appearance为例

# qasite_lib.py

@rpctimeout_retry
def qasite_wait_appearance(element, timeout: int = 120) -> bool:
    element.wait_for_appearance(timeout)
    print(f"{element}出现了")
    return True

用例中应用:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco
from qasite_lib import *

auto_setup(__file__)

poco = UnityPoco()

button = poco("button")
qasite_wait_appearance(button)
qasite_click(button)  # 这个请参照qasite_wait_appearance自行实现

我们上面说了,如果只是超时,这种方法可以解决。如果是游戏内Poco服务卡死了,重试多少次也没用了。

 

---------------------------------------------------------------------------------

关注微信公众号即可在手机上查阅,并可接收更多测试分享~

posted @   ☆星空物语☆  阅读(713)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示