开源测试工具 DreamMultiDevices 框架解析 (一)

陈子昂 · September 18, 2019 · Last by 友台 replied at September 18, 2019 · 663 hits
前言

框架作者是一位上海上市游戏公司测试负责人,陈大猫也是一名游戏产业从业者,通过网络上成为了网友。
在腾讯系GA没有更新的2年后,网易的airtest出了一款游戏自动化的产品,在MSTC2018大会上亮相,社区内相关帖子也有不少,也有qq群,这块就不介绍了。

关于在IDE上使用 个人建议,不推荐的,主要是不能完成组内累积和其他项目复用,可读性不高和比较难维护。
这个论点在网上被反驳过,回应是本身工程思想很强或者开发能力强的人还是建议用工程化去开发,IDE不一定要OOP,python也是多范式的语言,如果只有工程思想的人花点时间学习代码,只会更好不会变差。

不用会代码提供编程计算在现阶段是属于关系自我矛盾的或者只是为了宣传,比如让用户新手引导一路点下去一样顺畅,写多了用户突然发现可以优化,还是改到工程里写吧,然后学习代码,成为自动化高手,然后一门语言到多门语言,走上一条去少林寺的道路。

正文

当然业内也有一批使用者用airtest做为底盘的基础上开发,出于种种原因,作者开源了这个airtest+混合poco+性能比脚手架晋升一步的框架属于比较完整的,支持在airtestIde以外执行
作者上篇文章 ,框架地址:https://github.com/saint228/DreamMultiDevicesfork以及参与维护。。其中受益者和赞赏者也可以来点星,关注,

安装方式具体看说明,请自建pip虚拟环境,后面会建议作者添加一个requriements.txt 指定版本的描述文件,然后【 pip install -r requriements.txt】

本文陈大猫和作者商量过,从程序运行顺序做源码解读,也顺带帮助宣传下框架。
【行文规范】
地址是指github上面地址,不是clone下来查看的。
画外音:自己夹带私货的导读,不包含对框架评论。

1.入口文件

DreamMultiDevices/blob/master/start.py
位置在项目根目录下面

from DreamMultiDevices.core import index
#Index.main()提供启动逻辑功能
#启动前前置行为:
#1.启动adb服务
#2.启动包装了index.main()

画外音:多线程和多进程编程也推荐这个模式,把相关逻辑文件引用链接到入口文件
执行骨干文件

DreamMultiDevices/blob/master/core/index.py
导入类库主要:
from multiprocessing import Process,Value #多进程模式 使用了创建多进程模块和共享变量
from DreamMultiDevices.core.MultiAdb import MultiAdb as Madb #自己封装的adbMadb是别名

index.main() 函数
1.先获取手机的device执行对象 支持多个

Madb().get_devicesList() #获取adb devices 列表

画外音:
等同devices = [devlist [0] for devlist in ADB().devices()],ADB().devices()由源码提供,列表推导式devlist [0] 里面内容,第一台链接上的手机。
ADB().devices()正确返回 是列表内套多个元祖对象 [(手机码, device),(手机码, device)]

Device应该是用于代码需要到DreamMultiDevices/blob/master/core/MultiAdb.py 查看

一开始陈大猫以为是典型的访问器和设置器的写法,设置器是通过ini文件。

self._devicesList 实例化区域内,通过Config.getValue获取属性的写法
self._configPath=self._rootPath+"\config.ini"
self._devicesList = Config.getValue(self._configPath, "deviceslist", )
#这2行代码说明了读取ini的文件位置,这块代码不做解读了继续往下。

2.如果没有获得内容实时链接获得一次

if devicesList[0] == "": #代表 上面第一个元祖里面的第一个位置是“”,需要再次获取。
作用使用的是 os.popen()的方式,优点执行失败不会返回错误码,一旦要对错误信息进行过滤处理,就会增加麻烦。

3. line31 对Config.ini的防御代码

