ATX ATX 结合 Maxim 实现多设备并行执行压力测试

linpengcheng · 2018年12月10日 · 最后由 linpengcheng 回复于 2019年01月18日 · 1141 次阅读

介绍

之前分享的UI自动化测试框架: 基于 ATX-Server 的 UI 自动化测试框架 实现了多设备的并行测试,能够自动生成报告并日志输出到指定的文件夹下面.

在此基之上,增加了基于maxim的压测功能.多设备的并行执行都是基于之前的基础之上.
能够实现app卸载重新安装之后,账号登录,进入到指定页面之后再执行monkey压力测试

GitHub地址还是这个:https://github.com/pengchenglin/ATX-Test

实现方式

在用maxim的时候,发现在在启动uiautomator2的时候,maxim就没法用了,原因是uiautomator2和Maxim工作时都需要连接系统的AccessibilityService.
在看uiautomator2的文档的时候发现是可以启停android-uiautomator-server

d.service("uiautomator").stop()     # 暂停
d.service("uiautomator").start() # 启动

atx-agent提供执行设备端shell命令的功能,操作maxim其实用shell就够了.
push 相关的jar和配置文件到手机上;pull 运行完成后的log日志内容

相关链接

WiFi 无线拉起执行 APP 稳定性 / 压力测试,免 USB 连线
基于 Android Monkey 二次开发,实现高速点击的 Android Monkey 自动化工具 fastmonkey - 代号 Maxim
浅谈自动化测试工具 python-uiautomator2

流程解析

工程目录


ATX_Test/Public/Maxim文件夹下存放了maxim运行是需要的所有文件,运行的时候会将指定文件push到Android设备中.

ATX_Test/Public/maxin_monkey.py是对maxim的shell命令的封装和执行monkey操作的两个方法封装,具体的参数定义在里面写比较清楚,可以直接去看代码
maxin_monkey.py下run_monkey的代码如下

def run_monkey(cls, monkey_shell, actions=False, widget_black=False):
'''
清理旧的配置文件并运行monkey,等待运行时间后pull log文件到电脑
:param monkey_shell: shell命令 uiautomatortroy max.xpath.selector文件需要配置正确
:param actions: 特殊事件序列 max.xpath.actions文件需要配置正确
:param widget_black: 黑控件 黑区域屏蔽 max.widget.black文件需要配置正确
:return:
'''
log.i('MONKEY_SHELL:%s' % monkey_shell)
cls.clear_env()
cls.push_jar()
if monkey_shell.find('awl.strings') != -1:
cls.push_white_list()
if monkey_shell.find('uiautomatortroy') != -1:
cls.push_selector()
if actions:
cls.push_actions()
if widget_black:
cls.push_widget_black()
cls.set_AdbIME()
runtime = monkey_shell.split('running-minutes ')[1].split(' ')[0]
log.i('starting run monkey')
log.i('It will be take about %s minutes,please be patient ...........................' % runtime)
# restore uiautomator server
cls.d.service('uiautomator').stop()
time.sleep(2)
cls.d.shell(monkey_shell)
time.sleep(int(runtime) * 60 + 30)
log.i('Maxim monkey run end>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
# restore uiautomator server
cls.d.service('uiautomator').start()

然后就是在ATX_Test/Public/Driver.py下增加了run_maxim实现maxim的多设备执行操作

ATX_Test/Monkey下是登录操作的脚本和最终的运行maxim_monkey的执行文件,运行就执行monkey_run.py就好了

工作流程

ATX_Test/Monkey/monkey_run.py的代码:

from Public.Drivers import Drivers
from Public.Report import *
from Public.maxim_monkey import Maxim
import unittest
from Monkey import login_steps

if __name__ == '__main__':
# back up old report dir 备份旧的测试报告文件夹到TestReport_backup
data = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
backup_report('./MaximReport', './MaximReport_History', data)
cases = unittest.TestSuite()
cases.addTest(login_steps.abcd('test_install_login'))

command = Maxim().command(package='com.github.android_app_bootstrap', runtime=1, mode='uiautomatordfs',throttle=500,options=' -v -v ', whitelist=True)

Drivers().run_maxim(cases=cases, command=command, actions=True, widget_black=False)

还是使用了macaca的bootstrap app作为demo演示
执行monkey前 卸载重装,账号登录的操作直接写成了unitest的脚本,这样原来的UI自动化写的脚本直接拿来用,其实很简单的几行就搞定了

class abcd(unittest.TestCase, BasePage):
@classmethod
@setupclass
def setUpClass(cls):
cls.d.app_stop_all()

@testcase
def test_install_login(self):
'''安装启动android_app_bootstrap'''
self.d.app_uninstall(pkg_name)
self.local_install(apk_path)
self.d.app_start(pkg_name)
self.set_fastinput_ime()
time.sleep(3)
login.login_page().input_username('username')
login.login_page().input_password('password')
login.login_page().click_login_btn()

运行maxim的命令通过maxim_monkey.py下的 Maxim().command来实现组装
最后执行Public.Drivers().run_maxim来开始运行

运行maxim的主要代码如下:

def _run_maxim(run, cases, command, actions, widget_black):
log = Log()
log.set_logger(run.get_device()['model'], os.path.join(run.get_path(), 'client.log'))
log.i('udid: %s', run.get_device()['udid'])

# set cls.path, it must be call before operate on any page
path = ReportPath()
path.set_path(run.get_path())

# set cls.driver, it must be call before operate on any page
base_page = BasePage()
if 'ip' in run.get_device():
base_page.set_driver(run.get_device()['ip'])
else:
base_page.set_driver(run.get_device()['serial'])

try:
# run cases
base_page.d.shell('logcat -c') # 清空logcat
if cases:
run.run_cases(cases)
Maxim().run_monkey(monkey_shell=command,actions=actions, widget_black=widget_black)

base_page.d.shell('logcat -d > /sdcard/logcat.log')
time.sleep(1)
base_page.d.pull('/sdcard/logcat.log', os.path.join(path.get_path(), 'logcat.log'))
base_page.d.pull('/sdcard/monkeyerr.txt', os.path.join(path.get_path(), 'monkeyerr.txt'))
base_page.d.pull('/sdcard/monkeyout.txt', os.path.join(path.get_path(), 'monkeyout.txt'))

base_page.set_original_ime()
base_page.identify()
except AssertionError as e:
log.e('AssertionError, %s', e)

设定好报告存放的路径,初始化设备之后,执行相关的操作:

1.清空logcat
2.存在UI自动化操作cases的执行cases
3.开始运行monkey(push相关的文件到手机,执行monkey shell命令)
4.monkey执行完成,将logcat.log monkeyerr.txt monkeyout.txtpush到电脑上报告存放的路径

输出结果


在monkey_run.py同级目录下,会将结果存在于一时间命名的文件夹下,不同的设备存在在不同的设备文件夹下

共收到 3 条回复 时间 点赞

前段时间也做了同样的的功能,感觉他们结合起来用真的特别棒!


1.第一个红框那有点不懂,请大神帮忙解释一下
2.第二个框那,好像有点错误,_db根本没有insert_multiple这个方法,而table类中才有insert_multiple这个方法

hk 回复

看一下tinydb库的用法 这段代码是小红书我复制过来的

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册