airtest测试用例_Airtest 常用方法
几个添加设备参数的例子
#方法一:在auto_setup()接口添加设备
auto_setup(__file__,devices=["Android://127.0.0.1:5037/SJE5T17B17"])#方法二:用connect_device()方法连接设备
dev = connect_device("Android://127.0.0.1:5037/SJE5T17B17")#方法三:用init_device()方法连接设备
init_device(platform="Android",uuid="SJE5T17B17")
过滤非严重级别的log
__author__ = "Airtest"
importlogging
logger= logging.getLogger("airtest")
logger.setLevel(logging.ERROR)
循环点击某个list元素合集
for item in range(len(freeze_poco("List").child())):
item=str(item)poco("NestStarReward").offspring(item).offspring("T").click()
冻结poco,使操作更快
freeze_poco = poco.freeze() #TODO:定义dongjiepocofreeze_poco("TheExpDlg(Clone)").offspring(item).click()
判断元素不存在则点击
if not poco("TeamDlg(Clone)").offspring("Categories").offspring("item1").offspring("Text").exists():
poco("CurrentCategory").click()
判断元素存在则点击
if poco("TeamDlg(Clone)").offspring("Categories").offspring("item1").offspring("Text").exists():
poco("CurrentCategory").click()
在脚本中重置下条case的环境
try:finally:
判断多个控件同时存在
with poco.freeze() as freeze_poco:if freeze_poco("DetailsBtn").exists() and\
freeze_poco("CurrentExp").exists() and\
freeze_poco("Chests").child("item0").exists() and\
freeze_poco("Chests").child("item1").exists() and\
freeze_poco("Chests").child("item2").exists() and\
freeze_poco("Chests").child("item3").exists() and\
freeze_poco("Chests").child("item4").exists() and\
freeze_poco("LeftView").child("Exp").exists() and\
freeze_poco("LeftView").child("Exp500").exists() and\
freeze_poco("LeftView").child("Exp1000").exists() and\
freeze_poco("LeftView").child("Exp500").child("box").exists() and\
freeze_poco("LeftView").child("Exp1000").child("box").exists() and\
freeze_poco("DailyActivityDlg(Clone)").offspring("RightView").offspring("Go").exists()
保证该控件在可点击范围方法
def butpos(butpos,pos1=0.4,pos2=0.81,high=1330,low=930,lows=482):"""把不在屏幕内部的控件滑动到屏幕内,使之可被操作
:param butpos: 控件元素
:param pos1: 希望控件所在屏幕上的最低限
:param pos2: 希望控件所在屏幕上的最上限
:param high: 固定坐标
:param low: 滑动起始或终点位置
:param lows: 滑动起始或终点位置
:return:"""
for i in range(50):
but=butpos.get_position()if but[1]
swipe([high, lows], [high, low],5)elif but[1] >pos2:
swipe([high, low], [high, lows],5)else:break
获取手机屏幕大小
def_get_screen_size(devices):'获取手机屏幕大小'size_str= os.popen(f'adb -s {devices} shell wm size').read()if notsize_str:print('请安装 ADB 及驱动并配置环境变量')
sys.exit()
m= re.search(r'(\d+)x(\d+)', size_str)ifm:
sizeheight= "{height}".format(height=m.group(1))
sizewidth= "{width}".format(width=m.group(2))returnint(sizeheight),int(sizewidth)return "1920x1080"
把print输出成log
_print = print
def print(*args, **kwargs):
_print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), *args, **kwargs)
使用函数定义pcoo
defdeviceconnect(devices):"""用于poco实例化的公用方法
:param devices: 制定设备
:return:"""dev= connect_device("android:///" +devices)
poco= UnityPoco(device=dev)return poco
所有UI相关的操作都默认以UI的 anchorPoint 为操作点,如果想自定义一个点那么可以使用 focus 方法。调用此方法将返回 新的 设置了默认 焦点 的UI,重复调用则以最后一次所调用的为准。focus 所使用的是局部坐标系,因此同样是UI包围盒的左上角为原点,x轴向右,y轴向下,并且包围盒长宽均为单位1。很显然中心点就是 [0.5, 0.5] 。下面的例子会展示一些常用的用法。
poco('bg_mission').focus('center').click() #click the center
将 focus 和 drag_to 结合使用还能产生卷动(scroll)的效果,下面例子展示了如何将一个列表向上卷动半页。
scrollView = poco(type='ScollView')
scrollView.focus([0.5, 0.8]).drag_to(scrollView.focus([0.5, 0.2]))
在给定时间内等待一个UI出现并返回这个UI,如果已经存在画面中了那就直接返回这个UI。 如果超时了还没有出现,同样也会返回,但是调用这个UI的操作时会报错。类似的操作还有wait_for_appearance
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
点击(click)
poco.click([0.5, 0.5]) #click the center of screen
poco.long_click([0.5, 0.5], duration=3)
滑动(swipe)
#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)
截屏幕并以base64编码返回。截图的格式(png, jpg, …)由对应的sdk实现决定,大多数情况下是png。详见 ScreenInterface.getScreen
from base64 importb64decode
# 注意:在poco的某些引擎实现中不支持快照。
b64img, fmt= poco.snapshot(width=720)
open('screen.{}'.format(fmt), 'wb').write(b64decode(b64img))
异常处理(Exceptions)
PocoTargetTimeout(控件出现超时)
from poco.exceptions importPocoTargetTimeouttry:
poco('guide_panel', type='ImageView').wait_for_appearance()exceptPocoTargetTimeout:#bugs here as the panel not shown
raise
PocoNoSuchNodeException(没有这个控件)
from poco.exceptions importPocoNoSuchNodeException
img= poco('guide_panel', type='ImageView')try:if notimg.exists():
img.click()exceptPocoNoSuchNodeException:#If attempt to operate inexistent nodes, an exception will be thrown
pass
最简单的操作就是点击(click),也可以长按(long click),按多久都行,下面例子展示点击和长按各自的效果。
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
poco('btn_start').click()
poco('basic').click()
poco('star_single').long_click()
poco('star_single').long_click(duration=5)
如果从一个不存在的UI里读取属性值或者操作它,会触发异常,如果你不确定那个UI是否存在,可以调用 .exists() 来判断。在具体的测试用例中,如果因为UI不存在出现了异常,这很有可能是game/app的bug,不要强行忽略
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
btn= poco('btn_start')
btn.click()print(btn.get_text()) #=> 'Start'
intro= poco('introduction')print(intro.get_text()) #=> 'xxxx'
print(intro.attr('text')) #=> 'xxxx'
print(intro.attr('type')) #=> 'Text'
print(intro.attr('texture')) #=> None. Because there is no texture on Text.
print(intro.attr('foo-bar')) #=> None. Because "intro" dose not have an attribute named "foo-bar".
intro.click()#Perform a click on any UI objects are allowed.
obj= poco('foo-bar', type='FooBar')print(obj.exists()) #=> False. This UI does not exist actually
invisible_obj= poco('result_panel', type='Layer')print(invisible_obj.exists()) #=> False. This UI is not visible to user.
Swipe滑动
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()#swipe the list view up
poco('Scroll View').swipe([0, -0.1])
poco('Scroll View').swipe('up') #the same as above, also have down/left/right
poco('Scroll View').swipe('down')#perform swipe without UI selected
x, y = poco('Scroll View').get_position()
end= [x, y - 0.1]
dir= [0, -0.1]
poco.swipe([x, y], end)#drag from point A to point B
poco.swipe([x, y], direction=dir) #drag from point A toward given direction and length
在UI自动化测试中,最关键的就是将目标UI选择出来。一般情况下,通过名字选择是最简单的方式,但是在一些情况下,并不是每个UI控件都有命名,特别是通过代码动态生成和加载的UI,一般都没有一个有意义的名字。Poco提供了强大有效的各种选择方式,不仅可以通过UI单一的属性选择,还可以通过UI之间的层次关系和位置关系来选择出目标UI。更强大的是,以上三种模式可以进行任意串联或者组合使用,这样基本上能应付所有情况了。
下面的例子将展示如何在复杂层次里选出对应的UI控件
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
items= poco('main_node').child('list_item').offspring('name'):
first_one=items[0]print(first_one.get_text()) #=> '1/2活力药剂'
first_one.click(
poco里的坐标的取值范围是相对于屏幕的,屏幕的宽和高都为单位1,因此也叫百分比坐标。当你需要和某个UI控件附近的UI控件交互或者要点击某个按钮的边缘而不是中间时,那可以用 局部定位 。
总的来说,和UI控件交互最终都是和坐标交互,例如点击一个按钮实际上就是点击某个坐标。 局部定位 就可以基于某个UI的左上角进行偏移,然后可以实现点击到这个UI控件内的各个坐标甚至UI外面的其他坐标。
#coding=utf-8
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
image= poco('fish').child(type='Image')
image.focus('center').long_click()
time.sleep(0.2)
image.focus([0.1, 0.1]).long_click()
time.sleep(0.2)
image.focus([0.9, 0.9]).long_click()
time.sleep(0.2)
image.focus([0.5, 0.9]).long_click()
time.sleep(0.2)
也可以在选中的UI外单击。通过它的名字标签点击一些模型是非常有用的
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
balloonfish_image= poco(text='balloonfish').focus([0.5, -3])
balloonfish_image.long_click()
下面的示例表明,focus是一个不会影响原始UI的不可变方法
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()#focus is immutable
fish = poco('fish').child(type='Image')
fish_right_edge= fish.focus([1, 0.5])
fish.long_click()#still click the center
time.sleep(0.2)
fish_right_edge.long_click()#will click the right edge
time.sleep(0.2)
下面的示例演示如何使用拖动来滚动列表。
#coding=utf-8
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
listView= poco('Scroll View')
listView.focus([0.5, 0.8]).drag_to(listView.focus([0.5, 0.2]))
time.sleep(1)
Poco提供了非常简单的方式来处理一系列UI交互,直接用for循环进行迭代遍历即可。在for循环中,每次迭代的对象都是一个UI代理,所以可以像之前说的那样,去访问对象的属性和进行对象操作。
下面的示例展示了如何遍历拖动
#coding=utf-8
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
poco('btn_start').click()
poco(text='drag drop').click()
time.sleep(1.5)
shell= poco('shell').focus('center')for star in poco('star'):
star.drag_to(shell)
time.sleep(1)assert poco('scoreVal').get_text() == "100", "score correct." #这是另一种断言方法
poco('btn_back', type='Button').click()
下面是另一个遍历模型所有名称的示例
#coding=utf-8
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()for name in poco('plays').offspring('fish').child('name'):print(name.get_text()) #pearl/shark/balloonfish
下面例子展示了怎么样在商城界面中购买当前屏幕的所有商品。
#coding=utf-8
poco=Poco(...)
bought_items=set()for item in poco('main_node').child('list_item').offspring('name'):#get its text value
item_name =item.get_text()#markdown the bought item
if item_name not inbought_items:
item.click()
bought_items.add(item_name)
这个异常特指无效的操作,或者说不起作用的操作,例如点击到了屏幕外面,或者对一个图片设置text属性(输入框才能设置text属性)。虽然这个异常并不会对应用造成什么实质性影响,但是还是要尽可能避免,以免测试脚本里逻辑混乱或测试结果不稳定。
#coding=utf-8
from poco.drivers.unity3d importUnityPocofrom poco.exceptions importInvalidOperationException
poco=UnityPoco()try:
poco.click([1.1, 1.1]) #click outside screen
exceptInvalidOperationException:print('oops')
如果从一个不存在的UI控件读取属性或控制它,那就会出现这个异常。测试一个UI控件是否存在可以调用UI代理的 .exists() 方法。
#coding=utf-8
from poco.drivers.unity3d importUnityPocofrom poco.exceptions importPocoNoSuchNodeException
poco=UnityPoco()
node= poco('not existed node') #select永远不会引发任何异常
try:
node.click()exceptPocoNoSuchNodeException:print('oops!')try:
node.attr('text')exceptPocoNoSuchNodeException:print('oops!')print(node.exists()) #=> 假的。此方法不会引发
这个异常只会在你主动等待UI出现或消失时抛出,和 PocoNoSuchNodeException 不一样,当你的操作速度太快,界面来不及跟着变化的话,你只会遇到 PocoNoSuchNodeException 而不是 PocoTargetTimeout ,其实就是在那个UI还没有出现的时候就想要进行操作。
下面的例子展示测试脚本如何与UI保持同步,并处理 PocoTargetTimeout 异常
#coding=utf-8
from poco.drivers.unity3d importUnityPocofrom airtest.core.api importconnect_devicefrom poco.exceptions importPocoTargetTimeout
poco=UnityPoco()#UI is very slow
poco('btn_start').click()
star= poco('star')try:
star.wait_for_appearance(timeout=3) #wait until appearance within 3s
exceptPocoTargetTimeout:print('oops!')
time.sleep(1)
与上面 PocoTargetTimeout 不同,如果操作速度远远慢于UI变化的速度,那*很可能*会出现这个异常。这个异常仅当去访问或操作一个刚才还在但现在不在的UI控件才会出现,并且一般情况下基本不会出现。
下面例子展示点击一个已经不存在的UI控件的效果
#coding=utf-8
from poco.exceptions importPocoTargetRemovedException, PocoNoSuchNodeException
# 这个异常仅会在一些poco-sdk实现中,所以更可靠的做法是必要的情况下显示地去调用 .exists() 去判断UI是否存在。
poco=Poco(...)
start= poco('start')print(start.exists()) #=> True.
start.click()print(start.exists()) #=> False
try:
start.click()exceptPocoTargetRemovedException:print('oops!')#IMPORTANT NOTE:#`start2` is different from `start` !#`start` is tracking the UI at initial and it knows itself was removed but `start2`#does not know anything before.
start2 = poco('start')try:
start2.click()exceptPocoNoSuchNodeException:print('oops!')
这个异常仅会在一些poco-sdk实现中,所以更可靠的做法是必要的情况下显示地去调用 .exists() 去判断UI是否存在。
在poco.drivers.std。StdPoco,这个异常从未被提出!
#coding=utf-8
from poco.drivers.unity3d importUnityPocofrom airtest.core.api importconnect_device
poco=UnityPoco()#no PocoTargetRemovedException case
start = poco('start')print(start.exists()) #=> True.
start.click()print(start.exists()) #=> False
#重要提示:在Unity3d软件中,此操作将点击与之前相同的坐标#不管发生什么
start.click()
一些复杂的测试用例中,不可能只是不断地主动控制或者读取属性。通过被动地获取UI状态改变的事件,这样有助于写出不混乱的测试脚本。Poco提供了简单的轮询机制去同时轮询1个或多个UI控件,所谓轮询就是依次判断UI是否存在。
下面例子展示的是最简单的UI同步
#coding=utf-8
from poco.drivers.unity3d importUnityPoco
poco=UnityPoco()#start and waiting for switching scene
start_btn = poco('start')
start_btn.click()
start_btn.wait_for_disappearance()#waiting for the scene ready then click
exit_btn = poco('exit')
exit_btn.wait_for_appearance()
exit_btn.click()
下面例子展示轮询UI时等待 任意一个 UI出现就往下走
#coding=utf-8
from poco.drivers.unity3d importUnityPocofrom poco.exceptions importPocoTargetTimeout
poco=UnityPoco()
bomb_count=0whileTrue:
blue_fish= poco('fish_emitter').child('blue')
yellow_fish= poco('fish_emitter').child('yellow')
bomb= poco('fish_emitter').child('bomb')
fish=poco.wait_for_any([blue_fish, yellow_fish, bomb])if fish isbomb:#跳过炸弹,数到3退出
bomb_count += 1
if bomb_count > 3:return
else:#否则点击鱼收集。
fish.click()
time.sleep(2.5)
下面例子展示轮询UI时等待 所有 UI出现才往下走
#coding=utf-8
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
poco(text='wait UI 2').click()
blue_fish= poco('fish_area').child('blue')
yellow_fish= poco('fish_area').child('yellow')
shark= poco('fish_area').child('black')
poco.wait_for_all([blue_fish, yellow_fish, shark])
poco('btn_back').click()
time.sleep(2.5)
介绍一种加快UI操作速度的一种方法(即冻结UI),只是对于复杂的选择和UI遍历有效,如果只是简单的按名字选择请不要用这种方法,因为一点效果都没有冻结UI其实就是将当前界面的层次结构包括所有UI的属性信息抓取并存到内存里,在跟UI交互时就直接从内存里读取UI属性,而不用在发送rpc请求到game/app里去操作UI。好处就是一次抓取(消耗几百毫秒),可以使用多次,读取UI属性几乎不消耗时间,同时坏处就是,你需要手动处理UI同步,如果抓取了层次结构后,某个UI控件位置发生了变化,此时如果仍然点击这个UI的话,就会点击到原来的位置上,而不是最新的位置,这很容易导致奇怪的测试结果
下面两个例子分别展示使用了冻结UI和不使用冻结UI的效果区别
Freezing UI
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
with poco.freeze() as frozen_poco:
t0=time.time()for item in frozen_poco('Scroll View').offspring(type='Text'):printitem.get_text()
t1=time.time()print t1 - t0 #大约6 ~ 8秒
No Freezing UI
importtimefrom poco.drivers.unity3d importUnityPoco
poco=UnityPoco()
t0=time.time()for item in poco('Scroll View').offspring(type='Text'):printitem.get_text()
t1=time.time()print t1 - t0 #约50 ~ 60 s
airtest测试用例_Airtest 常用方法相关推荐
- airtest测试用例_airtest-template
airtest-template 第一章运行环境搭建 第二章.UI框架配置说明(*****) 1.框架结构 businessdao.air: 提供用例场景运行日志插入与更新数据库操作 commonut ...
- 编写测试用例的常用方法
等价类划分法: 等价类划分法:等价类是输入的集合,比如在注册时,手机号规定为系统内不存在的手机号,那么所有已存在的手机号是一个等价类,所有不存在的手机号是另一个等价类.在每个等价类中选取一定数目的值作 ...
- 【测试】编写测试用例的常用方法
文章目录 1)等价类划分法 1.1 什么是等价类 有效等价类: 无效等价类: 1.2 划分标准 1.3 划分方法 1.确立等价类 2.转化为测试用例 1.4 实例:三角形问题 1.4.1 分析对输入条 ...
- 测试用例的测试编号是自己定义的还是别人给的_初级软件测试工程师必须掌握的东西...
第一自己根据已有的知识思考; 第二无果网上搜索; 第三最后才找人询问. 一.前言 功能测试是测试工程师的基础功,很多人功能测试还做不好,就想去做性能测试.自动化测试.很多人对功能测试的理解就是点点点, ...
- 如何编写测试用例及用例的意义
一.概念 1.什么是测试用例? 在测试过程中很重要的一类文档,它是测试工作的核心.是一组在测试时输入输出的标准.是软件需求的具体对照. 2.测试用例的作用: 检验软件是否满足客户需求.体现一个测试人员 ...
- 如何编写测试用例?(详细分析)
一.概念 1.什么是测试用例? 为了实施测试而向被测系统提供的一组集合: 2.测试用例的作用? 检验软件是否满足用户的需求,体现一个测试人员的工作量.展现测试用例的设计思路: 3.测试用例包含哪些内容 ...
- 测试用例设计方法 之【等价类划分法】
前言: 在没有测试用例之前,团队里的成员进行测试时,完全"以人为本",根据个人思路.需求理解度.发散性思想来完成测试系统,人无完人,弊端显而易见.衍生出[测试用例]后,测试工作的目 ...
- 2021最详细的测试用例的设计方法及案例——骚操作
测试用例的设计方法 一.概念 1.什么是测试用例? 在测试过程中很重要的一类文档,它是测试工作的核心.是一组在测试时输入输出的标准.是软件需求的具体对照. 2.测试用例的作用: 检验软件是否满足客户需 ...
- 【测试】编写测试用例的思路和方法
文章目录 1)什么是测试用例? 1.1 测试用例的定义 测试用例的内容: *为什么需要测试用例? 测试用例的作用: 1.2 测试用例的元素 测试目标(Why): 测试对象(What): 测试环境(Wh ...
最新文章
- 伯克利新无监督强化学习方法:减少混沌所产生的突现行为
- 解决:设置中打开蓝牙,測试机不会自己主动搜索设备
- 获得诺贝尔奖之后影响力会下降?绘制精英科学家的职业生涯路线图
- [HEOI2016/TJOI2016]求和(第二类斯特林数)
- 51NOD-1028 大数乘法V2【大数】
- 使用火狐解决网站图片不能复制下载的问题
- 【论文笔记】ego_planner_swarm
- linux命令cd 什么意思,Linux命令 cd ./.是什么意思
- 第三章:Servlet基础
- 软考高项 : 计算题汇总
- java求4位会员卡号之和中奖,日常作业2018.12.25
- Win7 C盘瘦身 微信文件夹太大WeChat Files
- 计算机网络属性设置知识,系统属性设置快捷键
- 深度分析AI新职位丨人工智能训练师是什么?做什么的?发展前景如何?
- switch内部执行顺序
- [Unity3D]-协程的介绍和使用
- 计算机专业学生常用的软件,盘点学生党必备高效实用软件
- 2019沈阳网络赛B.Dudu's maze
- php监听网卡数据,VnStat PHP:用于监控网络带宽使用的基于Web的界面
- 在线招聘江湖:老、中、新三代平台对垒
热门文章
- ASP.NET Core应用针对静态文件请求的处理[5]: DefaultFilesMiddleware中间件如何显示默认页面...
- Nginx学习之一:从权威途径(wiki)了解Nginx
- C#编写WINNT服务,随便解决安卓开发遇到的5037被众多程序无节操占用的问题
- 洛谷 P3952时间复杂度 (本地AC测评RE的伪题解)
- shell输入输出重定向
- 六省联考2017 Day1
- mysql创建视图不允许子查询
- 程序员必须知道的10大算法(转)
- 大数据之-Hadoop3.x_Yarn_常用命令---大数据之hadoop3.x工作笔记0147
- STM32工作笔记0075---UCOSIII任务管理(下)