Airtest Project 微信小程序UI自动化测试

官网:http://airtest.netease.com/docs/docs_AirtestIDE-zh_CN/
其他笔记:
Airtest Project 自定义启动器批量运行脚本
解决运行Airtest脚本时opencv-contrib-python报错的问题

开发环境准备

使用AirtestIDE来编写脚本,只需要在 官网 下载最新版本AirtestIDE,解压即可直接使用。AirtestIDE内置了Python3.6.5,airtest和poco环境,本地无需安装python环境就能直接使用。

如果想要使用其他需要安装的Python第三方库,或者Python2环境,则需要进行本地python的 环境部署 ,然后在AirtestIDE设置中添加本地的Python.exe路径,详情参考 IDE配置。

在AirtestIDE中新建的脚本,后缀都为 .air ,但实际上在运行的时候, 运行的是.air目录下的同名.py文件 。

脚本调试

目前AirtestIDE暂不支持断点调试功能,因此调试脚本只能通过print等较为简单的方式。但是由于Airtest框架涉及到图像识别的准确率问题,需要反复运行和调试才能确定合适的图片与识别阈值,因此IDE特别提供了一种 选中部分代码单独运行 的调试功能(如下),需要注意的是,该单独运行代码的功能不会执行到脚本中其他代码里的内容,可能会出现别处的变量未能初始化等情况(因此不支持poco)。

Airtest Project 微信小程序UI自动化测试_第1张图片

IDE还提供了一个图片截图预览功能,在脚本编辑区内双击图片,会弹出图片编辑器,在图片编辑器内点击 Snapshot Recognition 按钮,将会截取当前的手机屏幕画面,并且进行一次识别,识别成功的话会在截图上面标注出识别区域,方便进行截图的调试。

Mac Airtest图片编辑器疑有BUG,点击图片编辑器的右下角的OK或Cancel键后,整个IDE都会卡死,已提交Issue

Airtest Project 微信小程序UI自动化测试_第2张图片

目前图片识别中,每次识别时,只要识别结果的可信度>阈值 threshold 即认为是识别通过。如果识别到错误的位置,可以通过调节 threshold 进行准确度调整。

Android 真机USB连接

测试机:华为

  1. 开启开发者模式:进入设置->系统->关于手机,多次点击版本号后进入开发者模式;

  2. 设置开发人员选项:允许USB调试、连接USB时总是弹出提示、监控ADB安装应用、仅充电模式下允许ADB调试(可选)

  3. 关闭电脑上已经安装的手机助手软件, 使用USB线连接手机,手机上出现USB连接方式(传输照片、传输文件和仅充电),选择"传输照片",如果在第二步中设置了仅充电模式下允许ADB调试,则需要选择"仅充电"选项;

  4. 点击Airtest点击列表内对应设备的 Connect 完成连接, 若设备未刷出,点击 refresh ADB 按钮设备列表将会刷新;

Airtest

基于图像识别的无侵入式测试框架。

初始化

# -*- encoding=utf8 -*-
​
from airtest.core.api import *
auto_setup(__file__)  #自动初始化设备

录制airtest语句

  • 辅助按键录制脚本

在AirtestIDE的Airtest录制辅助窗内,包含有三种类型的录制按钮:

Airtest Project 微信小程序UI自动化测试_第3张图片

点击某个按钮后,在设备画面上按下鼠标左键进行截图框选,抬起鼠标左键完成框选。对应操作语句会自动插入编辑器脚本中。

  • 脚本自动录制

点击自动录制按钮后,使用鼠标操作设备画面,对应操作语句会自动插入到编辑器脚本中(不好用)。

Airtest Project 微信小程序UI自动化测试_第4张图片

airtest.core.api

Airtest的常用API大部分都列在了AirtestIDE里的Airtest辅助窗中,在使用各种常见的截图语句时,鼠标移动到按钮上即可看到每个接口的常用参数与返回值信息,非常方便。

Airtest Project 微信小程序UI自动化测试_第5张图片

Poco

基于UI控件识别的测试框架

API文档:https://poco.readthedocs.io/en/latest/source/poco.proxy.html#poco.proxy.UIObjectProxy.exists

poco.exceptions module: https://poco.readthedocs.io/en/latest/source/poco.exceptions.html

初始化

切换Poco应用类型时,脚本编辑框会弹出提示插入初始化Poco代码的通知窗。 确认Poco应用类型正确后,确认插入光标位置后,点击 'Yes' 即可插入对应的Poco初始化代码。

Airtest Project 微信小程序UI自动化测试_第6张图片
  • Unity3D
from poco.drivers.unity3d import UnityPoco

poco = UnityPoco()
  • Android native APP
from poco.drivers.android.uiautomation import AndroidUiautomationPoco

