当前位置:   article > 正文

[1054]Airtest的探索使用_airtest yosemite

airtest yosemite

Airtest的简介

Airtest是网易出品的一款基于图像识别和poco控件识别的一款UI自动化测试工具。Airtest的框架是网易团队自己开发的一个图像识别框架,这个框架的祖宗就是一种新颖的图形脚本语言Sikuli。Sikuli这个框架的原理是这样的,计算机用户不需要一行行的去写代码,而是用屏幕截屏的方式,用截出来的图形摆列组合成神器的程序,这是Airtest的一部分。

另外,Airtest也基于poco这个U控件搜索框架,这个框架也是网易自家的跨平台U测试框架,原理类似于appium,通过控件的名称,id之类的来定位目标控件,然后调用函数方法,例如click(),swip()之类的方法来对目标控件进行点击或者是操作。

关于自动化测试

概念:自动化测试,就是把繁杂的人工测试用例利用自动化测试工具编写成代码,让机器代替人工自动跑用例的过程。实际上就是把以人为驱动的测试行为转化为机器执行的一种过程。

意义:节省人力、物力、时间、硬件资源等,提升测试效率,特别对于繁琐重复的测试用例,可以使测试人员更专注于新的测试模块的建立和开发,从而提高测试覆盖率。

市面上常见的UI自动化测试工具以及优缺点

以上主流工具的优点跟缺点:

相较于以上工具来说,Airtest有以下优点和缺点:

所以其实基于图像识别的Airtest更适合用于游戏测试多一点。

环境的搭建

1、AirtestIDE的下载
AirtestIDE已经帮你集成了所有的环境,自带录制脚本栏,自动生成脚本,自带编辑器还自带模拟器,有了一个AirtestIDE就可以轻松简单的录制脚本了。下载地址是Airtest的官网:

http://airtest.netease.com/

AirtestIDE的使用教程跟文档也在下面的连接中:

https://airtest.doc.io.netease.com/

Android真机连接

使用AirtestIDE对Android应用进行自动化测试时,第一步就需要连接Android设备。

Android真机连接准备:

  • 请先安装手机对应品牌的官方驱动,确保能使用电脑对手机进行USB调试
  • 确保已经打开了手机中的”开发者选项”,并且打开”开发者选项”内的”允许USB调试”
  • 部分手机需要打开”允许模拟位置”、”允许通过USB安装应用”
  • 关闭电脑上已经安装的手机助手软件,能避免绝大多数问题,请务必在任务管理器中手工结束手机助手进程
Android真机USB连接

gif

  • 请使用USB线连接手机,手机上出现的 允许USB调试 弹窗点击 确定,
  • 点击连接面板中的 refresh ADB 按钮,设备列表将会刷新,
  • 点击列表内对应设备的 Connect 完成连接,
  • 若设备未刷出,点击 refresh ADB 按钮。

如果遇到连接问题,请查阅Android连接常见问题:https://airtest.doc.io.netease.com/IDEdocs/faq/1_common%20problems/

手机连上Airtest之后,会向手机中安装2个app,如下:

pocoservice是支撑poco操作的app,yosemite是airtest的输入法,安装之后,手机的默认输入法会变成这个输入法,如果需要改回来原来的输入法,需要手动到手机设置里面进行修改;

远程连接
  • 已知IP和端口的远程设备 ip:port ,AirtestIDE可以直接连接,
  • 点开设备窗内的 远程设备连接 按钮
  • 将 adb connect ip:port 字段填入填充框内,点击 连接 按钮,
  • 远程设备将出现在设备列表中,点击 connect 按钮。
无线连接

参考:使用adb无线连接手机

当手机与电脑处在同一个wifi下,即可尝试无线连接手机了,但是这种方式受限于网络连接的稳定性,可能会出现连接不够稳定的情况。具体连接操作步骤如下:

  • 确保手机开启了USB调试选项,并先用USB线将手机和电脑连接起来
  • 在电脑端执行命令 adb tcpip 5555 ,其中 5555 是端口号,可以根据自己的需求来指定,5555是默认值
  • 获取手机的IP地址,可以在 手机设置-关于手机-状态信息-IP地址 里找到,也可以执行 adb ifconfig 来查看
  • 随后可以拔掉USB线,在AirtestIDE的 远程设备连接 处输入 adb connect 手机ip:刚才填入的端口号5555 ,点击连接,刷新ADB后就能在设备列表中看到连上的设备了
  • 如果因为网络波动、重启ADB等原因导致连接断开,重新执行一次 adb connect ip:port 即可。

