学习笔记-airtest自动化
笔记目录:https://blog.csdn.net/weixin_/article/details/
昨天下了雨,今天刮了风,明天太阳就出来了
录制视频
报告
- 自定义截图压缩精度
- 自定义报告截图的最大尺寸
- 局部截图/区域截图
- 用log()接口在报告中显示信息/报错
截图
脚本全局设置
Firebase打包脚本
进一步熟悉
- 滑动
- 引用其他脚本
- 输入无法使用解决方法
- 输入和删除文字
- 输入完毕后的回车与搜索键
- 输入随机数
- poco获取节点的text属性
- 自定义log级别
- 模拟鼠标右键
poco的元素定位
坐标介绍
Airtest图像识别原理相关
截图技巧
一:录制视频
airtest1.1.6支持 在 --recording 参数后面加上一个文件名来命名录屏文件 ,例如 --recording test.mp4 ,如果有不止一台手机在运行,会把文件命名为 手机名_test.mp4 。
#开始录制/结束录制 start_recording() 和 stop_recording()
【回顾】在使用纯py文件编写脚本的时候,如使用了android手机,初始化连接
if not cli_setup(): auto_setup(__file__, logdir="./log", devices=["Android://127.0.0.1:5037/FIFIMFFEPVAIWCU8"])
devices:adb server所在主机的ip:adb port / 序列号,其中FIFIMFFEPVAIWCU8是序列号,通过这种方式可以查出

API:https://airtest.readthedocs.io/zh_CN/latest/all_module/airtest.core.android.recorder.html?highlight=recording#airtest.core.android.recorder.Recorder.start_recording
录屏的这两个方法 属于 Recorder(adb) 类,需要实例化这个类,才能通过实例去调用里面的方法
adb = ADB(serialno="FIFIMFFEPVAIWCU8") recorder = Recorder(adb) # 开始录屏 recorder.start_recording(max_time=10) sleep(3.0) # 结束录屏 recorder.stop_recording(output="dy.mp4")
在录制的时候,涉及密码输入,会出现黑屏,在安全设置中,把安全键盘之类的设置关掉 ,或者是 关掉其它一些防止恶意截屏录屏的设置。
二:报告
__author__ = "漫步云端" __title__ = "打开我的页面" __desc__ = """ 前提:无; 步骤1:打开app; 步骤2:点击我的; 步骤3:断言; """

可以使用命令行:airtest info 脚本路径, 可以获得airtest解析出来的脚本信息,类似这样的返回值
{“name”: “untitled.air”, “path”: “untitled.air”, “author”: “user”, “title”: “脚本标题”, “desc”: “用例描述”}
三:截图
(1)自定义截图压缩精度
① 使用命令行启动,airtest run ... --compress quality
② 在脚本中自定义,优先级高于命令行,取值范围是1-99的正整数,airtest默认取10
import airtest.core.api import * ST.SNAPSHOT_QUALITY = xxx # [1, 99] # 在报告的该touch步骤中,保存的截图的精度为全局精度xxx touch(xx) # snapshot保存的截图精度也是全局精度xxx snapshot(filename='./ok.jpg',msg="完成截图")
③ 设置某张图片的压缩精度
snapshot(quality=my_quality)
(2)自定义报告截图的最大尺寸
# 设置截图尺寸不超过600*600,如果不设置,默认为原图尺寸 ST.IMAGE_MAXSIZE = 600 # 在报告的该touch步骤中,保存的截图尺寸不超过600*600 touch(xx) # 截图质量为90,尺寸不超过1200*1200 snapshot(filename="ok1.png", msg="ok1", quality=90, max_size=1200) # 不设置的情况下,默认采用ST中的全局变量的数值,即600*600 snapshot(msg="ok2")
(3)局部截图/区域截图
如(0,160)(1067,551)
# crop_image()方法在airtest.aircv中,需要引入 from airtest.aircv import * screen = G.DEVICE.snapshot() # 局部截图 screen = aircv.crop_image(screen,(0,160,1067,551)) # 保存局部截图到log文件夹中 try_log_screen(screen)