poco = AndroidUiautomationPoco()
poco.device.wake()
poco(text='Clock').click()

切换模式

Poco Pause ->冻结模式

主要用途:查看当前画面中各位置的UI呈现范围。UI自动化测试中,常使用此功能进行元素定位。

进入方式:

  • 单击UI渲染树上的任意条目(注意是单击,双击会直接将当前UI位置插入到代码区域);

  • 点击 Poco Pause 按钮:

    Airtest Project 微信小程序UI自动化测试_第7张图片

具体表现:

  • 屏幕画面会冻结(设备操作失效),UI渲染树的数据也会停止刷新。

  • 伴随鼠标在画面中的移动,对应位置的UI元素会被标记框标出。

  • 鼠标左键点击,可以在log输出窗中查看对应控件的详细属性。

Poco Inspect ->检视模式

主要用途:伴随设备操作,查看不同页面UI的渲染情况。

进入方式:

Airtest Project 微信小程序UI自动化测试_第8张图片

具体表现:

  • 设备画面可以正常交互,UI渲染树的数据正常刷新。

  • 伴随鼠标在画面中的移动,对应位置的UI元素会被标记框标出。

  • 鼠标左键点击,可以在log输出窗中查看对应控件的详细属性。

Poco Recording ->录制模式

  • 单步录制Poco脚本

    如下,先通过冻结模式在UI树中找到目标条目,双击直接插入poco代码,也可以右键目标条目,选择插入UI节点的Xpath代码。

    Airtest Project 微信小程序UI自动化测试_第9张图片
    注意:单步录制,只会poco插入代理对象,具体的操作代码(如 ".click()" )需要手动添加。

  • 自动录制

    进入方式:

    Airtest Project 微信小程序UI自动化测试_第10张图片

    具体表现:

    • 设备画面可以正常交互,UI渲染树的数据正常刷新。

    • 伴随鼠标在画面中的移动,对应位置的UI元素会被标记框标出。

    • 伴随设备操作(点击、滑动),即可插入对应UI节点的poco代码。

自动录制时,会自动插入代码对象的操作代码。

选择器

在poco实例后加一对括号就可以进行UI选择了。选择器会遍历所有UI,将满足给定条件的UI都选出来并返回。括号里的参数就是所给定的条件,用属性名值对表示,其中第一个参数固定表示 节点名 其余可选参数均表示节点的属性及预期的属性值。详见: API Reference selecting UI

  • Basic Selector
# select by node name
poco('bg_mission')

# select by name and other properties
poco('bg_mission', type='Button')

# 支持正则
poco(text='确定')
poco(textMatches='^据点.*$', type='Button', enable=True)
  • Relative Selector
# select by direct child/offspring
items=poco('main_node').child('list_item').offspring('item')

# 可迭代对象
for item in items:
    item.child('icn_item')
  • Sequence Selector
tems = poco('main_node').child('list_item').offspring('item')
print(items[0].child('material_name').get_text())
print(items[1].child('material_name').get_text())

读取属性

mission_btn = poco('bg_mission')
print(mission_btn.attr('type'))     # 'Button'
print(mission_btn.get_text())     # '查询停车费'
print(mission_btn.attr('text'))    # '查询停车费' equivalent to .get_text()
print(mission_btn.exists())    # True/False, exists in the screen or not

操作对象

  • 点击 click
    点击默认点在 anchorPoint 上,每个UI都会有一个 anchorPoint ,也就是检视器(Inspector)中UI包围盒的那个红点,大部分情况下 anchorPoint 都在UI包围盒的正中央。如果想指定其他的点击位置,可以传一个参数到 click 方法中,这个参数是一个用list或tuple表示的2维向量,其 [x, y] 值分别表示相对于包围盒左上角的偏移量,左上角为 [0, 0] ,右下角为 [1, 1]
poco('bg_mission').click()
poco('bg_mission').click('center')
poco('bg_mission').click([0.5, 0.5])    # equivalent to center
poco('bg_mission').focus([0.5, 0.5]).click()  # equivalent to above expression
  • 局部定位 focus
    所有UI相关的操作都默认以UI的 anchorPoint 为操作点,如果想自定义一个点那么可以使用 focus方法。调用此方法将返回 新的 设置了默认 焦点 的UI,重复调用则以最后一次所调用的为准。focus 所使用的是局部坐标系,因此同样是UI包围盒的左上角为原点,x轴向右,y轴向下,并且包围盒长宽均为单位1。很显然中心点就是 [0.5, 0.5] .
poco('bg_mission').focus('center').click()  # click the center
  • 滑动 swipe
    swipe操作同样是以 anchorPoint 为起点,如果你想改变起点请使用 focus 方法,然后朝给定向量所代表的方向滑动,距离也就是向量的长度.
