Airtest airtest 多设备并发运行批量脚本

直南瓜 · August 26, 2019 · Last by 直南瓜 replied at October 08, 2019 · 2162 hits

引言

用airtest快一年了,一直没有好好总结过,前几天看到有人发帖问多设备并行测试的事,发现现有的文档都只提供了单设备串行脚本的案例,在脚本较多的情况下会比较耗时,于是自己简单做了一个demo,希望能给新手一些帮助!

参考文档:xinufo https://testerhome.com/topics/16567

需求

1.多设备并行批量的脚本(适合做兼容测试)
2.多设备分配运行批量的脚本(适合做功能的回归测试)
3.每个脚本单独生成一个html报告并在父文件夹生成一个聚合报告

exe使用步骤

下载点这里:懒人链接
(1).双击打开airtest启动器.exe,进入程序主界面

(2).左边选取安卓设备,右边点击‘选取脚本路径’按钮,选择脚本所在的根目录,选好后可在右边窗口选取要运行的脚本;

(3).选取模式,模式分两种,在【config.ini 全局配置】中会有介绍;
(4).点击启动按钮,通过控制台查看运行情况,静静地等待运行结果;
(5).运行结束后会有一个弹窗提示,点击ok按钮查看该次测试的报告;

(6).历史报告会自动生成在logs_root文件夹下

源码使用步骤

github地址

(1).把自己写的air脚本放置到scripts文件夹下
(2).打开config.ini,根据注释填写运行模式、脚本名称及设备序列号;
(3).运行main.py文件,推荐用pycharm运行,全局环境下也可以直接用 运行.bat 来运行;
(4).等待运行结果,自动生成的报告将在logs_root文件夹;注:报告依赖airtest的静态,这里不建议更改报告的文件结构

config.ini 全局配置

[baseconf]
scripts_root = scripts
scripts =
devices = all
mode = 1
platform = Android

scripts_root #脚本根目录,默认为工程目录下的scripts文件夹

scripts # 要运行的脚本名称列表,半角逗号连接,如:SzwyMobile1014-1036.air,hh.air,无内容则按顺序运行scripts目录下所有脚本

devices = all # 设备id,半角逗号连接,格式为:PBV0216727000183,8TFDU18926001948,为空默认选取电脑上连的第一台设备,all则运行所有设备

mode = 1 # 1:每台设备各自运行所有脚本,2:所有设备分配运行所有脚本

platform = Android # 平台为Windows时设备号需填窗口句柄

这里提供两种模式:

  • mode = 1:每台设备各自运行所有要跑的脚本,即批量并行相同脚本,报告数量=脚本数量x设备数量,适合做兼容测试;
  • mode = 2:采用消息队列,将所有要跑的脚本逐一以分配的方式给空闲的设备运行,报告数量=脚本数量,适合做功能的回归测试;

流程分析

1.利用multiprocessing根据设备数量生成进程池,每台设备占用一条子进程;

2-1.模式1 每条进程里做一样的操作,将所有要运行的脚本实例化成MyAirtestCase,再添加进unittest.TestSuite()中,并一起给unittest.TextTestRunner运行

for fPy in oScripts:
oCase = NewCase(fPy, sLogDir, sDeviceNum)
oTestSuite.addTest(oCase)
...
unittest.TextTestRunner(verbosity=0).run(oTestSuite) # 运行脚本

2-2.模式2 创建multiprocessing.Queue()队列,将所有脚本put进队列中

oAirQueue = multiprocessing.Queue()
for sAirScript in lSuite:
oAirQueue.put(sAirScript)

3.模式1 无特殊处理,静静等待每一条进程TestSuite()里面添加的case全都运行完即可;
模式2 在每条子进程里通过Queue()的get()方法获取一个脚本,给unittest运行

if oScripts.empty():
return
fPy = oScripts.get()
oCase = NewCase(fPy, sLogDir, sDeviceNum, oScripts)
oTestSuite.addTest(oCase)
unittest.TextTestRunner(verbosity=0).run(oTestSuite) # 运行脚本

4.模式2 在一个脚本运行结束时,即tearDown函数里,判定队列是否存在,如果队列里还有脚本没跑,则继续选取脚本继续运行,直到脚本队列为空;
模式1 无队列,不执行以上逻辑,跑完一个脚本直接生成对应的报告,并执行下一个case

def tearDown(self):
try:
output = os.path.join(self.logdir, "recording_0.mp4")
print(output)
self.m_oDev.stop_recording(output)
except:
traceback.print_exc()
self.Report()
if self.queue:
RunScript(self.sDevice, self.m_LogRoot, oScripts=self.queue)

5.所有进程结束,代表单次测试结束,生成聚合报告

def Finish(sLogDir):
print('test finish')
sCombineLog = os.path.join(sLogDir, 'log.html')
sCombineTxt = os.path.join(sLogDir, 'log.txt')
with open(sCombineTxt, 'r') as f:
lMsg = f.readlines()
template_vars = {
'patch_tag': os.path.basename(sLogDir),
'files': [json.loads(line) for line in lMsg]
}
report.render('combine_log.html', sCombineLog, **template_vars)

其他模块作用

runner.py 利用multiprocessing根据设备数量生成进程池,单个进程里再利用unittest生成每一个脚本的测试用例

report.py 根据模板生成单个airtest脚本测试的报告,重写了airtest源码中若干源码,减少报告中的静态资源的路径依赖

utils.py 该模块提供了一些通用接口,其中还包括压缩本地报告上传至云平台的代码,上传地址需使用者自己填写

video.py 该模块利用OpenCV实现Windows端的录屏功能,弥补了airtest在PC运行时无法录屏的缺点。其中视频的帧率和录制时间间隔可以自己调整至一个合适的数值

file_lock.py 为了记录单次测试里每一个报告的聚合结果,这里采用将结果写入临时文件的方式。由于存在多条进程同时对一个文件进行读写操作的情况,我只是简单得用了文件锁来处理了一下。经测试在windows端进程较多的情况下仍会出现结果写入异常的情况,条件足够的话建议将结果保存在自己的数据库中。

最后

模块的具体作用还是直接看github和源码吧,废话不多说,show my code
github地址

共收到 12 条回复 时间 点赞

IOS设备有办法做到吗?

张全蛋 回复

忏愧,没用过mac机,我个人感觉ios应该只要改写连接设备的方式,进程的创建和单元测试应该是一样的

👍 赞一个

直南瓜 回复

据我了解ios的还没支持一台Mac同时执行多台设备的,他的端口号是固定的

5Floor has been deleted

目录名称无效啥问题呢。。。请教!请教!请教!

TD 回复

大佬,能不能讲讲你的研究,眼下我有这样一个需求,就是一台mac连多台ios设备,这个端口是固定的,不能修改吗?


window创建目录不能有冒号,你是用无线连接的吧,这里是我考虑不全,你用设备序列号连就可以,我提交了个新版你可以下载试试,不过还是建议用有线

直南瓜 回复

我们是智能电视智能盒子的应用,只能通过网络adb去连接

重新下载一下试试能不能用了

楼主,请问一下,我为啥每次走到report模块,就报如下错误呢

alice-92 回复


检查一下这个self.script_root是不是None

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up