(4)用log()接口在报告中显示信息/报错
【回顾】airtest报错in recv raise socket.error(“socket connection broken”)
原因是连接参数少写了一个
【回顾】看下API:airtest.core.android.adb module,导包写from airtest.core.helper import *,避免忘记导包
args, 可以是字符串或是 traceback 对象(异常),现在还支持传入非字符串
timestamp, 参数可以自定义当前这条 log 的时间戳,默认为当前时间
desc , 自定义一个 log 标题
ata = {"test": 123, "time": } # 第一条log,步骤名显示title,截取一张屏幕截图 log(data, timestamp=time.time(), desc="title", snapshot=True) # 第二条log,标记为报错步骤并截取一张屏幕截图 try: 1/0 except Exception as e: log(e, snapshot=True) # 第三条log,显示传入的字符串 log("中文") # 这样也行 import traceback try: xxxx except: log("出错啦", traceback. format_exc())



四:脚本全局设置
在airtest.core.settings里,提供了部分全局默认属性,可以修改全局设置,如:
from airtest.core.api import * # airtest.core.api中包含了一个名为ST的变量,即为全局设置 ST.THRESHOLD = 0.8
如touch,如果在里面有指定threshold,则使用指定的,如果没有,则默认使用全局属性。
常见的全局属性:
- RESIZE_METHOD = staticmethod(cocos_min_strategy)
分辨率适配规则
https://airtest.doc.io.netease.com/IDEdocs/airtest_framework/1_script_settings/
比如,参数都不用动,中间的内容是根据原属性,改为我要的缩放规则即可

- THRESHOLD = 0.7 # [0, 1]
图像识别的阈值
- THRESHOLD_STRICT = 0.7 # [0, 1]
只用于assert_exists(图片)接口
- OPDELAY = 0.1
每一个步骤的操作之间都会有一小段时间间隔,默认是0.1秒
- FIND_TIMEOUT = 20
图像查找时间,使用了该接口:touch、double_click、swipe(如果是a图片滑到b图片,只有a图片使用了该接口)、wait(在没有使用timeout的情况下使用了该接口)、assert_exists
- FIND_TIMEOUT_TMP = 3
图像查找时间,使用了该接口:swipe(如果是a图片滑到b图片,只有b图片使用了该接口)、exists、assert_not_exists
- PROJECT_ROOT = os.environ.get(“PROJECT_ROOT”, “”) # for
usingother script
可以通过设定一个默认项目根目录PROJECT_ROOT,让使用using接口时能够在当前根目录下寻找别的子脚本,无需填写完整路径,让脚本之间相互调用使用更加方便
from airtest.core.api import * ST.PROJECT_ROOT = "/User/test/project" # test1.air的实际路径为/User/test/project/test1.air using("test1.air") #调用其他的脚本 from test1 import test
五:Firebase打包脚本
限制:
- 安卓原生应用的poco无法使用,因为无法从一个app去启动另外一个app。但是游戏引擎的poco均可使用。
- 部分airtest接口,无法使用该方式执行,例如
clear_appinstall_appuninstall_app
- 由于启动脚本时,会出现kivy闪屏图片,所以脚本以start_app()开始
- 打包时,因为涉及到文件删除操作,所以不要使用目标包体的目录(有些用户习惯性直接在生成包体的目录打开命令行安装,会导致无法进行下一次打包)
原理:

步骤
1(环境配置):java(jdk,非jre)、配置jdk环境,输入jarsigner,没报错即可(如果出现不是内部命令,则将环境配到系统变量即可)
2(打包流程)

