二、Airtest启动器介绍
注解
主要描述编写录制脚本中,涉及到启动器部分和自定义参数的内容,可能未来会因为airtest的迭代而发生改动
在编写测试脚本的过程中,经过airtest封装的简单语句可能满足不了更复杂的代码编写需求,这一章主要介绍脚本编写中的一些高级特性。
Airtest脚本目前支持的自定义功能有:
- 设置脚本运行过程中的参数
- 添加自定义方法,或者替换默认方法
- 在测试用例的运行前后,执行初始化代码或清理代码,甚至是调用其他用例脚本
1. 启动器介绍
Airtest在运行用例脚本时,在继承 unittest.TestCase
的基础上,实现了一个叫做 AirtestCase
的类,添加了所有执行基础Airtest脚本的相关功能。
因此,假如需要添加自定义功能,只需要在 AirtestCase
类的基础上,往 setup
和 teardown
中加入自己的代码即可。如果这些设置和功能内容相对固定,可以将这些内容作为一个launcher,用来在运行实际测试用例之前初始化相关的自定义环境。
AirtestCase
的内容详情介绍可参考:Airtest帮助文档的相关内容 。
2. 启动器范例
以下是一个自定义custom_launcher.py的范例代码:
from airtest.cli.runner import AirtestCase, run_script
from airtest.cli.parser import runner_parser
class CustomAirtestCase(AirtestCase):
def setUp(self):
print("custom setup")
# add var/function/class/.. to globals
# self.scope["hunter"] = "i am hunter"
# self.scope["add"] = lambda x: x+1
# exec setup script
# self.exec_other_script("setup.owl")
super(CustomAirtestCase, self).setUp()
def tearDown(self):
print("custom tearDown")
# exec teardown script
# self.exec_other_script("teardown.owl")
super(CustomAirtestCase, self).setUp()
if __name__ == '__main__':
ap = runner_parser()
args = ap.parse_args()
run_script(args, CustomAirtestCase)
它的主要功能就是:在AirtestCase的基础上,添加了一些自定义的内容,同时可以通过它作为一个启动器,来运行实际的测试用例代码。
例如:
python custom_launcher.py test.air --device Android:///serial_num --log log_path
这个命令行使用自定义的启动器custom_launcher.py来运行名为test.air的脚本。
3. Airtest-IDE中的启动器
在IDE中,运行脚本的方式有两种,第一种是简单地在编辑框里写上要运行的Airtest代码,之后就能够用默认方式来运行脚本,无需其他额外的代码。
第二种,就是在刚才介绍的启动器基础上,实现一个自定义的启动器,这样能够初始化一个自定义的环境,供后来编写的Airtest代码运行。
1)配置方法
菜单-“选项”-“设置”-“Airtest”,点击“自定义Launcher文件位置”右侧的设置框,即可打开文件选择窗口,选择自定义的launcher.py文件即可。
点击“编辑”,可对launcher.py文件的内容进行编辑,点击右下角的“OK”按钮让新配置生效。
2)代码范例
以下是一份 在AirtestIDE中 使用的启动器代码范例(与上文那份命令行可直接运行的 启动器范例
相比,IDE下可以把当前运行的代码行标出颜色,以及未来可能还可以额外支持其他功能):
from airtest.cli.runner import run_script
from airtest.cli.parser import runner_parser
from airtest.core.settings import Settings as ST
# 假如脚本在IDE中运行,IDE会自动帮忙加载AirtestCase。假如要用命令行独立运行脚本,则需要手工import AirtestCase
if not global().get("AirtestCase"):
from airtest.cli.runner import AirtestCase
class CustomAirtestCase(AirtestCase):
def __init__(self):
super(CustomAirtestCase, self).__init__()
def setUp(self):
print("custom setup")
super(CustomAirtestCase, self).setUp()
def tearDown(self):
print("custom tearDown")
super(CustomAirtestCase, self).tearDown()
if __name__ == '__main__':
ap = runner_parser()
args = ap.parse_args()
run_script(args, CustomAirtestCase)
4. 启动器中自定义内容介绍
在自定义的启动器代码中,继承 AirtestCase
之后,能够在setUp()
与tearDown()
方法里对执行脚本时的环境变量进行设置:
class CustomAirtestCase(AirtestCase):
def setUp(self):
# add var/function/class/.. to globals
super(CustomAirtestCase, self).setUp()
1) 添加自定义变量与方法
将自定义变量添加到 self.scope
里,之后用该启动器来运行Airtest的脚本,脚本代码中就能够直接使用这些变量,无需重新定义:
def setUp(self):
self.scope["hunter"] = "i am hunter"
self.scope["add"] = lambda x: x+1
2)在正式脚本运行前后,添加子脚本的运行
在执行测试用例时,有一类很常见的需求,是在正式用例之前执行固定的初始化脚本,或是在用例执行完毕后执行清理脚本.
在自定义Airtest启动器中,可以使用很简单的代码来完成这类需求:
class CustomAirtestCase(AirtestCase):
PROJECT_ROOT = "子脚本存放公共路径" # 可以将子脚本放置在某个公共目录下
def setUp(self):
# exec setup script
self.exec_other_script("setup.air") # 假设该setup.air脚本存放在PROJECT_ROOT目录下,调用时无需填写绝对路径,可以直接写相对路径
super(CustomAirtestCase, self).setUp()
def tearDown(self):
# exec teardown script
self.exec_other_script("teardown.air")
super(CustomAirtestCase, self).setUp()
3)在正式脚本里,添加子脚本的运行
另一类常见需求是在脚本内执行子脚本,同样可以将子脚本存放在 PROJECT_ROOT
公共目录下,然后在脚本 test.air
中调用代码:
exec_script("子脚本.air")
4)修改Airtest默认参数值
Airtest在运行脚本和识别图像的过程中,由于默认配置的参数值可能不符合实际运行需要,以下代码演示了如何修改默认参数配置:
from airtest.core.settings import Settings as ST
class CustomAirtestCase(AirtestCase):
def setUp(self):
ST.THRESHOLD = 0.75
上面这段代码,将默认配置的图像识别准确率阈值改为了0.75(默认值是0.6),降低了图像识别的错误率。
在 airtest.core.settings
的 Settings
中,有以下配置选项可以进行修改:
THRESHOLD | 图像识别精确度阈值,0~1之间,越大表示识别精度越高 |
---|---|
THRESHOLD_STRICT | assert语句里图像识别时使用的高要求阈值,默认为0.7 |
RESIZE_METHOD | 可以对图像识别时的UI跨分辨率规律进行重定义 |
LOG_DIR | 脚本运行log存放路径,默认为脚本当前路径 |
LOG_FILE | 运行log的存放文件名,默认为log.txt |
OPDELAY | 每一步操作后等待多长时间进行下一步操作,默认0.1s |
FIND_TIMEOUT | 进行图像查找时的超时时间,默认为20s |
5)注册自定义设备,实现更多复杂操作
在Airtest中,默认支持三种设备:Android, Windows和IOS,在执行脚本的命令行中通过参数 --device Android:///
来指定脚本运行在某一类型设备上。
假如需要对这些设备的某些运行操作进行修改,可以自行实现一种新的设备,并将它注册到Airtest中,即可在运行脚本的时候调用了。
例如,当IDE中的Airtest脚本运行在Windows模式下时,由于截图大小的问题需要对Airtest的Windows代码进行一些修改。因此IDE实现了一个新的类,名为WindowsInIDE:
from airtest.core.win.win import Windows, screenshot
class WindowsInIDE(Windows):
def snapshot(self, filename="tmp.png"):
# 实现了IDE相关的特殊截图操作
pass
然后,在启动器中将这个WindowsInIDE注册到Airtest中::
class AirtestIDECase(AirtestCase):
"""单独在IDE中使用,添加了windows相关的特殊处理"""
def __init__(self):
if get_platform() == "Windows":
import WindowsInIDE
# 注册一种ide专属的windows模式设备到airtest中
from airtest.core.api import G
G.register_custom_device(WindowsInIDE)
super(AirtestIDECase, self).__init__()
注册后,在执行脚本时,修改运行指令中的device参数,就能使用刚才注册的新设备名称来运行脚本了:
python launcher.py test.air --device WindowsInIDE:///
5. 总结:实现自定义启动器的步骤
自定义启动器可以进行配置项的修改和实现更多复杂需求,类似于 unittest
,能够将原先的Airtest脚本作为测试用例来运行。
在IDE中,若想实现一个自定义启动器的步骤如下:
新建一个
custom_launcher.py
文件,在里面实现一个继承了AirtestCase
的类。在
setUp()
和tearDown()
中,添加上自己想要实现的操作。在IDE的选项-配置-Airtest配置中,将刚才实现的
custom_launcher.py
设置为启动器。直接点击运行脚本即可。或者使用命令行的方式运行:
python custom_launcher.py test.air airtest
脚本参数
6. 拓展:启动器的应用实例
Airtest启动器的应用实例,可以参考官方公众号AirtestProject的往期推文: