赞
踩
目前游戏自动化测试这块,据我了解的信息,挺多同行都采用了网易游戏的airtest这个测试框架,容易入门,只需要了解下Python的基础语法,加上还有airtest的IDE,很快就能上手,我这里呢就不重复写官网上的例子了,主要说说脱离了airtest IDE用Python来写UI自动化测试用例,可能写的也比较粗浅,仅供参考。
pip install -U airtest
注意:在Mac/Linux系统下,需要手动赋予adb可执行权限,否则可能在执行脚本时遇到 Permission denied 的报错:
# mac系统
> cd {your_python_path}/site-packages/airtest/core/android/static/adb/mac
# linux系统
> cd {your_python_path}/site-packages/airtest/core/android/static/adb/linux
> chmod +x adb
更多安装问题解决参考官网
我这里举例个ARPG游戏里的一个坐骑功能
1.需要导入我自定义的模块utils,我对airtest的断言方法进行了封装还有adb命令的封装,下文再一一介绍,先说用例本身
'''
@File : testZuoQi.py
@Contact : 512759438@qq.com
'''
from autoTest.utils import *
from airtest.cli.parser import cli_setup
if not cli_setup():
auto_setup(__file__, logdir=LOGPATH, devices=["Android:///",])
def auto_setup(basedir=None, devices=None, logdir=None, project_root=None, compress=0):
2.初始化
class TestZuoQi(WrapAirtest):
def __init__(self):
super(TestZuoQi, self).__init__()
self.png_path = '/xxx/autoTest/airTestPng/zuoqi/'
self.switch_up = 'up_button.png'
self.switch_down = 'down_button.png'
self.model_lock = 'model_lock.png'
self.pick_on = 'pick_on.png'
self.pick_off = 'pick_off.png'
3.功能入口
def entrance(self,en_1=None,en_2=None,en_3=None):
if self.exists_png(en_2) is False:
pos = self.wait_png(en_1,10)
if pos is not False:
self.touch_pos(*pos)
else:raise TargetNotFoundError
cz = self.wait_png(en_2,10)
if cz is not False:
self.touch_pos(*cz)
self.assert_exists(en_3,'显示坐骑按钮')
self.touch_png(en_3)
4.页面标题
def title(self,title_1,title_2):
self.assert_exists(title_1,'标题名字显示正确')
self.assert_exists(title_2,'页签名字显示正确')
5.tips说明
def tips(self,tips_button,ensure_button,describe):
"""
tips说明
:param tips_button: 问号按钮
:param ensure_button: 确定按钮
:param describe: 说明tips
"""
self.assert_exists(tips_button,'显示tips按钮')
self.touch_png(tips_button)
self.assert_exists(describe,'描述显示正确')
self.touch_png(ensure_button)
self.assert_not_exists(ensure_button,'点击确定后tips关闭')
6.激活按钮
def activate(self,activate_button):
"""
激活
:param activate_button: 激活按钮
"""
self.assert_exists(activate_button,'显示激活图标')
self.touch_png(activate_button)
self.assert_not_exists(activate_button,'激活后激活图标消失')
7.属性详情页对比
def attr_equal(self,init_attr,attr_1,attr_2):
self.assert_exists(init_attr,'初始化属性是否为零')
self.assert_equal(attr_1,attr_2,'升级后属性是否相等')
8.资源模型
def model(self,*model_png:list) -> bool:
"""
模型
:param model_png: 10个已解锁的模型
"""
if len(model_png) == 10:
self.assert_exists(model_png[0],'1阶坐骑')
self.touch_png(self.switch_up)
for i in range(1,len(model_png)):
if self.assert_exists(model_png[i],f'{i+1}阶坐骑'):
self.touch_png(self.switch_up)
else:self.assert_exists(self.model_lock,f'{i+1}阶坐骑没有激活-锁住图标')
return True
else:return False
9.自动购买选项
# 选中状态,默认要去选中 def pick_status(self,switch:bool=True) -> bool: if switch is True: if self.exists_png(self.pick_on): return True else: self.touch_png(self.pick_off) self.assert_exists(self.pick_on,'勾选自动购买成功') return True elif switch is False: if self.exists_png(self.pick_off): return False else: self.touch_png(self.pick_on) self.assert_not_exists(self.pick_off, '取消勾选自动购买') return False
10.升级
def upgrade(self,upgrade_button,upgrade_loop_button,fail_tips,get_item,star_2,star_max,lvl:list,fight:list): """ :param upgrade_button: 升星按钮 :param upgrade_loop_button: 一键提升 :param fail_tips: 失败tips-产出路径 :param get_item: 获取链接 :param star_2: 升星一次,两颗星 :param star_max: 满星 :param lvl: 各个阶数 :param fight: 各阶的战力 :return: """ # 检测自动购买是否勾选 if self.pick_status(switch=False) is False: # 点击升星 self.touch_png(upgrade_button) self.assert_exists(fail_tips,'升星材料不足弹出提示') # 点击其他区域关闭tips self.touch_png(upgrade_button) # 点击一键提升 self.touch_png(upgrade_loop_button) self.assert_exists(fail_tips,'一键提升时材料不足弹出提示') self.touch_png(upgrade_button) # 点击获取连接 self.touch_png(get_item) self.assert_exists(fail_tips,'弹出获取路径') self.assert_exists(lvl[0],'一阶图标显示') self.assert_exists(fight[0],'初始战力') if self.pick_status(switch=True) is True: # 升星一次 self.touch_png(upgrade_button) self.assert_exists(star_2,'升星成功,出现两颗星星') # 升到满星 self.touch_png(upgrade_button,8) self.assert_exists(star_max,'升到满星') # 升阶 self.touch_png(upgrade_button) self.assert_exists(lvl[1],'1阶变成2阶') self.assert_exists(fight[1], '2阶战力') for i in range(2,9): self.touch_png(upgrade_button,9) self.assert_exists(star_max,f'{i}升到满星') # 升阶 self.touch_png(upgrade_button) self.assert_exists(lvl[i], f'{i}阶变成{i+1}阶') self.assert_exists(fight[i], f'{i+1}阶战力')
11.执行用例
def test_case(self):
self.entrance('hp.png','chengzhang.png','zuoqi_button.png')
self.title('title_1.png','title_2.png')
self.tips('tips_button.png','ensure_button.png','describe.png')
self.activate('activate_button.png')
lvl_list = [f'lvl_{i}' for i in range(1,11)]
fight_list = [f'fight_{i}' for i in range(1,11)]
self.upgrade('upgrade_button.png','upgrade_loop_button.png','fail_tips.png','get_item.png',
'star_2.png','star_max.png',lvl_list,fight_list)
model_list = [f'model_{i}' for i in range(1,11)]
self.model(model_list)
return 'zuoqi end'
simple_report:输出测试报告
具体参数:simple_report(filepath, logpath=True, logfile=LOGFILE, output=HTML_FILE,export_report=None):
if __name__ == "__main__":
go = TestZuoQi()
go.test_case()
simple_report(__file__, output='zuoqi.html')
设置Windows/Linux的报告输出路径
from pathlib import Path
import os
REPORTPATH = ''
LOGPATH = ''
if os.name == 'nt':
REPORTPATH = Path('F:/FTP') / 'report'
elif os.name == 'posix':
REPORTPATH = Path(__file__).parent / 'report'
LOGPATH = REPORTPATH / 'log'
REPORTPATH.mkdir(parents=True, exist_ok=True)
1.初始化,调用adb封装类,检查设备是否连接
class WrapAirtest:
def __init__(self):
self.png_path = None
self.adb = AdbShell()
if self.check_devices():
self.screen_size = self.adb.getSize()
self.app_name = '测试包名或关键字'
self.app = self.adb.getPack_3(filter=self.app_name)
else:raise ConnectionError
# 获取操作系统
self.system = os.name
2.检查安卓设备是否连接
def check_devices(self):
if self.adb.getDevices() is not False:
return True
else:
self.adb.adb('adb kill-server')
self.adb.adb('adb start-server')
3.断言方法封装
def assert_exists(self,v, msg): """ 为了抛出异常时继续执行 :param v: 要识别的图片 :param msg:测试用例描述 """ try: assert_exists(Template(self.png_path+v, resolution=self.screen_size,threshold=0.6), msg) return True except: return False def assert_not_exists(self,v, msg): try: assert_not_exists(Template(self.png_path+v,resolution=self.screen_size), msg) return True except: return False def touch_png(self,png,times=1): """ 封装touch :param png: 要点击的图片 :param times: 点击次数 Template(r"tpl1532588127987.png", record_pos=(0.779, 0.382), resolution=(407, 264), threshold=0.6, target_pos=5, rgb=False) threshold:识别精准度 target_pos:点击坐标偏移 rgb:色彩识别 """ for _ in range(5): try: pos = touch(Template(self.png_path+png, resolution=self.screen_size,threshold=0.6),times) if pos: return True except: print('This picture was not found =>', png) return False
为了方便在Python代码里使用adb命令进行封装
调用时直接调用 AdbShell() ,用一次初始化一次,用于及时检测设备的状态更新,热拔热插
adb命令是外部命令,Python无法直接识别,我是采用subprocess来执行
1.判断系统和隐藏子进程窗口
import os
import subprocess
if os.name == 'nt':
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
2.封装指令并返回结果
def adb(self,command):
return [i.decode() for i in subprocess.Popen(command,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,).stdout.readlines()]
1.设备连接状态
def getDevices(self,host='192.168'): _result = self.adb('adb devices') usbDev = [] wifiDev = [] # print(_result) for item in _result: # 筛选有线无线设备 body_filter = item.split() if 'device' in body_filter: if host in body_filter[0]: self.connectStatus = True wifiDev.append(body_filter[0]) else: usbDev.append(body_filter[0]) if len(usbDev) > 0 or len(wifiDev) > 0: if len(wifiDev) > 0: # 优先返回无线设备 return wifiDev[0] else: return usbDev[0] else: return False
2.获取分辨率
def getSize(self):
body = self.adb('adb -s %s shell wm size'%self.dev)
body_1 = body[0].split()[2]
body_2 = re.search('(\d+)x(\d+)',body_1)
return int(body_2.group(1)),int(body_2.group(2))
3.获取第三方包名
def getPack_3(self, filter=''):
name_list = []
pack3 = self.adb('adb shell pm list packages -3')
if filter:
for packName in pack3:
if filter in packName:
name = str(packName).split(':')
name_list.append(name[1].split()[0])
return name_list
else:return pack3
adb命令的搬运工,更多封装请参考adb命令大全自行定制。
整篇写完下来,还有些地方要去优化,airTest的应用我这里经验不足,等后续有项目要用airTest时再重新优化出新的一版,欢迎评论留言,要是觉得不错,点个赞,谢谢!
最后的最后,各位的关注、点赞、收藏、碎银子打赏是对我最大的支持,谢谢大家!
需要源码的小伙伴关注微信公众号ID:gameTesterGz
或扫描二维码关注回复airtest脚本即可
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。