然后将该apk和被测应用安装在手机上,
然后用adb指令启动测试脚本 adb shell am instrument -w com.netease.open.airbase/android.support.test.runner.AndroidJUnitRunner
六:进一步熟悉
(1)滑动
swipe_along目前只有在使用了默认的 minitouch 模式(Android10使用 maxtouch )时才能使用
自定义点击或滑动操作的方案:https://airtest.doc.io.netease.com/IDEdocs/faq/3_api_faq/
(2)引用其他脚本
如果需要引用的子脚本路径统一都放在某个目录下,可以通过设定一个默认项目根目录 PROJECT_ROOT ,让使用 using 接口时能够在当前根目录下寻找别的子脚本,无需填写完整路径
如jb1.air路径是/User/test/project/jb1.air 其他脚本引用它则: ST.PROJECT_ROOT = "/User/test/project" using("jb1.air") 记住别漏了导入方法语句 from jb1 import xx方法
(3)输入无法使用解决方法
#如果遇到一些设备无法使用text(),可以这样 # 方法一 dev = init_device("Android") dev.shell(shell("input text ''")) # 方法二 dev = connect_device("Android://127.0.0.1:5037/P7CDU18C") dev.shell(shell("input text ''")) # 方法三 init_device("Android", ime_method="ADBIME") text("")
(4)输入和删除文字
#删除输入框内容 for i in range(10): keyevent("67") #poco写法:将输入框内容设置为空字符串 poco("xxx").set_text("") # 设置文字 # airtest写法: text("哈哈") #poco写法:注意XXX是可输入控件 poco("XXX").set_text("哈哈")
(5)输入完毕后的回车与搜索键
text接口有默认参数enter=True,即输入完成后回车,部分输入框是search=True
注意:输入法的回车和换行不同于keyevent事件
(6)输入随机数
#输入随机数 import random r = random.randint(1,100) text(str(r))
(7)poco获取节点的text属性
#poco获取节点的text属性 a = poco(text="cs") a.get_text() a.get_name()
(8)自定义log级别
import logging logger = logging.getLogger("airtest") logger.setLevel(logging.ERROR)
(9)模拟鼠标右键
# 获取当前连接的窗口 dev = device() # 拿到鼠标,并模拟鼠标的右键点击操作 dev.mouse.right_click(coords=(1920,100))
七:poco的元素定位
(1)借助IDE的poco辅助窗生成元素定位脚本
点检视器按钮(前两个都行),点元素,就能看到该元素所在的位置,点那个定位就能生成脚本(区别是第一个按钮锁住页面)
点录制按钮,点元素,然后就生成了脚本,去掉.click()即可
(2)利用基本选择器进行元素定位
(3)利用相对选择器进行元素定位
(4)利用空间顺序选择器进行元素定位
八:坐标介绍
(1)Airtest的坐标系
# Airtest的坐标系 # (1)touch-使用的是(x, y)绝对坐标 # (2)swipe-滑动起点和终点使用的是(x, y)绝对坐标

(2)poco的坐标系
poco点击默认是点在 anchorPoint [ˈæŋkə(r) pɔɪnt]上的,每个UI都会有一个 anchorPoint ,也就是检视器(Inspector)中UI包围盒的那个红点,大部分情况下 anchorPoint 都在UI包围盒的正中央


# (1)使用局部坐标系的click接口 # 引入局部坐标系来表示相对于某UI的坐标。 # 局部坐标系以UI包围盒左上角为原点,向右为x轴,向下为y轴,包围盒宽和高均为单位一。(如上图) # 局部坐标系可以更灵活地定位UI内或外的位置,例如(0.5, 0.5)就代表UI的正中央,也就相当于我们上文中默认的anchorPoint;超过1或小于0的坐标值则表示UI的外面。 # 点击 anchorPoint 以外的其他指定位置时,可以传一个参数到 click 方法中,这个参数是一个用list或tuple表示的2维向量, # 其 [x, y] 值分别表示相对于包围盒左上角的偏移量,左上角为 [0, 0] ,右下角为 [1, 1] poco(text="口红").click([0,0]) # 改变以anchorPoint为起点,也可以使用focus方法 poco(text="口红").focus([0,0]).click()
# (2)使用归一化坐标系的swipe接口 # 将屏幕宽和高按照单位一来算,这样UI在poco中的宽和高其实就是相对于屏幕的百分比大小 # 好处:不同分辨率设备之间,同一个UI的归一化坐标系下的位置和尺寸是一样的,有助于编写跨设备测试用例 # 屏幕正中央一定是(0.5, 0.5) # 也是以 anchorPoint 为起点,改变起点用focus 方法

