上期回顾:Airtest解决“自动装包”过程中需要输入密码的问题(同适用于随机弹框处理)
以下基于
python3.8;airtestIDE1.2.14;airtest1.2.6;pocoui1.0.87
Poco最新版1.0.87新增了一个新的元素刷新API:refresh()
新接口的由来
如果你的项目之前使用了Poco,那你一定会使用PO模式,这样就可能会遇到元素不刷新的问题。
比如你在元素的ele.py中定义了元素,类似
info_button = poco("info_button")
在用例case.py中引入了元素定义并使用
from ele import info_button
info_button.click()
# 经过一系列操作,info_button可能已经发生位移,此时再去点击,点的会是之前的位置
# 因为poco元素定义赋给变量后,信息只会保留第1次使用时抓取的,之后不会更新
info_button.click() # 会点不到
所以之前的解决方案很low,就是在case中再定义一次元素
info_button.click()
# 经过一系列操作,info_button可能已经发生位移
info_button1 = poco("info_button") # 相同的元素重新赋值一次
info_button1.click() # 这样就OK了
另外官方也列举了两个例子
例1
# 打开APP,有一个按钮‘每日推荐’
ele = poco("每日推荐")
print(ele.exist()) # 输出True
# 按手机HOME键
print(ele.exist()) # 此时仍输出True
即使元素不存在了,这种情况下Poco也仍然认为元素存在,原因同上面的例子,元素信息会保留第1次抓取的,后面不会自动更新
官方例子动图例2
同样的,有时用Poco的wait_for_disappearance(),会遇到实际上节点已经消失了,但是接口没有判断到消失的问题。
解决方法
对于第1、2个例子,可以显示的用新增API refresh()去手动刷新。
以第2个例子为例:
# 打开APP,有一个按钮‘每日推荐’
ele = poco("每日推荐")
print(ele.exist()) # 输出True
# 按手机HOME键
ele.refresh() # 给元素刷新信息
print(ele.exist()) # 输出False
官方例子动图
对于第3个例子wait_for_disappearance(),官方已经在源码中修复,所以以后还是直接使用wait_for_disappearance()即可。
注意
refresh()是针对Poco UI对象(UIObjectProxy实例)的API,而不是Poco实例的。
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
# 正确用法
poco(text="日历").refresh()
# 错误用法
poco.refresh() # 会报错!!!
两者的区别可以看之前文章:
Poco UI对象 API汇总
Poco实例(全局操作) API汇总
源码解析
先看下其源码:
源码地址:your_python_path/site-packages/poco/proxy.py
def invalidate(self):
self._evaluated = False
self._nodes = None
# refresh is alias of invalidate
# use poco(xxx).refresh() to force the UI element(s) to re-query
refresh = invalidate
其实之前版本就已经存在invalidate()方法了,这次只是新增了一个别名refresh而已。
invalidate()方法其实很简单,只是将两个变量重置而已,这两个变量的含义在class UIObjectProxy(object)
的__init__()
方法中有说明:
源码地址:your_python_path/site-packages/poco/proxy.py
# true or false whether the corresponding UI elements of this UI proxy (self) have been selected
# 此UI proxy是否已经查找到对应的UI elements了
self._evaluated = False
# the proxy object of UI elements, migh be `node` or `[nodes]`, the proxy type is specified by
# `self._nodes_proxy_is_list`
# 可能是远程node代理,也可能是远程[node]代理, 由`self._nodes_proxy_is_list`指定是何种proxy类型
self._nodes = None
self._nodes_proxy_is_list = True
---------------------------------------------------------------------------------
关注微信公众号即可在手机上查阅,并可接收更多测试分享~