airtest自动化测试框架
01airtest基础及安装
1.1airtest简介
官网文档:https://airtest.readthedocs.io/en/latest/
Airtest Project:是由网易游戏推出的一整套UI自动化项目,其包含3个部分:Airtest、Poco、AirtestIDE。
Airtest框架:是一个跨平台的、基于图像识别的UI自动化测试框架,适用于游戏和App,支持Windows、Android和iOS平台。是Python的一个第三方包,和Selenium、requests包一样。
Poco框架:是一款基于UI控件识别的自动化测试框架,目前支持Unity3D/cocos2dx-*/Android原生app/iOS原生app/微信小程序,也可以在其他引擎中自行接入poco-sdk来使用(游戏必须接入Poco-SDK)。是Python的一个第三方包,和Selenium、Requests包一样。
AirtestIDE:集成开发环境(IDE,Integrated Development Environment)是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。所以AirtestIDE就是用来编写airtest、Poco自动化代码的编辑器,其功能包含:编写代码、调试、截图、查看App控件、录制、报告等。
1.2 airtest安装方式
1.2.1 python方式
命令
:
pip3 install -U airtest -i https://pypi.douban.com/simple/
说明
︰安装python的AirTest库,通过python代码直接调用AirTest库的Api方法提示
︰此种方式,需要一定python代码基础
1.2.2 AirTestIDE
- 说明:AirTestIDE工具自带python环境,无需单独安装。
- 提示:使用工具可以录制操作,也可以手动编写调用api
1. 官网下载
2. 解压
3. IED启动方式
- 右键以管理员身份运行
AirtestIDE.exe
启动
- 右键以管理员身份运行
兼容模式启动.bat
启动
1.3 环境依赖(真机/模拟器/windows应用)
1.3.1 模拟器连接(采用mumu)
1. 官网下载
- 地址:https://mumu.163.com/
2. 双击安装(为了速度,本次装在固态硬盘)
3. 启动
4. 配置
5.打开开发者模式:多次点击版本号,即可开启开发者模式
6. 打开usb调式模式
7. 连接模拟器
1.3.2 android 真机连接
参考来源:https://blog.csdn.net/chengyq116/article/details/108296042
abd连接
1. 数据线连接手机
2. 打开开发者模式
- “设置”–>“关于手机”–>连续点击“版本号”,即可以打开
3. 选择usb配置模式
- “系统和更新”–>“开发人员选项” -->进入“选择USB配置” --> 选择"RNDIS(USB以太网)"
4. “系统和更新”–>“开发人员选项” -->打开“USB调试”开关
5. adb连接设备
C:\Users\jsonliu>adb kill-server
C:\Users\jsonliu>adb start-server
adb server version (40) doesn't match this client (41); killing...
* daemon started successfully
C:\Users\jsonliu>adb devices
adb server version (40) doesn't match this client (41); killing...
* daemon started successfully
List of devices attached
AN2FUT1B19000032 device
6. 启动adb server
adb kill-server
adb -a -P 5037 nodaemon server # 指定端口
adb -a nodaemon server # 使用默认端口
airtestIDE 连接真机
1.3.3 ios真机连接
环境依赖
1. ios-Tagent :
- 作用︰在手机上创建一个WebDriver服务器,可用于远程控制iOS设备,定位UI元素
- 下载:https://github.com/facebookarchive/WebDriverAgent
- 运行依赖:xcode
2. xcode
- 作用:ios开发集成工具,在这理主要作用为运行WebDriverAgen文件到手机
- 下载:AppSotre->平台搜索xcode
- 运行依赖:开发者账号
- xcode配置(前提:使用xcode打开下载的webDrvierAgent)
- 添加开发者账号(普通的apple ID即可)
- 配置WebDriverAgent ( Team、Product Bundle Identifiier)
- 测试运行WebDriverAgentRunner到手机
3. iproxy
- 作用:设置代理将iPhone端口映射到电脑端口,通过访问电脑的端口访问到手机的端口
- 下载:
brew install libimobiledevice
- 运行:
iproxy 8100 8100
4. 验证
- 查看:打开浏览器输入
http://127.0.0.1:8100/status
出现json格式连接信息 - 抓屏:
http://127.0.0.1:8100/inspector
5. AirtestIDE工具:下载ios版
连接步骤
1. 将真机使用数据线连接电脑
2. 启动xcode并打开配置好的iOS-Tagent项目(菜单-Product->Test启动自动化服务程序)
3. 打开终端运行:iproxy 8100 8100
(启动端口映射服务程序)
4. 启动AirTestIDE工具(连接ios设备-> connect按钮)
5. 注意事项
- 在xcode中点击Test前,检查项目默认终端是否选择真机设备
- 点击在xcode中Test之后,要查看控制信息,如果控制台没任何信息输出,可以等待或者多Test几次,直到控制台输出启动相关信息
- xcode配置iOS-Tagent只需第一次配置,之后使用无需在单独配置,切莫乱修改参数
- 真机设备中,要开启自动化测试和信任iOS-Tagent项目
1.3.4 windows应用连接
1. 点击菜单栏的"选项"–>点击“设置”,在"selenium"栏选择chrome安装的路径
2. 启动浏览器:会默认生成需要导入的库文件代码,不需要手动编写
3. 简单测试
1.3.5 windows应用连接
- 打开要测试的web应用–>“windows窗口连接” -->点击“搜索窗口” -->“refresh” -->
1.4 airtest布局
- ①菜单栏和②快捷按钮:创建新项目,保存项目,运行脚本和检查报告输出
- ③基于图像识别框架:
- ④poco库:支持主流游戏引擎、Android应用程序
- ⑤selenium windows :web项目框架
- 脚本编辑器:
- ⑥脚本编辑区域:
- ⑦log日志:
- ⑧实时手机屏幕:支持使用鼠标事件远程控制设备
1.5 快速使用
1. 新建脚本类型选择
.air AirTest项目
︰生成一个项目名称.air目录,目录下有一个项目名.py文件py纯Python(高级用户)
︰生成一个项目名.py文件- 区别:
- 相同点︰都是python文件
- 不同点∶脚本文件初始化代码不同,一个采用默认值无法看到,一个可以看到默认值,进行修改
2. 元素定位和元素操作
3. 运行脚本
- F5/鼠标右键运行
- 命令行运行:
- 需要安装的一些依赖
- airtest
- pocoui
- pynput
- 需要安装的一些依赖
airtest run 脚本名.air --device Android:///手机设备号 [--log 日志路径]
python -m airtest run 脚本名.air --device Android:///手机设备号 [--log 日志路径]
python -m airtest run 脚本名.air # web运行命令
- bat批处理文件执行测试脚本
echo offw当echo设置off值的时候,那么下面的指令都将只执行而不显示
C:
cd C:\xxxx\airtestFramework
start airtest run 脚本名.air
exit
4. 查看报告(control+L)
5. 常用快捷键
F5
:脚本运行Ctrl+L
:报告查看shift+F5
:脚本停止control+S
:保存
6. 代码注释
""""""
多行注释#
单行注释- 快捷键:
control+?
1.6 常用api
1.6.1 touch
touch(v,times=1,duration=0.01,right_click=False)
- 常用参数:
v
:点击的图片或者坐标times
:点击次数。默认1次duration
:按住时间,默认0.01s
-right click
: windows有效
1.6.2 swipe
- 作用:从屏幕一个位置滑动到屏幕的另一个位置
- 常用参数:
v1
:图片或坐标(x,y)
-v2
:图片或坐标(x,y)vector
:[x,y]录制时自动生成,记录了屏幕中的滑动比例,向右为x周正向,向下为Y轴正向duration
:滑动操作持续时长,默认0.5秒- 坐标点使用时,每组值需要使用()
实现滑屏方式
1. 基于屏幕录制
2.基于图片实现
3_1基于屏幕坐标实现:直接输入坐标
from poco.drivers.unity3d import UnityPoco
poco = UnityPoco()
# 向下滑到底部
poco.swipe([0.5,0.9],[0.5,0])
# 向上滑到顶部
# poco.swipe([0.5,0.1],[0.5,0.9])
3_2基于屏幕坐标实现:根据屏幕尺寸方式
# 获取当前屏幕宽高
width, height = device().get_current_resolution()
# 校准滑动的起点和终点
start_pt = (width / 2, height * 0.9)
end_pt = (width / 2, height * 0.1)
swipe(start_pt, end_pt, duration=2)
1.6.3 text
- 作用:输入文本操作
- 常用参数:
text
:要输入的文本(注︰输入的位置为当前页面默认焦点元素一般配合touch一起使用)enter
:完整输入后自动执行Enter操作,默认为Truesearch
:完成输入后强行执行search操作,默认为False
1.6.4 keyevent
- 作用:模拟键盘按键输入,支持键码
- 键常用参数:
keyname
:键码或键名- android keycode参考:https://www.cnblogs.com/findyou/p/5614178.html
- 常用键名:键码
键名 按键 键码 KEYCODE_ENTER 回车 66 KEYCODE_FORWARD_DEL 删除 112 KEYCODE_CLEAR Clear 28 KEYCODE_TAB Tab键 61 KEYCODE_HOME Home 3 KEYCODE_BACK 返回键 4 KEYCODE_SEARCH 搜索键 84 KEYCODE_DEL 退格键 67 KEYCODE_SPACE 空格键 62
1.6.5 snapshot
- 作用:截取当前屏幕图片,可以在测试报告显示。
- 常用参数:
Filename
:保存截屏为指定文件msg
:描述测试点,可以在HTML报告中呈现
1.6.6 wait
- 作用:等待某个元素出现,如果出现返回元素的中心点坐标,否则抛出TargetNotFoundError异常
- 常用参数:
v
:图片timeout
:等待超时,默认为20sinterval
:每次匹配的时间间隔,默认为0.5sintervalfunc
:图片没有找到就执行后面的函数,默认为None
1.6.7 exists
- 作用:判断图片是否存在,如果存在就返回图片的中心坐标,不存在就返回False
- 常用参数
v
:图片return
:返回值,如果存在就返回图片的中心坐标,不存在返回False
1.6.8 sleep
- 作用:暂停时间
- 常用参数
secs
:延迟时间(s),默认1.0s
1.7 断言
1. assert_exists
- 作用︰断言(判断)页面存在元素
- 常用参数
v
:图片(要判断页面是否存在元素)msg
:描述测试点return
:找到图片则返回图片中心点坐标,否则将raise AssertionError
2. assert_not_exists
- 作用:断言(判断)页面不存在元素
- 常用参数
v
:图片(注:判断当前页面不存在图片元素,不存在通过,存在失败)msg
:描述测试点(测试报告中显示)
3. assert_equal
- 作用:判断第一个值与第二个值相等
- 常用参数
first
:第一个值second
:第二个值msg
:描述此断言语句对应的测试点内容
4. assert_not_equal
- 作用:判断第一个条目与第二个条目不相等
- 常用参数
-first
:第一个值
-second
:第二个值
-msg
:描述此断言语句对应的测试点内容
1.8 综合demo(同花顺登陆)
- 大体流程:点击头像–>点击账号登陆 -->输入用户名、密码 --> 勾选协议 -->点击登陆 -->断言登陆成功(用户id) --> 点击设置 --> 拉到页面底部 --> 点击“退出当前账号” --> 确定 -->判断"登陆账号 体验更多服务存在" 再 back
02 web应用程序自动化(酷狗音乐播放)
大体流程:点击搜索框–>输入歌名–>点击播放
- IDE运行
脚本:
# -*- encoding=utf8 -*-
__author__ = "jsonliu"
from airtest.core.api import *
auto_setup(__file__)
for i in range(3):
if exists(Template(r"tpl1654356304880.png", record_pos=(0.033, -0.316), resolution=(1018, 720))):
touch(wait(Template(r"tpl1654356314479.png", record_pos=(0.031, -0.316), resolution=(1018, 720)))
)
touch(wait(Template(r"tpl1654356195086.png", record_pos=(-0.045, -0.316), resolution=(1018, 720)))
)
text("我会好好的")
sleep(1)
touch(wait(Template(r"tpl1654355322512.png", record_pos=(-0.296, -0.065), resolution=(1020, 720)))
)
touch(wait(Template(r"tpl1654355071000.png", record_pos=(-0.298, 0.109), resolution=(1020, 720)))
)
if exists(Template(r"tpl1654355241031.png", record_pos=(-0.392, 0.141), resolution=(1020, 720))):
touch(Template(r"tpl1654355241031.png", record_pos=(-0.392, 0.141), resolution=(1020, 720)))
03 微信小程序(平安证券为例)
1.前置条件:
- airtest连接真机/模拟器
- 提示:真机存在闪退现象
- 安装微信app
- 注册并成功登录微信账号
2.实现功能:
- 打开微信–>搜索“平安证券”小程序
- 点击“我的”–>点击“搜索”
- 点击基金搜索框–>清除输入框–>输入基金编码/名称的全部值或部分值
- 点击“+” —>截取当前屏幕—>断言文本等于“自选已添加”
- 点击“√” —>断言文本显示“自选已删除”
- 环境清理:退出返回到微信首页
3.大体流程
- 创建项目
- 编写脚本
- 运行测试用例
- 查看报告
4.自动化脚本
# -*- encoding=utf8 -*-
__author__ = "jsonliu"
from airtest.core.api import *
auto_setup(__file__)
ym = "com.netease.nie.yosemite/.ime.ImeService"
bd = "com.baidu.input_hihonor/com.baidu.input_huawei.ImeService"
def set_ime(ime):
# 输入法切换
shell("ime enable " + ime) # 启动指定输入法
shell("ime set " + ime) # 设置指定输入法
# set_ime(ym)
def safe_keyboad(num_l):
l = []
for i in num_l:
if i==0:
num = wait(Template(r"tpl1654415856731.png", record_pos=(0.0, 0.902), resolution=(1080, 2340)))
elif i==1:
num = wait(Template(r"tpl1654415157979.png", record_pos=(-0.33, 0.427), resolution=(1080, 2340)))
elif i==2:
num = wait(Template(r"tpl1654415172531.png", record_pos=(-0.002, 0.428), resolution=(1080, 2340)))
elif i==3:
num = wait(Template(r"tpl1654415225016.png", record_pos=(0.333, 0.424), resolution=(1080, 2340)))
elif i==4:
num = wait(Template(r"tpl1654415682693.png", record_pos=(-0.334, 0.586), resolution=(1080, 2340)))
elif i==5:
num = wait(Template(r"tpl1654415692437.png", record_pos=(-0.001, 0.589), resolution=(1080, 2340)))
elif i==6:
num = wait(Template(r"tpl1654415704268.png", record_pos=(0.333, 0.589), resolution=(1080, 2340)))
elif i ==7:
num = wait(Template(r"tpl1654415733890.png", record_pos=(-0.331, 0.748), resolution=(1080, 2340)))
elif i ==8:
num = wait(Template(r"tpl1654415818604.png", record_pos=(0.002, 0.741), resolution=(1080, 2340)))
elif i == 9:
num = wait(Template(r"tpl1654415826674.png", record_pos=(0.333, 0.747), resolution=(1080, 2340)))
l.append(num)
return l
def open_wechat_and_search():
# 1. 打开微信并搜索“平安金融”小程序
touch(wait(Template(r"tpl1654419360669.png", record_pos=(-0.353, 0.555), resolution=(1080, 2340)))
)
touch(wait(Template(r"tpl1654409526583.png", record_pos=(0.324, -0.934), resolution=(1080, 2340)))
)
touch(wait(Template(r"tpl1654410169024.png", record_pos=(-0.338, -0.929), resolution=(1080, 2340)))
)
keyevent("clear")
text("平安证券")
keyevent("66")
touch(wait(Template(r"tpl1654410492936.png", record_pos=(-0.143, -0.245), resolution=(1080, 2340)))
)
for i in range(3):
if exists(Template(r"tpl1654423805902.png", record_pos=(-0.322, -0.294), resolution=(720, 1280))):
touch(wait(Template(r"tpl1654423613589.png", record_pos=(-0.257, -0.172), resolution=(720, 1280)))
)
break
else:
sleep(2)
def fund_search():
# 2. 搜索对应基金并添加自选
touch(wait(Template(r"tpl1654423981398.png", record_pos=(0.246, 0.826), resolution=(720, 1280)))
)
touch(wait(Template(r"tpl1654422851414.png", record_pos=(-0.372, -0.42), resolution=(1080, 2340)))
)
sleep(10)
touch(wait(Template(r"tpl1654424437787.png", record_pos=(0.433, -0.683), resolution=(720, 1280)))
)
touch(wait(Template(r"tpl1654424451052.png", record_pos=(0.3, -0.439), resolution=(720, 1280)))
)
for i in range(3):
if exists(Template(r"tpl1654424792042.png", record_pos=(-0.01, -0.686), resolution=(720, 1280))):
touch(wait(Template(r"tpl1654424870398.png", record_pos=(-0.028, -0.569), resolution=(720, 1280)))
)
else:
sleep(5)
keyevent("28")
text("诺安成长")
keyevent("66")
touch(wait(Template(r"tpl1654422056528.png", record_pos=(0.433, -0.388), resolution=(1080, 2340)))
)
snapshot(msg="添加自选")
assert_equal("自选已添加","自选已添加")
touch(wait(Template(r"tpl1654422150769.png", record_pos=(0.43, -0.387), resolution=(1080, 2340)))
)
assert_equal("自选已删除","自选已删除")
def test_fund_add_optional():
# 退回到手机桌面
while not exists(Template(r"tpl1654419360669.png", record_pos=(-0.353, 0.555), resolution=(1080, 2340))):
keyevent("4")
open_wechat_and_search()
fund_search()
# 退回到微信首页
while not exists(Template(r"tpl1654419202677.png", record_pos=(0.288, -0.925), resolution=(1080, 2340))):
keyevent("4")
test_fund_add_optional()
04 微信公众号(平安证券)
测试方法与小程序差不多