假如在游戏中(如中心点(0.5,0.5)),那我想往右上走(如走到(0.9,0.1)),那我的偏移量为(0.4,-0.4),距离为sqrt(0.4*0.4)
cs = poco("xx") cs.swipe('up') # 向上向右滑动,duration是滑动时长 cs.swipe([0.4, -0.4], duration=0.5)
九:Airtest图像识别原理相关
默认情况下,Airtest会尝试用 SURFMatching 、TemplateMatching 和 BRISKMatching 这三种算法来进行图像识别
其中 TemplateMatching 属于 模板匹配算法,而 SURFMatching 和 BRISKMatching 则属于 特征点匹配方法。简单点说,模板匹配算法依赖 特征向量 来进行图像匹配,而特征点匹配算法则是依赖于 图像的特征点 。
# 程序如何根据算法结果判定是否找到匹配的截图? # 阙值 和 可信度 ,他们的取值范围都是[0,1]。在每一条图像识别的脚本中,都会有1个用于结果筛选的阙值,默认值为0.7 # 执行截图脚本时 # 如果可信度>阙值,程序判定找到匹配结果 # 如果可信度
<阙值,程序判定未找到匹配结果,循环用三种算法继续查找直到超时< code="">阙值,程序判定未找到匹配结果,循环用三种算法继续查找直到超时<>
十:截图技巧
(1)截取图标时尽量不要截入过多的背景内容

理论上图1的识别度比图2高,不过我看了一下精度,图2的更高
(2)启动应用
start_app() 支持Android和iOS设备,相对用截图脚本来启动应用
start_app("包名")
(3)用image editor查看截图识别结果的可信度
双击截图,进入图片编辑器,点击左上角的 snapshot+recognition 按钮

(4)用target_pos点击截图的不同位置

方法1:双击截图,进入图片编辑器,可以修改该值

方法2:可以直接写成代码的形式
touch(Template(r"1.png", target_pos=6, record_pos=(-0.434, -0.773), resolution=(900, 1600)))
(5)用坐标进行点击/滑动
如app的介绍页,由于图片经常变化,维护麻烦,可以使用坐标
(6)用keyevent(“BACK”)替代返回的截图脚本
Android设备可以使用这个
(7)画面切换
画面切换的时候,可以多使用wait或者sleep,再进行点击操作

(8)调整阙值
调的太低,容易把错误的结果通过
调的太高,容易把正确的结果不通过
方法1:双击截图,进入图片编辑器,可以修改该值

:方法2:
touch(Template(r"1.png", threshold=0.8, record_pos=(-0.021, 0.121), resolution=(900.0, 1600.0)))
方法3:全局的 threshold
from airtest.core.setting import Settings as ST ST.THRESHOLD = 0.7 # 其他语句的默认阈值
注意:只适用于除断言语句之外的截图语句
断言只能通过下述方式进行设置:
from airtest.core.setting import Settings as ST ST.THRESHOLD_STRICT = 0.7
(9)自定义语句(例如截图列表)

(10)通过poco的选择节点
比如删除(多选框)
(11)脚本测试遇到的情况
①写好的截图脚本在更换一台不同分辨率的手机/更换一个环境之后,就经常遇到执行失败的报错:
airtest.core.error.TargetNotFoundError: 'Picture Template(E:\\untitled.air\\1.png) not found in screen'
原因:图片识别有误差,在不同分辨率,或画面发生了一定变化
解决方法:修改截图
②运行后查看报告,发现识别出来的位置是一个错误的位置,但是airtest当做是正确的
解决方法:调整截图/阀值
③运行后查看报告,报告里能看到识别到了正确的位置,也点击成功了,但是实际上没有成功点到。
原因:如果有连续点击操作,屏幕内容可能会不断变化,有时候会导致脚本明明运行到了点击操作却发现没有生效的情况。这是因为屏幕内容切换速度过快,界面还未稳定的同时airtest就进行了元素识别和操作,导致没有成功点击到对应元素。
解决方法:给个等待时间
(12)利用灰度图识别

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/225212.html原文链接:https://javaforall.net
