python airtest UI自动化测试 您所在的位置:网站首页 python自动化框架airtest python airtest UI自动化测试

python airtest UI自动化测试

2024-07-09 13:43| 来源: 网络整理| 查看: 265

airtest UI自动化测试 前言环境python3安装安装airtest库 正文消费线的测试用例运行用例调用WrapAirtest设置路径封装airTest的类方法 调用AdbShellsubprocess封装adb命令 结语

前言

目前游戏自动化测试这块,据我了解的信息,挺多同行都采用了网易游戏的airtest这个测试框架,容易入门,只需要了解下Python的基础语法,加上还有airtest的IDE,很快就能上手,我这里呢就不重复写官网上的例子了,主要说说脱离了airtest IDE用Python来写UI自动化测试用例,可能写的也比较粗浅,仅供参考。

环境 python3安装 Python版本:3.7,官网原话:支持Python(2.7或 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 : [email protected] ''' from autoTest.utils import * from airtest.cli.parser import cli_setup if not cli_setup(): auto_setup(__file__, logdir=LOGPATH, devices=["Android:///",]) auto_setup的参数,我这里默认连接安卓手机 def auto_setup(basedir=None, devices=None, logdir=None, project_root=None, compress=0): 官方示范:auto_setup(file,logdir=True,devices=[“Android://127.0.0.1:5037/emulator-5554”])

2.初始化

示例的触控是基于图像识别,并没有接入pocoSDK,接入SDK的伙伴要替换相应的触控方法写的测试用例意思意思看看就好 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' WrapAirtest:在utils导入的模块定义图片路径和一些公用控件

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) 有3个层级的入口所以有en_1.2.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') 调用WrapAirtest 设置路径

设置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) 封装airTest的类方法

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 adbShell:封装的ADB命令,下文有说明

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') 没有连接的话重新启动adb-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 调用AdbShell

为了方便在Python代码里使用adb命令进行封装 调用时直接调用 AdbShell() ,用一次初始化一次,用于及时检测设备的状态更新,热拔热插

subprocess

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()] 封装adb命令

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 2018-2019 实验室设备网 版权所有