录制

点击录制按钮,选择事件进行录制,可以用鼠标操作

介绍一下录制时每一个参数的作用

  • touch(): 点击操作,根据录制脚本时所截取的图像进行点击
  • wait(): 可以等待画面中某个图片出现,如果在指定的时间范围内匹配到了该图片,就会返回图片所处位置的焦点,否则抛出TargetNotFoundError异常
  • swipe():可以从一个位置滑动到另外一个位置
  • exists():判断画面中是否存在某个图片,如果匹配到图片,返回图片所处位置的焦点,否则返回False
  • text():输入文本
  • sleep():线程挂起
  • assert_exists():断言图片存在于当前画面上
  • assert_not_exists():断言图片不存在
  • assert_equal():断言数值相等
  • assert_not_equal():断言数值不等
  • assert_exists()与assert_equal()的区别在于,assert_exists断言的对象是图片,assert_equal断言的对象是数值

可以按照需要的参数进行配置

一个简单的.air 脚本解析

什么是.air 脚本

在下载解压 Airtest 脚本的专属 IDE——AirtestIDE 后,点击 “新建脚本” 按钮,默认即可创建一个后缀名为.air的脚本文件,.air这是 Airtest 脚本的专属后缀。

让我们打开刚才新建脚本的文件夹,可以看到实际上.air脚本文件是一个普通的文件夹,里面附带了一个同名的.py文件,AirtestIDE 在执行脚本时,实际上执行的是里面的.py文件。也就是说,Airtest 脚本虽然自带一个后缀名,然而本质上依然是 Python 脚本,遵循的是 Python 语法,我们可以根据实际需要自由地import其他 Python 第三方库。

值得注意的是,.air文件夹中必须要有同名的.py文件,否则在命令行执行airtest run test.air 这样的运行指令时会导致失败。

初始化环境

首先,就像一个普通的 Python 脚本一样,我们需要在代码文件的最开头部分,写上from airtest.core.api import *,将 Airtest 的主要 API 都 import 进来,以便在后续脚本中使用这些 API。

auto_setup 是一个用来初始化环境的接口,接口文档在这里,它接受 4 个参数,我们可以设置当前脚本所在的路径、指定运行脚本的设备、设置默认的 log 路径和设置脚本父路径。

  • 如果auto_setup不传入任何参数的话,Airtest 将会读取运行时命令行中传入的各项参数,来对环境进行初始化。
  • 在 AirtestIDE 创建脚本时,默认生成的代码里是最简单的初始化代码auto_setup(__file__),意思是将脚本文件作为脚本路径传入,其他参数内容将默认读取运行命令行传入的参数。

脚本运行命令行有两种形式,命令行中的参数包含devicelog等:

  • 命令行运行 Airtest 脚本的示例:>airtest run untitled.air --device Android:///手机设备号 --log log/
    更多使用命令行运行脚本信息,请参考文档
  • 在使用 AirtestIDE 运行脚本时,会在 “Log 查看窗” 中自动生成一个可用的命令行,可以供大家作为参考。
    "D:\AirtestIDE-path\AirtestIDE" runner "D:\script-path\untitled.air" --device Android://127.0.0.1:5037/5PZTQWQOGES8RWUG --log "C:\Users\username\AppData\Local\Temp\AirtestIDE\scripts\aa8c71acdfa70c3068b862cb42ffb8dc"
设备连接
  • 在运行时的命令行中如果传入了类似--device Android:///这样的设备参数,那么脚本在初始化时会自动连上对应的设备,不需要再另外写代码连接了。
  • 如果没有在初始化时连上设备,可以在脚本代码中使用connect_device接口来连接设备。
  • Airtest 支持在一个脚本里同时连接多个设备,使用set_current接口可以在多个设备中进行切换,device()接口可以获取到当前使用中的设备。
模拟点击

