AirtestIDE使用


AirtestIDE使用

Airtest和poco(绝对坐标与相对坐标)

Airtest的坐标系
airtest的touch接口,实际上点击的是一个 (x, y)绝对坐标,在截图语句中,airtest会先根据传入的图片找到该图片在当前画面上的位置坐标,然后进行点击(查看log日记可以看到)。

而airtest的swipe接口,滑动起点和滑动终点使用的也是(x, y)绝对坐标。

根据设备分辨率,计算合适的坐标进行操作。

width, height = device().get_current_resolution()
start_pt=(width*0.9,height/2)
end_pt=(width*0.1,height/2)
for i in range(5):
    swipe(start_pt, end_pt)
    sleep(1)

使用屏幕坐标的功能查看坐标

打开IDE的选项>–设置,可以看到在Device设置部分,有实时坐标显示和相对坐标显示俩个选项

勾选实时坐标选项,可以实时在手机屏幕画面上显示出鼠标位置的坐标,方便大家获取绝对坐标。此时 点击鼠标右键,还可以自动将当前坐标信息复制到剪贴板中

在勾选了实时显示坐标的情况下,再勾选相对坐标选项,将会以(0, 0) 到 (1, 1) 为范围显示出相对坐标。使用相对坐标可以避免跨分辨率的操作点超出屏幕的问题,使坐标操作兼容性更好。

poco的坐标系

使用局部坐标系的click接口

首先我们需要知道点击默认是点在 anchorPoint 上的,每个UI都会有一个 anchorPoint ,也就是检视器(Inspector)中UI包围盒的那个红点,大部分情况下 anchorPoint 都在UI包围盒的正中央。

引入局部坐标系来表示相对于某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] 。

想改变以anchorPoint为起点,也可以使用focus方法:

poco(“com.miui.home:id/workspace”).offspring(“天气”).offspring(“com.miui.home:id/icon_icon”).focus([0,0]).click()

使用归一化坐标系的swipe接口

归一化坐标系就是将屏幕宽和高按照单位一来算,这样UI在poco中的宽和高其实就是相对于屏幕的百分比大小了,好处就是不同分辨率设备之间,同一个UI的归一化坐标系下的位置和尺寸是一样的

joystick = poco('movetouch_panel').child('point_img')
joystick.swipe('up')
joystick.swipe([0.2, -0.2])  #45度向右上方
joystick.swipe([0.2, -0.2], duration=0.5)

Airtest封装的ADB操作

问题:遇到ADB版本冲突的报错:
raise AdbError(stdout, stderr)
airtest.core.error.AdbError: stdout[] stderr[adb server version (36) doesn’t match this client (40); killing…
could not read ok from ADB Server
而我们不清楚电脑里面那么多ADB,究竟哪些是40版本,哪些是36版本时,我们就可以使用 adb version 查看当前的ADB版本,然后将电脑里面所有的ADB替换成同一个版本,从而解决这个版本冲突的问题

adb教程

__author__=AirtestProject
from airtest.core.api import *
from airtest.core.android.android import *
auto_setup(__file__,devices=["Android:///"],compress=90)
android = Android()
#打印本地设备的序列号
print(android.get_default_device())
#打印设备上安装的第三方应用的包名列表
#等同于:adb -5 《设备序列号> shell pm list packages -3
print(android.list_app(third_only=True))

1)返回应用的完整路径:path_app()
android = Android()
android.path_app(“com.netease.cloudmusic”)
2)检查应用是否存在于当前设备上:check_app()
android = Android()
android.check_app(“com.netease.cloudmusic”)
3)停止应用运行:stop_app()
stop_app(“com.netease.cloudmusic”)

启动应用:start_app()

start_app(“com.netease.cloudmusic”)

清除应用数据:clear_app()

clear_app(“com.netease.cloudmusic”)
4)安装应用:install_app()
install(r”D:\demo\tutorial-blackjack-release-signed.apk”)

卸载应用:uninstall_app()

uninstall(“org.cocos2dx.javascript”)

