以下基于
python3.8;airtestIDE1.2.11;airtest1.2.2;pocoui1.0.83
老规矩开场白,我们今天要讲的是Airtest框架的pinch(),不是Poco框架的,一般我们说Airtest,其实应该指的是Airtest Project,具体这些概念的关系是什么,可以看之前文章:Airtest Project——UI自动化利器介绍
wait()和exists()有什么区别?
相同点:
- 都是传入一张图片(template实例),然后判断图片是否存在;
- 如果图片存在,两者均会返回图片坐标。
不同点:
- wait()找不到图片会报错TargetNotFoundError,而exists()找不到则返回False。
- wait()默认查找时间是20秒,并可以指定查找时间;而exists()默认查找时间是3秒,不能指定查找时间。
- 两者的查找间隔都是0.5秒,但wait()可以自定义时间,而exists()不行。
- wait()有一个参数intervalfunc,可以在每轮未找到目标时,运行一个指定方法。
wait()
源码解析
我们先来看下wait()的源码(不想看源码的可以直接跳到后面的演示实例):
1# 文件位置:your_python_path/site-packages/airtest/core/api.py
2def wait(v, timeout=None, interval=0.5, intervalfunc=None):
3 timeout = timeout or ST.FIND_TIMEOUT
4 pos = loop_find(v, timeout=timeout, interval=interval, intervalfunc=intervalfunc)
5 return pos
参数:
v – 要等待出现的目标Template实例
timeout – 等待匹配的最大超时时长,默认为None即默认取 ST.FIND_TIMEOUT 的值20秒
interval – 尝试查找匹配项的时间间隔(以秒为单位),默认0.5秒
intervalfunc – 每轮查找匹配失败后的回调函数
源码解析:
第3行,指定了timeout则使用timeout;如果未指定timeout,值赋值为ST.FIND_TIMEOUT,ST.FIND_TIMEOUT在your_python_path/site-packages/airtest/core/settings.py中,值为20。
第4行,调用loop_find()循环查找方法。
第5行,返回坐标。
我们看下loop_find()源码
1# 文件位置:your_python_path/site-packages/airtest/core/cv.py
2def loop_find(query, timeout=ST.FIND_TIMEOUT, threshold=None, interval=0.5, intervalfunc=None):
3 G.LOGGING.info("Try finding: %s", query)
4 start_time = time.time()
5 while True:
6 screen = G.DEVICE.snapshot(filename=None, quality=ST.SNAPSHOT_QUALITY)
7
8 if screen is None:
9 G.LOGGING.warning("Screen is None, may be locked")
10 else:
11 if threshold:
12 query.threshold = threshold
13 match_pos = query.match_in(screen)
14 if match_pos:
15 try_log_screen(screen)
16 return match_pos
17
18 if intervalfunc is not None:
19 intervalfunc()
20
21 # 超时则raise,未超时则进行下次循环:
22 if (time.time() - start_time) > timeout:
23 try_log_screen(screen)
24 raise TargetNotFoundError('Picture %s not found in screen' % query)
25 else:
26 time.sleep(interval)
逻辑之前在Airtest源码分析--图像识别整体流程 讲过,这里重点说下中间的
1if intervalfunc is not None:
2 intervalfunc()
如果找到了,其上一句就返回坐标了,所以走到这就是没匹配到图片。判断intervalfunc是否为None,如果不为None,则运行intervalfunc()。所以wait()中的intervalfunc入参,其实是在这里生效的。
演示实例
进入公众号详情,去匹配左上角的公众号图标,运行前先往上滑3屏。
这样wait()中的循环的前2次是匹配不到图标的,每次匹配不到时,执行函数not_find_fun(),即下滑。
最终匹配到时会返回图标的坐标,我把坐标打印了出来,可以对比一下打印的坐标和最后IDE中我鼠标指向图标的坐标是差不多的。
1# -*- encoding=utf8 -*-
2__author__ = "测试工程师小站"
3
4from airtest.core.api import *
5
6def not_find_fun():
7 """wait()循环查找时,每次未找到时执行的函数,即下滑"""
8 swipe([561, 512],[561, 1512])
9
10postion = wait(Template(r"tpl1635075246242.png", record_pos=(-0.369, -0.796), resolution=(1080, 2340)), timeout=30, interval=1, intervalfunc=not_find_fun)
11print(postion)
exists()
源码解析
我们先来看下exists()的源码(不想看源码的可以直接跳到后面的演示实例):
1# 文件位置:your_python_path/site-packages/airtest/core/api.py
2def exists(v):
3 try:
4 pos = loop_find(v, timeout=ST.FIND_TIMEOUT_TMP)
5 except TargetNotFoundError:
6 return False
7 else:
8 return pos
参数:
v – 要等待出现的目标Template实例
源码解析:
第4行,可以看到和wait()一样,也是调用loop_find()循环查找方法。不过不同的是被包在try中,还记得上面loop_find()的源码吗,如果最终没找到图片,是会拋异常TargetNotFoundError。这里专门针对TargetNotFoundError的报错,当发生时不报错并返回False。
演示实例
进入公众号详情,去匹配左上角的公众号图标,运行前先往上滑一屏。
这样第一次exists()判断图标不存在,返回False;之后下滑。
第二次exists()判断图标存在,返回坐标。
1# -*- encoding=utf8 -*-
2__author__ = "测试工程师小站"
3
4from airtest.core.api import *
5
6postion = exists(Template(r"tpl1635075246242.png", record_pos=(-0.369, -0.796), resolution=(1080, 2340)))
7print('*************************')
8print(postion)
9print('*************************')
10swipe([561, 512],[561, 1512])
11postion = exists(Template(r"tpl1635075246242.png", record_pos=(-0.369, -0.796), resolution=(1080, 2340)))
12print('*************************')
13print(postion)
14print('*************************')
---------------------------------------------------------------------------------