Airtest笔记(二)

备注:未经博主允许禁止转载

个人笔记(整理不易,有帮助,收藏+点赞+评论,爱你们!!!你的支持是我写作的动力)

笔记目录学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客

个人随笔工作总结随笔_8、以前工作中都接触过哪些类型的测试文档-CSDN博客

参考官方博客:网易AirtestProject 的个人主页 - 动态 - 掘金

参考官方文档:欢迎使用 - Airtest Project Docs

目录

一:录制视频

二:报告

三:截图

(1)自定义截图压缩精度

(2)自定义报告截图的最大尺寸

(3)局部截图/区域截图

(4)用log()接口在报告中显示信息/报错

四:脚本全局设置

五:Firebase打包脚本

六:进一步熟悉

(1)滑动

(2)引用其他脚本

(3)输入无法使用解决方法

(4)输入和删除文字

(5)输入完毕后的回车与搜索键

(6)输入随机数

(7)poco获取节点的text属性

(8)自定义log级别

(9)模拟鼠标右键

七:poco的元素定位

八:坐标介绍

(1)Airtest的坐标系

(2)poco的坐标系

九:Airtest图像识别原理相关

十:截图技巧

(1)截取图标时尽量不要截入过多的背景内容

(2)启动应用

(3)用image editor查看截图识别结果的可信度

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

(5)用坐标进行点击/滑动

(6)用keyevent("BACK")替代返回的截图脚本

(7)画面切换

(8)调整阙值

(9)自定义语句(例如截图列表)

(10)通过poco的选择节点

(11)脚本测试遇到的情况

(12)利用灰度图识别


一:录制视频

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:airtest.core.android.recorder module — airtest 文档

录屏的这两个方法 属于 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": 123456}

# 第一条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 using other 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_app
    • install_app
    • uninstall_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 '123456'"))

# 方法二
dev = connect_device("Android://127.0.0.1:5037/P7CDU18C27000473")
dev.shell(shell("input text '123456'"))

# 方法三
init_device("Android", ime_method="ADBIME")
text("123456")

(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

# 执行截图脚本时
# 如果可信度>阙值,程序判定找到匹配结果
# 如果可信度<阙值,程序判定未找到匹配结果,循环用三种算法继续查找直到超时

十:截图技巧

(1)截取图标时尽量不要截入过多的背景内容

理论上图1的识别度比图2高,不过我看了一下精度,图2的更高

(2)启动应用

start_app() 支持Android和iOS设备,相对用截图脚本来启动应用

start_app("包名")

(3)用image editor查看截图识别结果的可信度

双击截图,进入图片编辑器,点击左上角的 snapshot+recognition 按钮

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

默认情况下,我们的截图脚本都是点击截图的中心位置,即 target_pos=5
对于一张截图来说,总共有9个 target_pos ,当我们把截图的 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)利用灰度图识别

如有三个图片是一样的,前两个背景是红色,第三个是黄色
勾选了rgb,或者在代码加入rgb=True,则进行强制使用色彩图片识别,airtest会将红色的认为是相同的

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值