joystick = poco('movetouch_panel').child('point_img')
joystick.swipe('up')
joystick.swipe([0.2, -0.2])  # swipe sqrt(0.08) unit distance at 45 degree angle up-and-right
joystick.swipe([0.2, -0.2], duration=0.5)
  • 拖拽 drag
    swipe 不同的是, darg 是从一个UI拖到另一个UI,而 swipe 是将一个UI朝某个方向拖动。
poco(text='AAA').drag_to(poco(text='BBB'))```

focusdrag_to 结合使用还能产生卷动(scroll)的效果,下面例子展示了如何将一个列表向上卷动半页。

scrollView = poco(type='ScollView')
scrollView.focus([0.5, 0.8]).drag_to(scrollView.focus([0.5, 0.2]))
  • UI等待
    在给定时间内等待一个UI出现并返回这个UI,如果已经存在画面中了那就直接返回这个UI。 如果超时了还没有出现,同样也会返回,但是调用这个UI的操作时会报错。(我真被这里坑死了)
poco('bg_mission').wait(5).click()  # wait 5 seconds at most,click once the object appears
poco('bg_mission').wait(5).exists()  # wait 5 seconds at most,return Exists or Not Exists
  • 截图 snapshot
    截屏幕并以base64编码返回。截图的格式(png, jpg, …)由对应的sdk实现决定,大多数情况下是png。
from base64 import b64decode

b64img, fmt = poco.snapshot(width=720)
open('screen.{}'.format(fmt), 'wb').write(b64decode(b64img))
  • 全局操作
    在没有选定或指定UI的情况下也可以进行操作(模拟输入),也叫全局操作。
poco.click([0.5, 0.5])  # click the center of screen
poco.long_click([0.5, 0.5], duration=3)

# swipe from A to B
point_a = [0.1, 0.1]
center = [0.5, 0.5]
poco.swipe(point_a, center)

# swipe from A by given direction
direction = [0.1, 0]
poco.swipe(point_a, direction=direction)

常见异常

from poco.exceptions import PocoTargetTimeout
from poco.exceptions import PocoNoSuchNodeException


使用命令行运行脚本

官方文档: http://airtest.netease.com/docs/docs_AirtestIDE-zh_CN/4_run_script/run_script.html#id3

运行脚本:

PS E:\treasure\Airtest> [python -m] airtest run parkIndex.air --log E:/CatJmx/ParkTest/Airtest/log

可选参数:

  • [--recording]

让airtest自动对脚本执行过程中的手机屏幕进行录制操作。录制完成后,将自动生成一个命令格式类似于 recording_0.mp4 的文件到脚本生成的log目录中。在最后生成报告时,这个mp4文件会默认显示在HTML报告页面里。

  • [--device]

设备字符串,什么都不填写,会默认取当前连接中的第一台手机;字串完整定义格式:Android://:/

  • [--log]

指定生成的log目录路径,默认为脚本所在目录

Airtest Project 微信小程序UI自动化测试_第11张图片

生成报告

脚本运行过程,与报告生成过程是独立的两个步骤,因此在运行过 airtest run script.air后,假如没有指定 --log log/ 参数,Airtest 将把生成的log内容放到当前命令行的执行目录里(如果指定了 --log 参数,log内容与截图将会放在指定目录里)

PS E:\treasure\Airtest> [python -m] airtest report parkIndex.air --log_root E:/CatJmx/ParkTest/Airtest/log --outfile log/log.html --lang zh --export E:/CatJmx/ParkTest/Airtest --plugin poco.utils.airtest.report

可选参数:

  • [--log_root]
    日志根目录,日志文件应该是 log_root / log.txt

  • [--outfile]
    指定输出html文件路径,默认为log.html

  • [--static_root]
    静态文件根目录

  • [--lang zh]
    设置报告语言

  • [--export]
    在使用 airtest report 指令生成的报告中,使用了绝对路径来访问里面的图片文件,同时HTML报告中访问的静态css与js资源文件,也是硬盘上的绝对路径(默认在airtest的安装目录下的report文件夹里)。因此,假如想要发送报告给其他人观看,就必须要在命令行末尾加上 --export 导出目录,将报告导出到一个指定目录中,然后将整个目录发送给别人查看;

  • [-plugin poco.utils.airtest.report]
    默认报告是airtest的专属报告,对于poco语句的支持不够完善,需要使用插件的形式来补充;

  • [--plugin airtest_selenium.report]

    如果脚本中使用了selenium插件,在生成报告的命令行最后,需要加入 --plugin airtest_selenium.report,可以让报告支持selenium元素;
    Airtest Project 微信小程序UI自动化测试_第12张图片

[To be continued...]

你可能感兴趣的:(Airtest Project 微信小程序UI自动化测试)