基于appium的自动化测试工具,支持多进程,性能采集分析等
本帖已被设为精华帖!,
简介
基于appium编写的自动化测试工具。使用方法简单,编写yaml文件格式的测试用例即可,无需改动任何一行代码。支持Android,多台设备并行,性能采集等。
开源地址:https://github.com/ztwo/Auto_Analysis
为什么要重复造轮子
- 稳定:执行过程中会被异常打断,目前已经捕获这些异常,增加了判断
- 直观:例如性能报告有横向对比,错误日志筛选等
- 简单:无需改动一行代码即可运行测试
- 扩展:代码封装清晰,比较容易扩展,增加解释器
环境要求
- macOS,linux,windows
- appium 1.5.0+
- python 2.7
工具特性
执行编写yaml格式的testcase,执行后即可得到测试报告
- 1:支持Android 4.2.2 以上
- 2:支持多设备并行测试
- 3:性能采集与横向对比,每个case均是独立结果。
- 4:支持log采集与清洗
- 5:对appium异常的一些封装,例如失败重试,需要点击才能安装等
- 6:用例编写支持继承多重继承,大部分用例仅需写两个步骤即可
快速开始
- git clone https://github.com/ztwo/Auto_Analysis.git
- cd Auto_Analysis
- python setup.py install
- python demo_run.py
- result内查看测试报告
执行效果
报告样式
测试用例编写规范
- 1: 需要了解yaml格式编写规范,建议使用pycharm编写,自带yaml文档检查器. yaml语法学习地址
- 2: 用例名不可重复,会影响用例的继承
测试用例字段解释
字段 | 解释 | 演示 | 包含字段 | 是否必须 |
---|---|---|---|---|
test_name | 用例名 | login | / | 是 |
test_id | 用例id | 0001 | / | 否 |
test_control_type | 查找控件方式 | xapth | xpath, id | 否 |
test_action | 操作方法 | click | 见下表 | 是 |
test_control | 控件 | com.xx.id | / | 否 |
test_text | 断言、输入文本 | test | / | 否 |
test_inherit | 继承用例名 | login | / | 否 |
test_range | 循环本步骤次数 | 2 | / | 否 |
test_sleep | 步骤执行后,等待秒 | 2 | / | 否 |
test_wait | 配合断言,等待控件秒 | 30 | / | 否 |
test_action | 解释 | 所有字段 | 配合字段 | 辅助配合字段 |
---|---|---|---|---|
click | 点击 | click | test_control_type,test_control | / |
send_keys | 发送文本 | send_keys | test_control_type,test_control,test_text | / |
swipe | 滑动 | swipe_left,swipe_right,swipe_up,swipe_down | / | / |
assert | 断言 | assert | test_control_type,test_control,test_text | test_wait |
entity | 实体按键 | entity_home,entity_back,entity_menu,entity_volume_up,entity_volume_down | / | / |
完整用例范例,用例名:login
---
-
test_name: 点击跳过
test_id: 0001
test_control_type: id
test_action: click
test_control: test.joko.com.myapplication:id/button1
-
test_name: 输入帐号名
test_id: 0002
test_control_type: id
test_action: send_keys
test_control: test.joko.com.myapplication:id/editText
test_text: 199999999
-
test_name: 输入密码
test_id: 0003
test_control_type: id
test_action: send_keys
test_control: test.joko.com.myapplication:id/editText2
test_text: 9999
-
test_name: 点击登录
test_id: 0004
test_control_type: xpath
test_action: click
test_control: //android.widget.Button[contains(@text,'确定')]
-
test_name: 向上滑动页面
test_id: 0005
test_action: swipe_up
test_range: 3
-
test_name: 向下滑动页面
test_id: 0006
test_action: swipe_down
test_range: 3
主要代码分析
-
原理:开启appium driver,解析yaml格式testcase,执行,输出报告
-
po.BasePage:封装appium driver方法
def send_key_event(self,arg):
"""
操作实体按键
:return:
"""
event_list = {'entity_home':3,'entity_back':4,'entity_menu':82,'entity_volume_up':24,'entity_volume_down':25}
if arg in event_list:
self.driver.keyevent(int(event_list[arg]))
- po.ExecuteCase:执行case类
def get_all_case(self, path_yaml):
"""
:param path_yaml: 用例地址
:return: 返回yaml内字典,且遍历继承的信息,支持多重继承
"""
def get_case(path_yaml):
case_list = []
inherit_case_file = public.GetCase.case_yaml_file()
with open(path_yaml) as f:
for dic in yaml.load(f):
if isinstance(dic, dict):
if 'test_inherit' in dic:
inherit_case_name = dic['test_inherit']
inherit_case = inherit_case_name + '.yaml'
if inherit_case in inherit_case_file.keys():
case_list += case_list + get_case(inherit_case_file[inherit_case])
else:
case_list.append(dic)
else:
U.Logging.warn('get_case:not dic')
return case_list
return get_case(path_yaml)
def __analysis_yaml(self, path_yaml):
"""
测试用例解释器
:param path_yaml: 测试用例地址
1:每执行一条用例会记录下当前的性能
:return:
"""
- po.integration:初始化环境
- lib.ScreenShot:minicap截图,用于appium screen报错后,调用minicap
def phone_screen(self, width_height, filename):
"""
截图
:param width_height: 宽高
:param filename: 存储的文件名
:return:
"""
U.Logging.info('phone_screen:%s' % width_height)
self.adb.shell(
"'LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P {}/0 -s > /data/local/tmp/{}.png'".format(
width_height, filename))
U.Logging.info('phone_screen:success')
- lib.adbUtils:adb方法封装,几乎封装了所有常用的方法。(此处感谢testerhome某位朋友,是基于他的开源脚本扩写的,有知道的是谁的帮忙@ 下)
def last_update_time(self):
"""
查询当前屏幕应用安装更新时间
"""
for package in self.shell(
'dumpsys package %s' %
self.get_current_package_name()).stdout.readlines():
if 'lastUpdateTime' in package:
return package.split('=', 2)[1].strip()
def wifi_name(self):
"""
查询连接wifi名称
"""
for package in self.shell('dumpsys wifi').stdout.readlines():
if package.startswith('mWifiInfo'):
wifi_name = re.findall(r'SSID:([^"]+), BSSID', package)
if not wifi_name:
return None
else:
return wifi_name[0].strip()
-
lib.Utils:封装的一些基础方法,如创建数据库,log输出等
-
public.installApp:安装应用,且同时开启线程,监控屏幕是否有需要点击的安装按钮
def main(self):
"""
开启多线程:
线程1:安装应用
线程2:获取当前页面是否有可点击的按钮
:return:
"""
ini = U.ConfigIni()
install_file = ini.get_ini('test_install_path', 'path')
package_name = ini.get_ini('test_package_name', 'package_name')
threads = []
click_button = threading.Thread(target=self.tap_all, args=())
threads.append(click_button)
install_app = threading.Thread(
target=self.__install_app, args=(
package_name, install_file))
threads.append(install_app)
process_list = range(len(threads))
for i in process_list:
threads[i].start()
for i in process_list:
threads[i].join()
self.adb.shell('"rm -r /data/local/tmp/*.xml"')
目前缺点:
- 1.目前不支持iOS,不支持H5,不过框架是基于appium,增加解释器即可
- 2.测试报告样式略丑,因为样式是纯html,不会js,得慢慢改
正在完善
- 1.对于执行过程中异常的梳理,例如低电量,其实已经实现,但会影响执行设备的性能。还需要再打磨
- 2.错误信息的完善
开源地址:https://github.com/ztwo/Auto_Analysis
* 注:本文来自网络投稿,不代表本站立场,如若侵犯版权,请及时知会删除