5)关键词操作:keyevent()
keyevent(“HOME”)
keyevent(“POWER”)
6)唤醒设备:wake()
wake()
7)返回HOME:home()
home()
8)文本输入:text()
text(“123”)
9)检查屏幕是否打开:is_screenon()
android = Android()
android.is_screenon()
10)检查设备是否锁定:is_locked()
android = Android()
android.is_locked()
11)获取当前设备的分辨率:get_current_resolution()
android = Android()
android.get_current_resolution()
12)其它adb shell命令:shell()
shell(“ls”)
shell(“pm list packages -3”)

截图脚本

Airtest会尝试用 SURFMatching 、TemplateMatching 和 BRISKMatching 这三种算法来进行图像识别

阙值 和 可信度 ,他们的取值范围都是[0,1]。在每一条图像识别的脚本中,都会有1个用于结果筛选的阙值,默认值为0.7。
当上述三种算法在执行过程中识别到初始结果时,就会计算出来这个初始结果的可信度,当 可信度>阙值 的时候,程序会认为 找到了最佳的匹配结果 ;而当 可信度<阙值 的时候,程序则会认为 没有找到最佳的匹配结果 。

在执行截图脚本的时候,查看log窗口,观察算法识别结果的可信度:

① 可信度>阙值,程序判定找到匹配结果

② 可信度<阙值,程序判定未找到匹配结果,循环用三种算法继续查找直到超时

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

  • 打开应用尽量使用start_app而不是截图脚本,

    start_app(“com.netease.cloudmusic”) #打开网易云音乐

  • 用image editor查看截图识别结果的可信度

录制/编写好1条截图脚本之后,无需运行,可以直接双击截图,进入图片编辑器,点击左上角的 snapshot+recognition 按钮,即可查看截图在当前页面的识别情况,包含识别出来的位置以及识别结果的可信度

  • 巧用target_pos点击截图的不同位置

截图脚本都是点击截图的中心位置,即 target_pos=5 。对于一张截图来说,总共有9个 target_pos ,当我们把截图的 target_pos 设置成不同的值时,脚本会点击在截图不同的位置上

1 2 3

4 5 6

7 8 9

打开图片编辑器,右侧可以修改 target_pos 的值

修改完成之后,把截图脚本切换成代码模式,我们就可以看到此时的截图脚本里面多了 target_pos 这个参数:

当精准截图(仅截取某个按钮/图标)不能满足唯一定位时,我们可以考虑加大截图范围,增加更多的特征点,确保截图定位的准确性

  • 巧用坐标进行点击/滑动,如首页的轮播图
  • 巧用keyevent(“BACK”)替代返回的截图脚本
  • 录制功能要注意截图的兼容性
  • 画面切换的时候,可以多使用wait或者sleep,再进行点击操作
  • 合理调整阙值

双击截图打开图片编辑器,在右侧修改截图的阙值

设置全局的 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

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

对应截图纳入搜索列表。代码脚本如下:

picList = [pic1,pic2,pic3]  # 截图的图片对象列表
for pic in picList:
     pos = exists(pic)
     if pos:
         touch(pos)
         break

注意:如果for循环中没有break语句,会导致次逻辑运行时将所有的图片都找一遍(找到后执行touch),而非找到合适结果立即返回

  • 用poco语句代替截图脚本

    取前3行遍历节点的脚本

select=list(poco("android.widget.LinearLayout").offspring("com.netease.cloudmusic:id/dragSortplayListlist").child("android.view.view"))
for s in select[:3]:
  s.offspring("com.netease.cloudmusic:id/checkedImage").click()

tidevice-不依赖 xcode 启动 WebDriverAgent

不依赖 xcode 启动 WebDriverAgent 完成设备连接

1)安装tidevice库

在本地python环境中,使用 pip install tidevice 命令安装 tidevice 库。

另外需要注意的是,目前 tidevice 库仅支持安装在 python3.7及以上版本 中。

2)常用的tidevice命令