Airtest 作为自动化测试框架,模拟的是人的操作,常见接口主要有:

  • touch 点击某个位置,可以设定被点击的位置、次数、按住时长等参数
  • swipe 从一个位置滑动到另外一个位置
  • text 调用输入法输入指定内容
  • keyevent 输入某个按键响应,例如回车键、删除键
  • wait 等待某个指定的图片元素出现
  • snapshot 对当前画面截一张图
  • 其他

核心 API 请参见这个文档,在这个文档页里出现的 API 都是跨平台 API,由于我们在代码的第一行里将airtest.core.api里的接口全部import进来了,因此这些 API 可以在代码里直接进行调用,像这样:

from airtest.core.api import *
touch((x, y))
  • 1
  • 2

在很多接口中,支持传入Template图片对象作为参数,在运行时将会去点击图片在画面中的所在位置,类似这样:

# 等价于 touch((x, y)), (x, y)是图片所在的中心点
touch(Template(r"tpl1556019871196.png", record_pos=(0.204, -0.153), resolution=(1280, 720)))
  • 1
  • 2

其中,Template对象是一个图片类,Airtest 会先尝试在当前画面中寻找能够匹配这张图片的位置,如果找到了,将对这个坐标进行点击操作,如果找不到,将抛出识别异常。我们将在后文对Template图片类进行更加详细的介绍。

安装包

1)使用 pip 安装Airtest框架 pip install airtest

2)若运行代码时,在cv2模块报 ImportError: DLL load failed: 找不到指定模块 的错,如果使用的python版本低于3.7,请直接运行:

pip uninstall opencv-contrib-python
# 若以下安装语句运行失败,可以尝试更新pip到最新版本后重试
pip install opencv-contrib-python==3.2.0.7
  • 1
  • 2
  • 3

3)Poco安装

使用 pip 安装poco框架 pip install pocoui,请注意库的名称为 pocoui,不要填错。

Airtest基本操作方法

除了跨平台的API还有平台特定的API,比如:

airtest.core.android #安卓平台
airtest.core.ios   #苹果平台
airtest.core.win   #Windows平台
  • 1
  • 2
  • 3

这里我们来详细说说这些模块。

跨平台API模块

这里我们要介绍的第一个就是跨平台模块:

from airtest.core.api import * #导入所有方法
  • 1

1).初始化设备

这里初始化设备我们也有两种方案,下面请看:

根据设备的UUID来初始化

语法格式:

init_device(platform='Android',uuid='',cap_method=JAVACAP for Android)
#平台 – Android,IOS或Windows
#uuid –目标设备的uuid,例如,用于Android的serialno,用于Windows的handle,用于iOS的uuid
#kwargs –可选的平台特定关键字args,例如cap_method = JAVACAP for Android
  • 1
  • 2
  • 3
  • 4

下面我们来列举一下实例,如下:

init_device(platform='Android',uuid='127.0.0.1:62001',cap_method='JAVACAP')
  • 1

根据设备的URL来初始化

语法格式如下:

android:///   连接当前安卓设备
android://adbhost:adbport/serial NO.?cap_method=javacap&touch_method=adb
windows:///    连接本地桌面程序
ios:///     连接IOS设备
  • 1
  • 2
  • 3
  • 4

这里我们主要是传入了ADB地址,端口和连接的夜神模拟器的序列号而连接上的。具体例子如下:

connect_device('android://127.0.0.1:5037/127.0.0.1:62001?cap_method=javacap&touch_method=adb')
  • 1

2).返回当前活动设备

device()
  • 1

3).设置当前活动设备

有时候如果我们连接了多个设备,我们需要切换的话,就是用这个函数来达到目的,可以使用设备的索引或者设备的序列号来进行切换哦。

set_current(0)
set_current('127.0.0.1:62001')
  • 1
  • 2

4).运行环境配置

auto_setup(basedir = None,devices = None,logdir = None,project_root = None,compress = 0 )
basedir 设置当前脚本的所在位置,__file__也可以。
devices 指定运行脚本的设备以列表形式存在
logdir 设置脚本运行时的日志保存路径,默认为None,设为True可保存
project_root  设置api的项目根目录
  • 1
  • 2
  • 3
  • 4
  • 5

