poco安装
poco常用api介绍
可结合参看之前写的文章airtest api简介
poco安装
Poco是一款基于UI控件搜索的自动化框架,与基于图像识别的Airtest不同的是,Poco可以使用类似poco("OK").click()
的方式来获取并操作节点
pip install pocoui
元素定位
先根据使用的引擎,按对应的方式初始化Poco实例,以下以android原生应用为例
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
poco.device.wake()
poco(text='Clock').click()
借助AirtestIDE的poco辅助窗生成元素定位脚本
AirtestIDE的 poco辅助窗 给我们提供了很多种方式来生成元素定位的脚本。最简单的方法是,点击poco辅助窗里面的录制按钮 ,然后再点击下目标元素
这种方式生成其实并不是最优,而且有时候直接用这个生成的,也会出现找不到定位元素而报错
可在这个生成的脚本基础上进行优化和改进
基本选择器进行元素定位
poco()括号里的参数就是所给定的条件,用属性名值对表示,其中第一个参数表示节点名 ,就像 poco("star_single") 。后面还可以跟着一些可选参数,均表示节点的属性及预期的属性值
- 通过name和其他属性
# select by node name
poco('bg_mission')
# select by name and other properties
poco('bg_mission', type='Button')
- 使用属性正则如textMatches、nameMatches参数
poco(textMatches='^据点.*$', type='Button', enable=True) # 正则匹配
poco(nameMatches=".*portalTitle",textMatches=".*推荐")
- log viewer中查看控件及其相关属性
# log viewer中查看控件的属性,如下为某tab的相关属性
Path from root node: [0, 0, 0, 1, 0, 0, 0, 1, 0, 2]
Payload details:
type : android.widget.TextView
name : android.widget.TextView
text : 沪深
enabled : True
visible : True
zOrders : {'global': 0, 'local': 3}
package : b'com.android.dazhihui'
anchorPoint : [0.5, 0.5]
dismissable : False
checkable : False
scale : [1, 1]
boundsInParent : [0.13703703703703704, 0.04893238434163701]
focusable : True
touchable : True
longClickable : False
size : [0.13703703703703704, 0.04893238434163701]
pos : [0.3425925925925926, 0.13211743772241993]
focused : False
checked : False
editalbe : False
selected : False
scrollable : False
相对选择器进行元素定位
如果直接用节点属性(或者说仅仅使用基本选择器)没法选出你所想要的元素时,你还可以通过元素之间的渲染层级关系进行选择,例如父子关系、兄弟关系、祖先后代关系等等
# select by direct child/offspring
poco('main_node').child('list_item').offspring('item')
空间顺序选择器进行元素定位
按照序号(顺序)进行选择总是按照空间排布顺序,先从左往右,再像之前那样一行一行从上到下
items = poco('main_node').child('list_item').offspring('item')
# print(items[0].child('material_name').get_text())
# print(items[1].child('material_name').get_text())
for item in items:
item.child('icn_item')
获取属性
如上我们已经知道log viewer中可以查看控件及其相关属性,如果想获取属性的值,可通过如下方式获取
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
hushen = poco(text="沪深")
print(hushen.attr('type'), hushen.attr('text'), hushen.get_text(), hushen.exists(), hushen.get_name(), print(hushen.get_size(), hushen.get_bounds(), hushen.get_position())
相关操作
UI对象相关操作
如
- click
poco('bg_mission').click()
poco('bg_mission').click('center')
poco('bg_mission').click([0.5, 0.5]) # equivalent to center
poco('bg_mission').focus([0.5, 0.5]).click() # equivalent to above expression
点击默认点在 anchorPoint 上,每个UI都会有一个 anchorPoint ,也就是检视器(Inspector)中UI包围盒的那个红点,大部分情况下 anchorPoint 都在UI包围盒的正中央。如果想指定其他的点击位置,可以传一个参数到 click 方法中,这个参数是一个用list或tuple表示的2维向量,其
[x, y]
值分别表示相对于包围盒左上角的偏移量,左上角为[0, 0]
,右下角为[1, 1]
(局部坐标系:相对于某UI的坐标,局部坐标系可以更灵活地定位UI内或外的位置,例如(0.5, 0.5)就代表UI的正中央,超过1或小于0的坐标值则表示UI的外面)
- swipe
joystick = poco('movetouch_panel').child('point_img')
joystick.swipe('up') # up, down, left, right
joystick.swipe([0.2, -0.2]) # swipe sqrt(0.08) unit distance at 45 degree angle up-and-right
joystick.swipe([0.2, -0.2], duration=0.5)
swipe使用的坐标是归一化坐标系,将屏幕宽和高按照单位1来算,这样UI在poco中的宽和高其实就是相对于屏幕的百分比大小了。如左上角点为原点[0, 0],向屏幕中央滑动等价于[0.1, -0.1],up等价于[0, -0.1], down等价于[0, 0.1], left等价于[-0.1, 0],right等价于[0.1, 0](其他标量和向量的计算方法同欧式空间)
这样做的好处是不同分辨率设备之间,同一个UI的归一化坐标系下的位置和尺寸是一样的,有助于编写跨设备测试用例。
- drag_to
从一个UI拖到另一个UI
poco(text='突破芯片').drag_to(poco(text='岩石司康饼'))
- focus:局部定位
所有UI相关的操作都默认以UI的 anchorPoint 为操作点,如果想自定义一个点那么可以使用 focus 方法。调用此方法将返回 新的设置了默认焦点 的UI,重复调用则以最后一次所调用的为准
scrollView = poco(type='ScollView')
scrollView.focus([0.5, 0.5]).drag_to(scrollView.focus([0.5, 0.2])) #focus([0.5, 0.5])等价于focus('center')
- scroll:
scroll(self, direction='vertical', percent=0.6, duration=2.0)
- direction:滚动方向:vertical垂直或horizontal水平
- percent:滚动比例
- duration:持续时间
- wait、wait_for_appearance、wait_for_disappearance
poco('bg_mission').wait(5).click() # wait 5 seconds at most,click once the object appears
poco('bg_mission').wait(5).exists() # wait 5 seconds at most,return Exists or Not Exists
- freeze:冻结UI以加快一些速度
在一些复杂的场景可以冻结UI来加快脚本的一些速度,冻结UI是将UI层级保存在本地,这样就可以不用跟app进行通讯以加快脚本执行速度。可进一步参看freezing_UI
全局操作
在没有选定或指定UI的情况下也可以进行操作(模拟输入),也叫全局操作。包含click、long_click、swipe等
更多操作可参看官方api
异常处理
- PocoTargetTimeout
- PocoNoSuchNodeException
from poco.exceptions import PocoTargetTimeout
try:
poco('guide_panel', type='ImageView').wait_for_appearance()
except PocoTargetTimeout:
# bugs here as the panel not shown
raise
from poco.exceptions import PocoNoSuchNodeException
img = poco('guide_panel', type='ImageView')
try:
if not img.exists():
img.click()
except PocoNoSuchNodeException:
# If attempt to operate inexistent nodes, an exception will be thrown
pass