https://github.com/smart-test-ti/SoloX
基于 python 的移动设备性能测试工具,支持 android,通过 itunes(tidevice 的技术)支持了 ios 设备。
# 功能介绍
使用 python -m solox 启动服务,会自动打开 web 客户端:默认端口为 50003。
# 性能测试
-
设备类型支持安卓和苹果
-
支持选择设备列表
-
支持选择目标 app
-
支持选择子进程 (仅安卓)
-
支持性能指标的开关 (只控制显示,不控制是否采集)
- CPU
- 内存
- 流量
- FPS
- 电池
- surfaceview (仅安卓)
- wifi (仅安卓)
- GPU (仅苹果)
-
支持显示设备信息
- 品牌
- 设备名
- 系统版本
- 序列号
- wifi 地址
-
支持启动数据采集、停止设备采集(此时生成报告)
-
支持显示 logcat 日志 重要 (仅安卓)
-
支持安装应用
-
支持查看当前应用启动时间 (安卓支持较好)
-
支持对比模式 (仅安卓)
多台设备同时连接,同时测试
支持- CPU
- Memory
- NetWorkData
- FPS
# 报告管理
- 报告展示
- 报告管理
- 编辑 (场景名)
- 导出为 excel
- 删除
- 报告详情
- 结果对比
- 保存 html
- 保存图片
- 单个图片导出
# 功能剖析
# web 功能
# flask 服务
web 功能基于 flask flask-template flask-soketio 实现。
app = Flask(__name__, template_folder='templates', static_folder='static') | |
socketio = SocketIO(app, cors_allowed_origins="*") | |
def startServer(host: str, port: int): | |
socketio.run(app, host=host, debug=False, port=port) |
# 自动打开页面
服务启动时会自动打开浏览器,打开 solox 前端客户端
def openUrl(host: str, port: int): | |
flag = True | |
while flag: | |
logger.info('Start solox server ...') | |
f = Figlet(font="slant", width=300) | |
print(f.renderText("SOLOX 2. 6. 7")) | |
flag = getServerStatus(host, port) | |
webbrowser.open('http://{}:{}/?platform=Android&lan=en'.format(host, port), new=2) | |
logger.info('Running on http://{}:{}/?platform=Android&lan=en (Press CTRL+C to quit)'.format(host, port)) |
其中,使用了
- Figlet 打印艺术字
- webbrowser 是 python 内置的一个库,可以打开 url
# 端口检查
服务启动时,还调用了检查端口的函数
- 对于非 windows 系统,直接干掉进程
os.system("lsof -i:%s| grep LISTEN| awk '{print $2}'|xargs kill -9" % port)
- 对于 windows 系统
- 使用
netstat
命令结合findstr
过滤器,在指定端口上查找监听的进程。 - 读取命令输出的数据,并逐行处理。
- 提取每行中的进程 PID,并将其添加到
pid_list
列表中。 - 将
pid_list
转换为集合,再转换回列表,以去除重复的 PID。 - 选取列表中的第一个 PID,并使用
taskkill
命令强制终止该进程。
- 使用
# 启动
- 检查 python 版本:必选 3.10 以上
- 然后使用 Fire 启动
fire 库可以自己的库封装成一个命令 通过 python -m 命令调用
其他所有的功能都是由 http 请求触发,logcat 是一个 websocket
前端使用 jquery 处理事件和操作 dom;
# 设备监听与信息抓取
- 前端每次打开页面(
$(document).ready
)后,会自动触发连接按钮的点击事件,从而调用initializeEnv
方法; initializeEnv
请求接口 /device/ids?platform = 当前选择设备类型- 后端接口:
# 安卓
- 获取到当前的设备 id 列表 (解析命令行
adb devices
的输出)- 获取第一个设备的 pkg 列表 (adb -s deviceID shell pm list package)
- 获取设备信息 (安卓基于
adb
,ios 基于tidevice
)
def getDdeviceDetail(self, deviceId, platform): | |
result = {} | |
match(platform): | |
case Platform.Android: | |
result['brand'] = adb.shell(cmd='getprop ro.product.brand', deviceId=deviceId) | |
result['name'] = adb.shell(cmd='getprop ro.product.model', deviceId=deviceId) | |
result['version'] = adb.shell(cmd='getprop ro.build.version.release', deviceId=deviceId) | |
result['serialno'] = adb.shell(cmd='getprop ro.serialno', deviceId=deviceId) | |
cmd = f'ip addr show wlan0 | {self.filterType()} link/ether' result['wifiadr'] = adb.shell(cmd=cmd, deviceId=deviceId).split(' ')[1] | |
case Platform.iOS: | |
iosInfo = json.loads(self.execCmd('tidevice info --json')) | |
result['brand'] = iosInfo['DeviceClass'] | |
result['name'] = iosInfo['DeviceName'] | |
result['version'] = iosInfo['ProductVersion'] | |
result['serialno'] = iosInfo['SerialNumber'] | |
result['wifiadr'] = iosInfo['WiFiAddress'] | |
case _: | |
raise Exception('{} is undefined'.format(platform)) | |
return result |
# ios
- 获取设备信息 (解析命令行 tidevice list --json)
- 获取第一个设备 pkg 列表:
tidevice --udid 设备uid applist
- 获取设备详情,同上
# 性能采集
点击开始按钮,触发启动测试。
- 必须先选中设备和应用
- 分别调用 collectCpu、collectMem、collectNetwork、collectFps、collectBattery 如果是 ios 系统,还要采集 GPU collectGpu
- 这些方法再调用 collectPers 方法(参数包括一个获取采集数据的方法),然后使用 highcharts 绘制图表;其中采集数据的方法作为 highcharts 实例的数据 load 方法,并且图表支持切换时间范围; 这个请求函数成功后会设置一个 settimeout 定时器,一秒钟后再次请求这个接口更新数据,并将数据塞入到图表数据的最新;
性能采集需要比较复杂,打算分成系列的博客慢慢写一下。