介绍
AirtestProject是由网易游戏推出的一款自动化测试框架,是一个跨平台的、基于图像识别的UI自动化测试框架,适用于游戏和App,支持平台有Windows、Android和iOS。
Airtest项目文档请 点击此处 访问。
本着3W法,我们在学习过程中需要了解 what , why ,how。下文会围绕这三点来做讲解。
什么是Airtest (what)
我们先来看一下官方文档的描述。
AirtestProject是由网易游戏推出的一款自动化测试框架,项目构成如下:
-
Airtest:是一个跨平台的、基于图像识别的UI自动化测试框架,适用于游戏和App,支持平台有Windows、Android和iOS
- 源码
- API文档
-
Poco:是一款基于UI控件识别的自动化测试框架,目前支持Unity3D/cocos2dx-*/Android原生app/iOS原生app/微信小程序,也可以在其他引擎中自行接入poco-sdk来使用
- 源码
- API文档
AirtestIDE:跨平台的UI自动化测试编辑器,内置了Airtest和Poco的相关插件功能,能够使用它快速简单地编写Airtest和Poco代码。
如果我们是第一次使用那么可以直接下载AirtestIDE来进行我们的UI自动化,如果我们有一些二次开发的需求我们可以使用airtest源码来进行二次开发,airtest是使用python来进行开发的,我们也可以使用python进行二次开发。
我们再来看一下Airtest的项目架构。
可以看到,底层的主要测试框架主要是Airtest和Poco,二者的区别在于:
- Airtest:基于Python的、跨平台的UI自动化测试框架,基于图像识别原理,适用于游戏和App。
- Poco:基于UI控件搜索的自动化测试框架,其核心优势是除了对Android、IOS之外,对游戏也是支持的,同时也支持微信小程序、微信小游戏和H5应用。
整套框架配备了非常实用的IDE,通过AirtestIDE, 可以轻松的完成脚本的录制、测试任务的执行以及最后测试报告的生成。
为什么使用Airtest(why)
之前我们说到Airtest是通过图像识别来进行ui自动化测试的,那这种方式有什么好处的?举一个简单的场景,大多数游戏开发的前端页面都是通过游戏引擎来进行渲染的,与我们常见的web程序不一样,我们不能利用webdrvier来获取元素节点,这时候appium就不能很好的支持我们完成测试工作了,反而是airtest这种图像识别技术,从更上层来进行操作的模拟以及结果的判定,完全不关系底层的页面是怎么实现的,适用性更强。
工具 | 是否收费 | 支持语言 | 跨平台 | 断言、报告 | 环境搭建 | 实现原理 | 录制 |
---|---|---|---|---|---|---|---|
Appium | 开源 | Python、Java、Js/Nodejs、Ruby、OC、C#等 | IOS、Android、Windows和Mac不同机型需要分别配置 | 依赖第三方库 | 需要一系列安装依赖 | 元素识别 | 支持 |
Airtest | 网易开发(免费) | python | IOS、Android、Windows和Mac不需要配置 | 自带 | 开箱即用 | 图片识别(Airtest)元素识别(poco,需要项目接入sdk) | 支持 |
由此可见对于一些没有代码基础以及自动化实践经验的测试人员来说,airtest显然更适合快速的落地。但针对不同的项目还是要选择适合自己的自动化工具,毕竟Airtest也有他自身的缺点,例如:依赖图片识别的精准度无法保证。
怎么使用Airtest(how)
先附上官方教程:https://airtest.doc.io.netease.com/tutorial/1_quick_start_guide/
由于Airtest上手难度较低,官方教程也比较详细,再次就不再做过多的赘述。
Airtest常用的指令
Airtest api 官方文档:https://airtest.readthedocs.io/zh_CN/latest/all_module/airtest.core.api.html
touch(v, times=1, **kwargs)
在当前设备画面上进行一次点击
- v – 点击位置,可以是一个 Template 图片实例,或是一个绝对坐标 (x, y)
- times – 点击次数
- kwargs – 平台相关的参数 kwargs,请参考对应的平台接口文档
touch((100, 100)) #点击绝对坐标
touch(Template(r"tpl1606730579419.png", target_pos=5)) #点击图片的中心位置
touch((100, 100), times=2) #点击两次
touch((100, 100), duration=2) #在Android和Windows下,可以设置点击持续时间
touch((100, 100), right_click=True) #右键点击(Windows)
click(v, times=1, **kwargs)
在当前设备画面上进行一次点击
- v – 点击位置,可以是一个 Template 图片实例,或是一个绝对坐标 (x, y)
- times – 点击次数
- kwargs – 平台相关的参数 kwargs,请参考对应的平台接口文档
touch((100, 100)) #点击绝对坐标
touch(Template(r"tpl1606730579419.png", target_pos=5)) #点击图片的中心位置
touch((100, 100), times=2) #点击两次
touch((100, 100), duration=2) #在Android和Windows下,可以设置点击持续时间
touch((100, 100), right_click=True) #右键点击(Windows)
double_click(v)
双击
- v – 点击位置,可以是一个 Template 图片实例,或是一个绝对坐标 (x, y)
double_click((100, 100))
double_click(Template(r"tpl1606730579419.png"))
swipe(v1, v2=None, vector=None, **kwargs)
在当前设备画面上进行一次滑动操作。
有两种传入参数的方式
- swipe(v1, v2=Template(...)) # 从 v1 滑动到 v2
- swipe(v1, vector=(x, y)) # 从 v1 开始滑动,沿着vector方向。
- 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])
swipe((100, 100), (200, 200))
自定义滑动持续时间和经过几步到达终点:
swipe((100, 100), (200, 200), duration=1, steps=6) # 滑动持续1秒,分为6步
keyevent(keyname, **kwargs)
在设备上执行keyevent按键事件
- keyname – 平台相关的按键名称
- ****kwargs** – 平台相关的参数 kwargs,请参考对应的平台接口文档
Android:
keyevent("HOME") # The constant corresponding to the home key is 3
keyevent("3") # same as keyevent("HOME")
keyevent("BACK")
keyevent("KEYCODE_DEL")
Windows:
keyevent("{DEL}")
keyevent("%{F4}") # close an active window with Alt+F4
ios:
keyevent("HOME")
keyevent("volumeUp")
text(text, enter=True, **kwargs)
在目标设备上输入文本,文本框需要处于激活状态。
- text – 要输入的文本
- enter – 是否在输入完毕后,执行一次 Enter ,默认是True
text("test")
text("test", enter=False)
在Android上,有时你需要在输入完毕后点击搜索按钮:
text("test", search=True)
sleep(secs=1.0)
设置一个等待sleep时间,它将会被显示在报告中
secs – sleep的时长
sleep(1)
wait(v, timeout=None, interval=0.5, intervalfunc=None)
等待当前画面上出现某个匹配的Template图片
- v – 要等待出现的目标Template实例
- timeout – 等待匹配的最大超时时长,默认为None即默认取 ST.FIND_TIMEOUT 的值
- interval – 尝试查找匹配项的时间间隔(以秒为单位)
- intervalfunc – 在首次尝试查找匹配失败后的回调函数
wait(Template(r"tpl1606821804906.png")) # timeout after ST.FIND_TIMEOUT
wait(Template(r"tpl1606821804906.png"), timeout=120, interval=3) # find Template every 3 seconds, timeout after 120 seconds
你可以在每次查找目标失败时,指定一个回调函数:
def notfound():
print("No target found")
wait(Template(r"tpl1607510661400.png"), intervalfunc=notfound)
exists(v)
检查设备上是否存在给定目标
- v – 要检查的目标
if exists(Template(r"tpl1606822430589.png")):
touch(Template(r"tpl1606822430589.png"))
因为 exists() 会返回坐标,我们可以直接点击坐标来减少一次图像查找
pos = exists(Template(r"tpl1606822430589.png"))
if pos:
touch(pos)
find_all(v)
在设备屏幕上查找所有出现的目标并返回其坐标列表
- v – 寻找目标
find_all(Template(r"tpl1607511235111.png"))
[{'result': (218, 468), 'rectangle': ((149, 440), (149, 496), (288, 496), (288, 440)),'confidence': 0.9999996423721313}]
assert_exists(v, msg='')
设备屏幕上存在断言目标
- v – 要检查的目标
- msg – 断言的简短描述,它将被记录在报告中
assert_exists(Template(r"tpl1607324047907.png"), "assert exists")
assert_not_exists(v, msg='')
设备屏幕上不存在断言目标
- v – 要检查的目标
- msg – 断言的简短描述,它将被记录在报告中
assert_not_exists(Template(r"tpl1607324047907.png"), "assert not exists")
assert_equal(first, second, msg='')
断言两个值相等
- first – 第一个值
- second – 第二个值
- msg – 断言的简短描述,它将被记录在报告中
assert_equal(1, 1, msg="assert 1==1")
assert_not_equal(first, second, msg='')
断言两个值不相等
- first – 第一个值
- second – 第二个值
- msg – 断言的简短描述,它将被记录在报告中
assert_not_equal(1, 2, msg="assert 1!=2")
运行脚本
IDE点击“运行脚本”按钮或者"F5"即可执行写好的脚本
使用python命令行运行脚本
airtest run untitled.air --device Android:///手机设备号 --log log/
python -m airtest run untitled.air --device Android:///手机设备号 --log log/
生成报告
点击IDE上的报告按钮可以直接生成报告并自动打开