5).开启并执行远程Shell命令

shell(cmd) #ls / data / local / tmp
  • 1

6).在设备上启动程序

start_app('启动的应用程序包名')
  • 1

7).在设备上停止程序

stop_app('启动的应用程序包名')
  • 1

8).清除设备上的应用程序数据

clear_app('启动的应用程序包名')
  • 1

9).在设备上安装应用程序

install(filepath='要在目标设备上安装的文件的路径')
  • 1

10).在设备上卸载应用程序

uninstall('应用程序包名')
  • 1

11).截图并保存到文件中

snapshot(filename='1.jpg',msg='hello',quality=3)
filename:图片名
msg:屏幕截图的简短描述
quality:图像质量,范围为[1,99]的整数
  • 1
  • 2
  • 3
  • 4

12).唤醒并解锁设备

wake('设备')
  • 1

13).返回目标设备的主屏幕

home('设备')
  • 1

14).设备屏幕上执行点击,滑动,捏,按键,输入操作

click(v=Template(x,y),times=2) #单击
v:触摸目标,可以是Template实例,也可以是绝对坐标(x,y)
times:执行多少次触摸

double_click() #双击
swipe(v1,v2)#滑动起点和终点
swipe(v1,vector=(x,y))#沿向量移动,向量可以是坐标也可以是屏幕百分比
#返回值:原点位置和目标位置

pinch()#捏操作,相当于缩放,参数如下:
in_or_out:放大或缩小
center:默认为None表示屏幕中心
percent:捏动作的屏幕比例,默认值为0.5 
keyevent(keyname='Home')#按键操作

text('文本')#在设备上输入文本
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

15).睡眠,等待

sleep(2)#睡眠两秒,延迟两秒
wait(v,timeout,interval,intervalfunc)#等待与设备屏幕上的模板匹配
v:等待的目标对象
timeout:超时时间
interval:尝试找到匹配项的时间间隔(秒)
intervalfunc:在每次未成功尝试找到相应匹配项后调用
返回值:匹配目标的坐标
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

16).检查给定目标在设备屏幕上是否存在

exists(v)
v:检查对象
如果找不到目标,则为False,否则返回目标的坐标
  • 1
  • 2
  • 3

17).在设备屏幕上查找所有出现的目标并返回其坐标

find_all(v)
v:寻找目标
返回坐标列表
  • 1
  • 2
  • 3

18).断言操作

assert_exists(v,msg) #断言目标存在于设备屏幕上
assert_not_exists(v,msg) #断言目标在设备屏幕上不存在
v:要检查的目标
msg:断言的简短描述

assert_equal(v1,v2,msg) #断言两个值相等
assert_not_equal(v1,v2,msg) #断言两个值不相等
v1:第一个值
v2:第二个值
msg:断言的简短描述
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里基本上我们就把使用方法说完了,下面我们来进行下实际操作,下一篇文章即将奉上。

  • 使用
from airtest.core.api import *
# 通过ADB连接本地Android设备
connect_device("Android:///")
#安装待测软件apk,路径信息。
install("path/to/your/apk")
#开始运行app
start_app("com.pingan.certicationApp")
#点击某个图片,Airtest中基于图像识别语法,图片自己提供。
touch(Template("image_of_a_button.png"))
#滑动语音,开头图片跟结尾图片
swipe(Template("slide_start.png"), Template("slide_end.png"))
#添加断言的图片
assert_exists(Template("success.png"))
#点击Android上的返回键
#keyevent("BACK")
#点击Android上的Home键返回
#home()
#uninstall("package_name_of_your_apk")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • poco样例
# -*- encoding=utf8 -*-
__author__ = "enmonster"

from airtest.core.api import *

auto_setup(__file__)

from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

poco("com.miui.home:id/workspace").offspring("计算器").offspring("com.miui.home:id/icon_icon").click()
poco("com.miui.calculator:id/btn_c_s").click()
poco("com.miui.calculator:id/digit_7").click()
poco("com.miui.calculator:id/op_add").click()
poco("com.miui.calculator:id/digit_5").click()
poco("com.miui.calculator:id/btn_equal_s").click()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