如果有填写device对象拿到,获取到继续往下 。
如果没有填写走到下面一行缓存内,声明是必须必填项目,给予一个状态机devicesList=None

这里等于None会在第line47行进行分叉,goto到line 86行,未找到设备,建议是主动断开.

画外音:有互联网朋友说游戏产业真的对状态机(中间变量)特别有偏好,如果做过这块逻辑就知道了,一个大型脚本几百个的,有100-200个中间变量不算多了,业务很复杂。

4. 读取状态功能 是否跳过性能测试

同上,通过访问器。
在反序通过相等==“1”三目表达式拿到布尔对象赋予skip_performance对象
画外音:python有一个property,但不适合这个地方,三目表达式是好东西,虽然python不是编译型语言。

5. 是否需要存储性能数据

这个和上面一样的,前提是先开通上面的。

6. 初始化功能型文件夹

Os.getcwd拿到运行时路径,拼接到根目录Report文件夹。
没有加在git里,因为这3个目录是放用户数据。用户如果在库外调用,那会生成在执行代码所在的目录。

7.devicesList上面不为空,继续往下执行

用列表装载进程池,用 for …range的模式把每个对象取出来后放到MultiAdb的实例化里面去
看看实例化的代码作用 关键字mdevice初始为“”,这个时候实例化后就放置了device对象。
画外音:py在内存里面,主要是列表和字典这2个,字典因为没有偏移的关系并且在3.5还是3.3以上支持会更好。

8. madb.get_androidversion() 设置最低版本支持

不满足的手机通过continue轮空
通过adb反馈的结果拿到当前的安卓版本,这块反馈的是str,int(version)在函数内显式转换比在调用时调转更好

9.多进程执行target=关键函数

上面8的另外一个分支或者不被轮空的手机在多进程区域开辟2段int类型内存flag和fpsflag(方法区往上的共享区域),定义字面值为0

#取之前的状态机skip_performance,上面有写,通过Config.ini里面预设好的,在载入到类的实例变量内,然后通过get方法访问器反馈出来。  
#P1变量通过Process创建记录性能的进程(进程属性引用的函数名称,args元祖区域传入形参列标参数)
#List.append()把常见的进程添加到生命周期依然存活的列表.
#P2变量通过Process创建执行进程,其他类似,创建后添加到进程池内,进程池内长度在1-2.

通过for in的模式 让start()就绪区域后执行,然后join防止主进程结果后,进入阻塞,等待子进程完成。

10.打印日志,让批量执行的手机屏幕关闭
screenoff=Madb().get_screenoff() 是拿到ini里面的变量
#这里注意setScreenOFF是引用到了其他文件from DreamMultiDevices.tools.ScreenOFF import * 藏到了*里面
DreamMultiDevices/blob/master/tools/ScreenOFF.py

setScreenOFF()内部先判断执行平台,然后赋值2个变量,这2个变量用来放不同情况下的可提供os.popen(cmd字符串)

os.popen反馈的结果中做字符串内容拆分 如果取出字符串位置等于false包含在result内不处理,如果不是,os.popen(触发26)相关代码.

Keyevent可以网上自行查映射关系。下面就是用一个while循环去触发上面的行为直到"mScreenOnEarly=false"

在函数内部往所有机器都关闭,最后在外层函数打印设备xxx已经关闭。

画外音: 以上服务都是adb原生提供的,这个一般使用adb的模式,判断是不是闭屏,如果不是keyevent锁屏,但这里主要是通过变量设置。

11.中间发生错误的拦截

通过导入类库区域导入的2个类库

结果发送邮件(目前暂时屏蔽了)

暂时写到了
DreamMultiDevices/blob/master/core/index.py  94
下篇会跳到enter_processing()逻辑方法内。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 2 条回复 时间 点赞

试试看看

已在大佬群里,群里氛围特别好,解决了自己很多问题,支持。

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