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

更多