poco辅助窗
poco是通过元素本身的属性来定位元素,常用的API如下:
attr(‘type’):提取指定元素属性为type的值
get_text(): 提取指定元素的文本内容
attr(‘text’): 通过给定的属性名检索ui元素的属性。如果属性不存在,则返回none(属性有visible、text、type、pos、size、name等)
exists():判断指定元素是否在当前屏幕上存在,存在true、不存在false
click(): 点击事件,可使用click(center)、click([0.5,0.5])、focus([0.5,0.5]).click()来点击控件中心位置
rclick():右键点击
double_click():双击操作
long_click():长按操作
swipe:滑动事件,如:swipe([0.2, -0.2], duration=1)以45度角滑动,持续1秒钟
drag:拖拽事件,如:poco(text=‘需要拖动位置’).drag_to(poco(text=‘目标位置’))
focus (local positioning):局部定位,如:poco(‘控件地址’).focus(‘center’).click()点击控件中间位置
wait:等待事件,如:poco(‘控件地址’).wait(2).click() 控件出现就点击,最多等待2秒

多个手机交互

如果case中涉及到两个手机交互的,可以在.py文件中连接多个手机,需要在哪个手机上操作,就需要在脚本中使用set_cerrent()借口来切换到相应的手机上;

device1 = "c17a4cb4" #设备1
device2 = "RKK0217C15003363" #设备2
dev1 = connect_device("android://127.0.0.1:5037/"+device1)#连接设备1
dev2 = connect_device("android://127.0.0.1:5037/"+device2)#连接设备2
poco1 = AndroidUiautomationPoco(dev1) #初始化设备1
poco2 = AndroidUiautomationPoco(dev2) #初始化设备2
set_current(device1)#切换到手机1
set_current(device2)切换到手机2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
case举例

初始化设备之后就可以进行相关设备的poco操作了,举个例子:

这个例子是打开微信,点击聊天信息中的一个好友,然后清除好友聊天的例子;

from poco.drivers.android.uiautomation import AndroidUiautomationPoco
device1 = "c17a4cb4" #设备号
dev1 = connect_device("android://127.0.0.1:5037/"+device1)#连接师傅手机
poco1 = AndroidUiautomationPoco(dev1) #实例化手机
auto_setup(__file__)

  
def clear_wechat(poco):#清除微信的聊天记录
     start_app("com.tencent.mm")#启动微信
     sleep(12)#等待12秒
     poco1(text="三星").click()#点击好友“三星”的聊天
     poco1("android.support.v7.widget.LinearLayoutCompat").click()#点击更多
     poco1(text="清空聊天记录").click()#点击清空聊天记录
     poco1(text="清空").click()#点击清空
     stop_app("com.tencent.mm")#关闭微信
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
引用其他air文件的方法

如果有很多重复的操作,可以将这些重复的操作写到一个公用的air文件里面,然后再在用例里面引用这个公用的air文件的方法就可以:

举例,有一个名叫gongyou.air的文件,里面有一个clear_wechat的方法,这个clear_wechat方法就是一个清除微信聊天记录的用例,如果需要在用例中用到这个clear_wechat,就需要在用例中引用这个文件,然后倒入这个引用文件中的clear_wechat方法,如下:

# -*- encoding=utf8 -*-
__author__ = "xhong"

from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
from poco.exceptions import PocoNoSuchNodeException
from poco.exceptions import PocoTargetTimeout
ST.PROJECT_ROOT = "D:\code\AirtestCase"#引用公用air的路径
using("gongyou.air")
from gongyou import clear_wechat
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

参考:https://www.jianshu.com/p/32d08455e86f
https://blog.csdn.net/sunxitao970324/article/details/105731046
http://testerhome.com/topics/20704
https://cloud.tencent.com/developer/article/1819833
https://zhuanlan.zhihu.com/p/165527546
https://blog.csdn.net/chqj_163/article/details/109242399

AirtestIDE连接安卓真机及常见问题:
https://www.cnblogs.com/songzhenhua/p/14716116.html
airtest连接设备黑屏或者运行报错minicap超时问题:
https://blog.csdn.net/qq_32394351/article/details/112512540

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/276243
推荐阅读
相关标签
  

闽ICP备14008679号