airtest结构:
包括两种脚本:①airtest、②poco脚本
Airtest脚本
方法为基于图像识别原理,适用于图像比较复杂的情况(不会出现误识别,点击到其他位置)
在测试的时候,由于我使用的是盲打键盘,airtest经常会出现识别键盘失误的情况。
配置项:
target_pos
:用于设置图像的点击位置,为1-9的整数,默认值为5(即图像中心,1为图像左上角位置,9为图像右下角位置)
threshold
:图像识别的阙值,只有当图像识别结果的可信度大于阙值,才算找到图像识别的结果;阈值越高,对图像匹配的精度要求也就越高
常用方法记录:
①touch
(v, times=1, **kwargs) #点击
- v – 点击位置: 可以是一个
Template
图片实例,或是一个绝对坐标(x, y)
- times – 点击次数
- kwargs – 平台相关的参数
返回:返回最后点击的位置
实例:
#点击绝对坐标
touch((100, 100))
#点击图片所在,target_pos=5意思是中心位置
touch(Template(r"tpl1606730579419.png", target_pos=5))
#点击两次,相当于:double_click((100, 100))
ouch((100, 100), times=2)
#duration:按下的持续时间
touch((100, 100), duration=2)
#右键点击
touch((100, 100), right_click=True)
②swipe
(v1, v2=None, vector=None, **kwargs) #滑动
- v1 – 滑动的起点,可以是一个Template图片实例,或是绝对坐标
(x, y)
- v2 – 滑动的终点,可以是一个Template图片实例,或是绝对坐标
(x, y)
- vector – 滑动动作的矢量坐标,可以是绝对坐标
(x,y)
或是屏幕百分比,例如(0.5, 0.5)
- **kwargs – 平台相关的参数
kwargs
,请参考对应的平台接口文档
返回:原点位置和目标位置
实例:
#原点为图片中心所在位置,滑动向量为后续
swipe(Template(r"tpl1606814865574.png"), vector=[-0.0316, -0.3311])
#原点位置直接给出(100,100)。滑动向量直接给出(200,200)
swipe((100, 100), (200, 200))
#定义滑动时间和滑动步骤(均分为6次滑动)
swipe((100, 100), (200, 200), duration=1, steps=6)
③pinch
(in_or_out='in', center=None, percent=0.5) #双指捏合操作
- in_or_out – 向内捏合或向外扩大,在[“in”, “out”] 中枚举一个值
- center – pinch动作的中心位置,默认值为None则为屏幕中心点
- percent – pinch动作的屏幕百分比,默认值为0.5
#双指向屏幕中心点捏合
pinch()
#将(100, 100)作为中心点,向外扩张两指:
pinch('out', center=(100, 100))
④keyevent
(keyname, **kwargs) #按键事件,,非文本输入
- keyname – 平台相关的按键名称
- **kwargs – 平台相关的参数
kwargs
,请参考对应的平台接口文档
Android
: 相当于执行了 adb shell input keyevent KEYNAME
#home按键为返回主屏幕,安卓下方圆圈
keyevent("HOME")
# The constant corresponding to the home key is 3
keyevent("3") # same as keyevent("HOME")
#back按键为返回键,安卓下方箭头
keyevent("BACK")
#other按键
keyevent("KEYCODE_DEL")
⑤text
(text, enter=True, **kwargs) 输入框必须处于激活状态
- text – 要输入的文本
- enter – 是否在输入完毕后,执行一次
Enter
,默认是True
#输入test,并发送
text("test")
#输入test,不发送
text("test", enter=False)
⑥sleep
(secs=1.0) 睡眠secs秒
⑦wait
(v, timeout=None, interval=0.5, intervalfunc=None) #等待当前画面上出现某个匹配的Template图片
- v – 要等待出现的目标Template实例
- timeout – 等待匹配的最大超时时长,默认为None即默认取
ST.FIND_TIMEOUT
的值 - interval – 尝试查找匹配项的时间间隔(以秒为单位)
- intervalfunc – 在首次尝试查找匹配失败后的回调函数
返回:匹配目标的坐标
实例:
#等待直到***.png出现,ST.FIND_TIMEOUT:全局等待事件
# timeout after ST.FIND_TIMEOUT
wait(Template(r"***.png"))
# find Template every 3 seconds, timeout after 120 seconds
wait(Template(r"tpl1606821804906.png"), timeout=120, interval=3)
#回调函数定义,intervalfunc回调函数定义
def notfound():
print("No target found")
wait(Template(r"tpl1607510661400.png"), intervalfunc=notfound)
⑧exists
(v) #检查设备上是否存在给定目标
返回:如果未找到目标,则返回False,否则返回目标的坐标
if exists(Template(r"tpl1606822430589.png")):
touch(Template(r"tpl1606822430589.png"))
pos = exists(Template(r"tpl1606822430589.png"))
if pos:
touch(pos)
wait()和exists()有什么区别?
相同点:
-
都是传入一张图片(template实例),然后判断图片是否存在;
-
如果图片存在,两者均会返回图片坐标。
不同点:
-
wait()找不到图片会报错TargetNotFoundError,而exists()找不到则返回False。
-
wait()默认查找时间是20秒,并可以指定查找时间;而exists()默认查找时间是3秒,不能指定查找时间。
-
两者的查找间隔都是0.5秒,但wait()可以自定义时间,而exists()不行。
-
wait()有一个参数intervalfunc,可以在每轮未找到目标时,运行一个指定方法。
Poco脚本
Poco,基于UI控件搜索原理
如图所示,界面中网易云音乐就是一个控件,左侧是该控件的基本信息
Poco代码,主要有两个部分组成,控件定位脚本与控件操作脚本
控件定位脚本
控件定位脚本主要有3种方式定位控件
- 基本选择器
- 相对选择器
-
空间顺序选择器
基本选择器
在poco实例后加一对括号就可以进行UI选择了。选择器会遍历所有UI,将满足给定条件的UI都选出来并返回。
例如:
在此例中,下列两行代码都是等价的,选择的都是网易云音乐的控件。其中默认第一项是name
#相当于poco("网易云音乐")
poco(name = "网易云音乐")
poco(desc = "网易云音乐")
相对选择器
当控件过多或者控件被覆盖等处于无法选中的状态时,基本选择器就会失效,此时可以选择相对选择器。
其中 offspring 是后代的意思,在这里意味着offspring内写着最终的目标控件并意味着选择的终点。
poco("plays").child("playBasic").offspring("star_single")
空间顺序选择器
在左侧的同一个目录下,可以通过从左到右、从上到下的顺序形成数组,我们就可以通过下标的方式直接访问。
例如下列代码,在“Content”目录下有很多类型为“Text”的子控件,我们可以通过下标的方式直接访问,而不用每个控件都用名字等访问
name0 = poco("Content").child(type="Text")[0].get_name()
name1 = poco("Content").child(type="Text")[1].get_name()
name2 = poco("Content").child(type="Text")[2].get_name()
print(name0+" "+name1+" "+name2)
控件操作脚本
①click
(x, y)
- x:x轴坐标
- y:y轴坐标
单击一下
②longClick
(x, y, duration)
- x:x轴坐标
- y:y轴坐标
- duration:长按的时间
长按duration秒
# 控件单击
poco("star_single").click()
# 控件长按
poco('star_single').long_click()
③keyevent
(keycode)
传入一个按键事件
④swipe
(x1, y1, x2, y2, duration) or swipe([vector])
- x1:初始x轴坐标
- y1:初始y轴坐标
- x2:目标x轴坐标
- y2:目标y轴坐标
- duration:长按的时间
- [vector]:位移矢量
# 向下滑动0.2个单位距离
poco("Handle").swipe([0,0.2])
sleep(1.0)
# 向上滑动0.2个单位距离
poco("Handle").swipe([0,-0.2])
sleep(1.0)
# 向下滑动0.1个单位距离
poco("Handle").swipe("down")
sleep(1.0)
# 向上滑动0.1个单位距离
poco("Handle").swipe("up")
sleep(1.0)
⑤attr()接口,通过attr结构读取控件的基本信息
print("name:"+poco("star_single").attr("name"))
print("type:"+poco("star_single").attr("type"))
print("texture:"+poco("star_single").attr("texture"))
同时,通过attr接口包装了很多其他的接口:
- 获取控件的name属性:
get_name
- 获取控件的text属性:
get_text
- 获取控件的position属性:
get_position
- 获取控件的size属性:
get_size
print("name:"+poco("star_single").get_name())
print("position:"+str(poco("star_single").get_position()))
print("size:"+str(poco("star_single").get_size()))
⑥setattr()设置控件信息
# 先激活输入光标
poco("pos_input").click()
# 再执行输入动作
poco("pos_input").set_text("123")
sleep(1.0)
poco("pos_input").setattr('text',"456")
当然,通过包装接口,形成了其他很多接口,例如上例set_text()
⑦exists()
该方法比airtest脚本里面的exists方法更精确有效,但是无法识别控件的状态变化,只能识别控件存在与否。
if poco("star_single").exists():
poco("star_single").click()
else:
print("未找到星星控件")
⑧drag_to()
# 拖动到另一个控件上
poco("playDragAndDrop").child("star")[0].drag_to(poco("shell"))
# 拖动到固定目标上
poco("playDragAndDrop").child("star")[1].drag_to([0.503, 0.705])
⑨focus()
点击位置默认为控件长宽归一化之后的中心点。若不想点击中心点,则可以使用该方法:
# 内部偏移
pearl = poco(texture="icon")
pearl.focus('center').long_click()
sleep(1.0)
pearl.focus([0.1,0.1]).long_click()
sleep(1.0)
pearl.focus([0.9,0.9]).long_click()
断言
Airtest IDE 提供了四种断言快捷断言的方式
- assert_exists 断言存在
- assert_not_exists 断言不存在
- assert_equal 断言相等
- assert_not_equal 断言不相等
断言(不)存在(assert_exists、assert_not_exists)
参数:
- v 要检查的目标
- msg 断言的简短描述,它将被记录在报告中
- AssertionError 如果断言失败
返回:
- 成功:目标坐标
- AssertionError
当页面上找不到元素的时候,不会立马断言失败,此时会有个timeout时间,默认是20秒。
assert_equal
断言2个值相等,实际结果等于期望结果
参数:
- first – 第一个值
- second – 第二个值
- msg – 断言的简短描述,它将被记录在报告中
断言失败引发异常: AssertionError – 如果断言失败
返回: None
assert_equal("实际结果", "期望结果", "请填写断言的简短描述")
#例如
assert_equal(poco("star_single").exists(),True,"断言星星控件存在")
assert_equal(poco("com.taobao.taobao:id/dx_root").get_text(), "天猫新品", "控件的text属性值为天猫新品")
assert_equal(str(poco(text="天猫新品").attr("enabled")), "True", "控件的enabled属性值为True")
assert_not_equal
断言两个值不相等
参数:
- first – 第一个值
- second – 第二个值
- msg – 断言的简短描述,它将被记录在报告中
引发: AssertionError – 如果断言异常
返回: None
assert_not_equal(1, 2, msg="assert 1!=2")