查看已连接设备:

tidevice list

查看设备上的第三方应用包名:

tidevice applist

指定设备安装:

# $UDID可以使用tidevice list命令查看
tidevice -u $UDID  install D:/test.ipa
# 或者
tidevice -u $UDID install https://example.org/example.ipa

更多详细的功能可以查看 tidevice 的github文档:https://github.com/alibaba/taobao-iphone-device

3)确保手机上已经安装上WebDriverAgent

对于未跑过自动化的iOS设备,我们需要先检查设备上是否安装好了WebDriverAgent这个APP,如未安装,则可以通过以下2种方式安装:

① 将iOS设备与一台Mac连接,然后使 用xcode编译源码安装 ,成功安装WebDriverAgent即可脱离Mac;

② 使用tidevice的安装命令,将 开发者证书重签名 的 WebDriverAgent.ipa 安装到iOS设备上

在IDE连接tidevice启动的iOS

1)用数据线将iOS设备与Windows电脑连接
2)查看设备里WebDriverAgent的BundleID
tidevice applist

3)指定BundleID启动

tidevice xctest -B com.gameappium.WebDriverAgentRunner.xctrunner

WebDriverAgent 启动成功后,后台挂着该命令行窗口即可。
4)在IDE的设备连接窗口连接iOS设备
最后打开 最新版 的IDE(1.2.8版本),在连接iOS设备框中输入:

DeviceIdentifier可以在启动的信息中查看

http+usbmux://DeviceIdentifier
最后点击连接即可

5)补充另一种启动方式

tidevice wdaproxy -B com.gameappium.WebDriverAgentRunner.xctrunner --port 8200

与步骤3)中的xctest启动方式不同的是,使用wdaproxy启动之后,我们可以在浏览器中使用http://localhost:8200/status来访问到这个iOS

用脚本连接windows窗口

