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

直南瓜 · 2019年08月26日 · 最后由 hulu12 回复于 2023年06月01日 · 9926 次阅读

引言

用 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 地址

共收到 37 条回复 时间 点赞

IOS 设备有办法做到吗?

我去催饭 回复

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

👍 赞一个

直南瓜 回复

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

5楼 已删除

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

TD 回复

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


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

直南瓜 回复

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

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

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

alice-92 回复


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

仅楼主可见
llnhhy 回复

建议用数据库

楼主您好,我用了一下您的脚本,很适合我现在的项目,但是有个问题,我把所有的脚本放到 scripts 文件夹下,运行脚本会提示我找不到相应的图片。
我只有把脚本里面的图片改成绝对路径才能成功运行。我看了下源码也没有提到脚本图片位置的问题。

Casper 回复

感觉是你脚本里没写 auto_setup(file)

直南瓜 回复

多谢,确实是这个原因。

您好,我运行时报错了。这些库,我都有 install。
Traceback (most recent call last):
File "runner.py", line 60, in runTest
File "C:/Users/DELL/Desktop/H5/exe/scripts\小程序.air\小程序.py", line 7, in
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
ModuleNotFoundError: No module named 'poco.drivers.android.uiautomation'

部分代码如下:

-- encoding=utf8 --

author = "DELL"

from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

auto_setup(file)

xy = poco.get_screen_size()
x = xy[0]
y = xy[1]

wait(Template(r"tpl1574851348258.png", record_pos=(-0.129, 0.815), resolution=(1080, 1920)))

swipe((0.5*x,0.2*y),(0.5*x,0.8*y),duration=1)

21楼 已删除


请问 这是怎么回事??


请问:导致这个的原因是? 是因为脚本路径没有识别出.py 还是什么?上传的脚本通过本地批量运行都可以执行的 ,这个模块没有找到 求解 ?

hui 回复


有的个人电脑上面运行脚本的时候卡住不动,随机存在在不同的脚本上,但是有的电脑完全都是没有异常的 请问这个是什么情况


大佬,在 Q 上面运行 timeout 了 同样的脚本在 P 上面运行是没问题的 且 IDE 上运行 Q 也是没有问题的

零度 回复

是不是那台不行的电脑上有开着 IDE 或者 STF 之类有用到 minitouch 服务的东西

胡适 微信小程序自动化多设备分布式运行方案 中提及了此贴 05月08日 18:23
零度 回复

曾哥里面的 airtest 版本是 1.0.27 不支持安卓 10 的,你本地 IDE 能运行应该是比较新的 IDE 版本了,你可以选择把 airtest 版本升级到最新,或者是把 airtest1.0.30 里面关于安卓 10 的部分加到现在的 python 环境中

直南瓜 回复

曾哥还维护呢, 指导指导我啊

喵喵喵 回复

要不项目送你了,你自己去维护

直南瓜 回复

他每天都看你之前撸的代码😂

33楼 已删除

这个是不是不能做 web 自动化只能做手机自动化? 小米手机的 MIUI 11 版本会报错

好难下载下来 EXE,有没有其他链接可以下载

等老夫下载下来研究一下

小米 安卓 10 执行 air 脚本的时候,出现这个提示是什么原因呢?

airetest 并行的时候,如果对每个测试用例都调用 run_script,不同的测试用例参数不一样(比如脚本路径、日志路径等),而 run_script 中会设置 Settings 全局变量,这样难道不会有冲突吗

仅楼主可见

请问,我是连接了两台设备,为啥用例全都分配到一台机器上执行了。 测试用例的类应该是继承 unittest.TestCase 呢,还是代码里面的 MyAirtestCase?盼望答复!

可以提供一下 exe 文件的源码吗
想参考学习一下

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