窗口句柄是每个Windows窗口对象拥有的独一无二的32位无符号整数,而且每次打开窗口,旬柄的数值都会变化。
使用句柄连接窗口的脚本我们可以这么写auto_setup( file_,devices=[“Windows:///133194”])

大多数情况下,搜索窗口的title比较不容易变化,所以我们可以写一个正则表达式去匹配到待测窗口的title。

例如匹配“吹梦到西洲”后面跟着换行符以外的任意字符的窗口titleauto_setup( file_,devices=[“Windows:///?title_re=吹梦到西洲.*”])

如果不需要指定某个窗口应用的话,我们还可以使用如下代码直接连接整个桌面来做自动化:
auto setup( file_,devices=[“Windows:///“])

poco定位器和操作

①基本选择器
利用元素的一些基本属性来进行定位,比如name、text等等poco(name=”网易云音乐”)
②相对选择器
利用控件之间的父子关系、爷孙关系和兄弟关系等来定位控件,例如parent()、child()、offspring()等poco(“LinearLayoutCompat”).child(“搜索”)
③空间顺序选择器
常用于UI树中多个相同名称的节点定位,根据节点在U1树的索引顺序进行定位,索引坐标从0开始
poco(“mainActivityTab”).offspring(“aActionBar$Tab”)[0]

①点击操作:
poco(“star_single”).click()

poco(‘star_single’).long_click()
②)读取和设置控件的属性
poco(“star_single”).get_name()
poco(“star_single”).attr(‘name’ )

poco(“star_single”).get_text()

poco(“pos_input”).set_text(“123”)

poco(“pos_input”).setattr(‘text’,”456”)
③判断元素是否存在
poco(XXX).exists()
④)拖动与滑动
poco(“star”).drag_to(poco(“shell”))

⑤内部偏移和外部偏移:
poco(“pearl”).focus([0.1,0.1]).long_click()

poco(“pearl”).focus([0.9,0.9]).long_click()

poco(“pearl”).focus([0.5,-3]).long_click ()
⑥遍历元素:
for star in poco(“playDragAndDrop”).child(“star”):star.drag_to(poco(“shell”))
⑦等待事件:
poco(“bomb”).wait_for_appearance()poco(“bomb”).wait_for _disappearance ()
yellow = poco (“yel low”)blue = poco (“blue”)
black = poco (“black”)
poco.wait for all([yellow,blue,black])poco.wait for any([bomb, yeilow, blue])

输入backspace键

driver.find element by id(“kw”).send keys(Keys.BACK_SPACE)

unity游戏接入poco-sdk

Poco的支持情况
Android和iOS原生直接支持,无需嵌入任何

代码引擎渲染的项目都需要事先接入Poco-SDK才能查看UI树

目前poco支持umity、Coc0s2dx-lua、Cocos2dx-js、Cocos-creator、UE4、Egret……

在unitv项目中接入Poco-SDK

下载Poco-SDK包

把Unity3D文件夹放到项目脚本中

根据UI类型选择,只留下1中gui文件夹

在unity载入脚本

成功后可使用IDE单独连接Game窗口查看控件树信息

成功接入后打成Android包

文件-build settings-选择安卓-切换平台

进入玩家设置-修改包名-生成Android包

在待测设备安装上包,并启动项目,IDE选择对应模式查看控件树

接入Poco-SDK的常见问题

如何判断项目是否需要接入sdk:引擎渲染项目都需要(游戏应用)

接入Poco-SDK的前提条件:有项目源码

为什么要在根节点或者主camera载入脚本:因为这些节点不会被销毁

其他技巧

连接上1台安卓设置,然后点击右上角的工具按钮,再点击 显示Android助手 选项,可以看到,弹出窗口的左下角,显示了设备当前所有应用的包名(该助手 仅适用于安卓设备

除了使用使用poco辅助窗的录制功能,还可以通过 双击控件树上的某个节点 ,来快速生成该节点的定位脚本,在加其他操作

获取设备连接的字符串

用IDE连接待测设备,随便开个脚本点击运行,1、2秒后终止运行,拉到log查看窗的最上方,看到完整的运行命令。含有设备连接字符串,直接复制

在命令行连接设备
①连接安卓真机
airtest run D:/test/moniqi_test.air –device Android://127.0.0.1:5037/5PZTQWQ0GES8RWUG
②)连接安卓模拟器
airtest run D:/test/monigi test.air –device Android://127.0.0.1:5037/emulator-5554?cap_method=JAVACAP&&ori_method=ADBORI
③注意事项
在IDE需要勾选备选参数才能够连接上的设备,命令行的设备参数中也要加上这些备选参数;&&符号在Windows和MacOS下都需要转义,否则命令会出现被截断的情况

在脚本中行连接设备
①使用auto_setup接口:
auto_setup( file_,devices=[“Android://127.0.0.1:5037/5PZTQWQ0GES8RWUG”,”Android://127.0.0.1:5037/emulator-5554”])
②)使用connect device接口:
dev =connect_device(“Android://127.0.0.1:5037/5PZTQWQ0GES8RWUG”)

dev = connect device(“Android://127.0.0.1:5037/emulator-5554”)
③)使用init_device接口:

init_device(platform=”Ándroid”, uuid=”5PZTQWQOGES8RWUG”)

开启录屏

adb=ADB(serialno=”PFT4PBLF75GQHYBM”)

recorder = Recorder(adb)

recorder.start_recording()
结束录屏

recorder.stop_recording(output=r”D:\airtest\music.mp4”)

生成报告

simple_report(file,logpath=r“D:\airtest\mylog”,output=“D:\airtest\log.html”)

学习教程

testerhome: https://testerhome.com/

掘金: https:/uejin.cn/

CSDN:https://www.csdn.net

博客园: https:/www.cnblogs.com/

开源中国:https://www.oschina.net
《软件测试》
《软件测试的艺术》
《Google软件测试之道》
《mysql必知必会》
《移动app测试实战》
《腾讯Android自动化测试实战》
《鸟哥的Linux私房菜》
《Web安全测试》


文章作者: 读序
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 读序 !
  目录