术语 | 解释 |
---|---|
InputDevice | 支持 linux 管理不同类型、不同原理、不同的输入信息的输入设备软件体系 |
MEM | MEM 是一个内存显示程序,显示所有内存驻留程序的占用情况 |
输入子系统 | 输入子系统核心层(Input Core)、驱动层和事件处理层(Event Handler) |
随着文件管理器(以下简称"文管")的使用者越来越多,厂商和社区反馈了越来越多反复操作后出现概率概率性 BUG,为了对 BUG 进行复现,就需要进行压力测试。
在我们日常压力测试过程中,文管测试组需要使用现有的设备进行问题复验和场景压测,设备和人力资源有限,因此,在复现和验证这些问题的过程中,存在着如下问题:
耗时巨大,追其原因,是因为在测试过程中,测试复现时反复操作的顺序不同、频率不够、操作慢都可能导致Bug无法复现,整个复现周期相对较长,人力和时间耗费较多。
无可靠性,在遇到概率性 BUG 进行回归的时候,我们无法确定需要测试多少次才能确保问题已修复,而且有可能人力压力测试无法达到复现条件,没有数据支撑测试结论。
因此,探索一种良好的压力测试方案,是迫在眉睫的,可以更准确的验证及回归问题,并且减少人力资源和提升测试效率。
基于上述问题,当前市面上对于应用压测存在如下几个方案:
方案一:使用 Python 脚本进行场景压测
使用 Python 编写压测脚本,需要使用第三方库 PyAutoGUI 和 Dogtail,PyAutoGUI 是一个纯Python 的 GUI 自动化工具,可以用程序自动控制鼠标和键盘操作模拟用户操作行为,多平台支持(Windows,OS X,Linux)
在编写脚本之前,我们首先需要准备环境,即安装 PyAutoGUI 和 Dogtail 库。
开始编写一个简单压测场景脚本:循环一直新建文件夹。
一个场景压测,往往不会这么简单,列举部分文管场景压力测试项如下:
压测场景 | 压测步骤 | 压测次数/时长 |
---|---|---|
循环执行创建,删除文件 | 1.在桌面/文管空白处,右键菜单2.点击“新建文件夹“3.选择新建文件夹右键”删除“ | 8H |
重复打开 1000 张图片的文件夹 | 1.在桌面选择包含 1000 张图片的文件夹2.关闭文管 | 8H |
重复搜索目录中的文件 | 1.打开文件管理器,进入test目录中2.点击搜索按钮3.在输入框输入 "test",进行搜索4.关闭文管 | 8H |
重复同时执行 10 个复制文件任务 | 1.在 dock 栏目右键打开 2 个文管窗口2.在 A 窗口中,选择文件右键-复制3.在 B 窗口中,右键粘贴4.快速粘贴 10 次5.删除B窗口的文件 | 8H |
重复向桌面复制文件 | 1.在dock栏目打开文管2.选择一个“音乐”目录 CTRL+C 复制文件3.在桌面粘贴文件4.关闭提示弹窗5.关闭文管 | 8H |
可以很直观的看出,这些测试项的操作都较复杂。
Dogtail 是 Python 的三方库,它使用 Accessbility 技术与桌面应用程序通信。代码通过提前设置好的 Accessbility 标签进行操作,但 Accessbility 标签需要开发人员提前在应用程序中添加,在下图一中看到,1021 的文管中就不存在标签,部分版本基线中该方法并不适用。
通过 Dogtail 和 PyAutogui 来控制键盘、鼠标来进行应用的操作,在 Python 代码遍历寻找应用程序上可用的 Accessbility 节点时候,过程需要 1-2S 左右,之后再执行其他操作,这个过程耗时较长,失去了压力测试本身的意义。
纵观整个方案一,缺点是显而易见的,例如无法测试所有的应用版本、无法满足压力测试暴力操作的要求。
方案二:使用 shell 脚本进行场景压测
这个方案使用 Xdotool 工具模拟键盘、鼠标操作,Xwininfo 工具来获取窗体属性,此方法通过窗体固有属性,找到对应坐标,之后来进行键盘鼠标操作,整个流程如下图所示:
UOS 系统自带了Xdotool和Xwininfo工具,这个方法其实和方案二比较相似,方案二使用 Dogtail 定位元素位置、PyAutoGUI 来操作键盘、鼠标,使用wininfo 获取窗体属性计算坐标,通过 Xdotool 控制键鼠操作。
编写shell脚本,使用 Xodtool 工具进行简单操作,运行代码,查看图三,能看到与上述 Python 脚本同样的操作,shell脚本运行时间接近快了1s。
使用 shell 脚本编写:重复向桌面复制文件,并且每次输出桌面和文管的窗口 ID(寻找窗口 ID 来获取坐标) 测试场景,多次运行后,在下图四能看到,同一个场景同一套代码同一个机器,运行结果,极其不稳定,容易报错找不到窗口。
纵观整个方案二:运行环境简单、但是运行结果不稳定。
总结: 现目前这两种方案,各有优劣,都是现阶段较主流的方案,优缺点如表三所示:
方案 | 优点 | 缺点 |
---|---|---|
1 | 可自动化、场景覆盖多 | 无法适用所有版本,环境复杂、键鼠操作比较慢达不到压测效果 |
2 | 可自动化、运行环境简单,能适用所有版本 | 不稳定 |
在目前的测试环境下,方案一由于 Python 在使用第三方库的时候,程序响应往往都需要 1-2s 时间,运行速度较慢,而且无法满足所有版本的压测需求。方案二使用 shell 脚本编写压测脚本,在运行 Xdotool 工具时候容易出错,Xdotool 工具对键鼠的操作已经算是比较快的工具了,但是在特殊 BUG 上,鼠标操作速度还是有所欠缺,如:异步线程出错,在测试过程中,经常性会遇到这样的小概率问题、同样的操作,有时候能复现问题有时候又不能复现,BUG 复现条件极其苛刻,需要更快的操作增加 复现概率,如下表列举部分的 BUG,在回归 BUG 就需要快速的键鼠操作。
BUG编号 | 描述 | 严重程度 | 优先级 |
---|---|---|---|
29689 | 【文件管理器】【5.1.1.63-1】【sp2】桌面空白处右键,选择“壁纸与屏保”,再快速在右键,桌面黑屏 | 2 | 2 |
26972 | 【文件管理器】【5.1.1.39-1】在列表试图下,快速来回切换排列顺序,再点击上级栏目,文件管理器崩溃 | 2 | 2 |
26100 | 【文件管理器】【5.1.1.33-1】4K屏幕,2.75缩放,在桌面空白处快速多次点击右键,桌面崩溃 | 2 | 2 |
25591 | 【文件管理器】【5.1.1.31-1】鼠标左右键,快速连续一起按,桌面黑屏 | 3 | 3 |
24478 | 【sp1】【文件管理器】【5.1.0.8-1】拖动文件到其他目录下,快速敲击键盘“ctrl+z”出现不正确提示 | 4 | 4 |
21172 | 【文件管理器】【5.1.0.8-1】左侧栏目快速切换,右键闪退。 | 2 | 2 |
因此,我们需要对方案二进行优化,找到能解决键鼠操作速度不够快和容易出错不稳定的方案。
在用户使用桌面应用时候,都是通过键盘与鼠标输入设备与软件交互。
我们对现状中的方案二进行优化,也参考了 Xdotool 和 Xwininfo 工具的逻辑,设计一款新的应用程序,程序名称为 app-wininfo-m,计划解决上述键鼠操作速度不够快和容易出错不稳定的问题。
对于键鼠操作速度不够快的问题,了解到 Linux 输入子系统,可以通过设备驱动程序写入键鼠事件驱动设备文件来对 USB 键盘输入和鼠标移动进行操作。
一个输入事件,如鼠标移动或者键盘按键事件,到达用户空间传给应用程序,如下图四流程
事件处理层为不同类型硬件提供了用户访问及处理接口。在 /dev/input 目录下显示的是已经注册在内核中的设备编程接口,用户通过 open 这些设备文件来打开不同的输入设备进行硬件操作,当打开设备 /dev/input/mice 时,会调用到事件处理层的 Mouse Handler 来处理输入事件,这也使得设备驱动层无需关心设备文件的操作,因为 Mouse Handler 已经有了对应事件处理的方法。
对于容易出错不稳定的问题,是 Xdotool 这个工具在经过长时间运行后获取窗口 ID 值出错,目前我们能接触到的 UOS 系统图形化界面都是基于 X11 协议,Xlib 是 X11 协议的 API 实现,另外用于代替 Xlib 的新型 API 为 XCB。下图五 Xlib 告诉我们每个窗口和像素图都有自己的坐标系,通过坐标系的位置,可以鼠标定位操作应用。
app-wininfo-m 自上而下的模块结构呈现如下图七:
当按照这种模式设计,每个业务都比较统一有序和模块化,再扩展其他功能更加方便,不会影响到原有的功能。
app-action 的设计理念是一个 wrapper,从功能需求上来看,app-action 提供以下功能:
app-wininfo-m程序运行流程如下:
对应用使用者提供了友好的说明文档,程序已经帮助实现了需要的操作,使用者只需要根据说明文档传入对应的参数,执行需要的操作。以及添加简单崩溃的断言服务,通过对 coredump 日志监控,判断经过压力测试的应用是否出现崩溃现象,并输出结果提供给测试人员。
在坐标获取业务中,获取不同应用的坐标位置,在之前我们获取坐标的方式是通过 Xdotool 获取到Window_ID,再通过 Window_ID 使用工具 Xwininfo 获取坐标。需要进行多个步骤操作后才能获取到坐标,在代码编写上步骤复杂,而且获取的结果不够稳定,因此找到了一个获取坐标的新方法,基本操作流程如下:
根据应用的进程寻找应用的坐标位置:
传入的 PID,再调用 app-wininfo-m 程序,如果 PID 不存在,则不会返回窗口的坐标等属性,如果 PID 存在,就返回窗口的坐标等属性。
在编码过程中,获取窗口的坐标引入 Xlib 的头文件 #include <linux/xlib.h> 获取结构体:XGetWindowAttributes() 函数返回指定窗口到当前属性 XWindowAttributes 结构。
了解到 Xlib 函数,就可以围绕 XGetWindowAttributes() 函数来获取窗口属性,经过以下流程,就完成窗口的属性获取了。
传入进程判断,获取窗口,伪代码如下
对鼠标进行移动点击,程序要知道鼠标的位置,获取鼠标位置的代码如下:
窗口属性的获取,伪代码如下:
在 Linux 系统中,万物皆文件,我们的键盘和鼠标都是设备文件,经过调研,通过对设备文件写入,就可以对键盘和鼠标进行操作,这个操作是硬件操作的最快的方法,其基本流程如下:
在编码过程中,对设备文件写入生效,需要引入子系统头文件 #include <linux/input.h> 获取到结构体:
通过 write() 函数对 /dev/input 目录下设备文件写入,伪代码如下:
最终,通过公式移动到鼠标想要的位置,如移动到应用左上角的位置( X1,Y1 ),鼠标位置( X2,Y2 ),鼠标相对位置 rel_x,rel_y 相对移动位置。
对于键盘的操作,与上面操作类似,就需要修改参数,代码如下:
根据技术方案调研的结果,需要对整体设计的方案和一些技术细节进行验证,为此设计以下实验:
app-wininfo-m 的目的是对桌面应用坐标定位,通过输入设备的设备文件操作鼠标键盘,本次实验将按照整体设计中的方式,生成一个可以运行的程序执行文件,以通过进程获取到应用坐标,并且鼠标点击关闭窗口为例进行演示。
app-wininfo-m 应用程序参数文件说明:
参数 | 说明 |
---|---|
-m | 鼠标移动位置,参数一:坐标X轴,参数二:坐标Y轴,参数三:1点击鼠标左键,2鼠标中键,3鼠标右键 |
-p | 通过传入的进程号查找应用窗口的属性,查看所有进程下的窗口,并输出窗口属性 |
-k | 键盘输入,如:-k KEY_A ,键盘输入A |
【实验环境】
【实验步骤】
编写测试脚本
使用 shell 方式来运行 demo 程序,编写的代码如下
查看下图运行结果,看到 通过进程获取到应用坐标,并且鼠标点击关闭窗口 演示操作的例子完美运行成功,app-wininfo-m 程序的整体方案是正确的。
以上述例子运行,进行不同系统架构测试,测试结果如下:
系统架构 | 测试结果 |
---|---|
MIPS64EL | 正常运行 |
X86 | 正常运行 |
ARM64 | 正常运行 |
压力测试对稳定性要求很高,设计以下测试项,对 app-wininfo-m 程序的关键点进行稳定性验证。
测试项 | 测试说明 | 时长 | 结果 |
---|---|---|---|
获取10个应用窗口属性 | 打开多个10个应用,对10个窗口属性获取,demo程序稳定 | 24H | 通过 |
同一个应用打开10个窗口,获取所有窗口属性 | 选择文管,打开10个窗口,获取10个窗口属性,demo程序稳定 | 24H | 通过 |
鼠标移动 | 使用demo控制在桌面随意移动,demo程序稳定 | 24H | 通过 |
长时间获取鼠标位置 | 桌面随机一定,一直获取鼠标位置,demo程序稳定 | 24H | 通过 |
点击鼠标左键 | 使用demo程序,鼠标随机一直标右键,demo程序稳定 | 24H | 通过 |
点击鼠标右键 | 使用demo程序,鼠标随机一直标左键,demo程序稳定 | 24H | 通过 |
键盘输入 | 使用demo程序,控制键盘一直输入,demo程序稳定 | 24H | 通过 |
经过上面的测试项,demo 程序满足了稳定性
demo 程序在设计当初考虑了极限的压力操作场景,准备了一下实验,进行验证结果,代码如下:
使用 time 命令运行 shell 脚本,下图就是 demo 程序运行速度。
由上图九可知 demo 程序运行速达到 1.844s,对比方案二的 2.315s 速度,明显超过 Xdotool 工具的运行速度。
本文针对压力测试工具提出技术方案,整体设计中通过对设备文件写入操作和使用 xlib 库开发了定位和操作服务,解决了方案二获取坐标不稳定和操作速度不够快的问题,基本上能满足现有压测场景的使用要求,同时提供简单崩溃断言的服务。
app-wininfo-m 工具作为我们自己开发的工具,未来可以根据需求进行功能扩展,如在“进行搜索的压力测试”,目前只能验证搜索出现崩溃这样的问题,无法验证搜索结果是否正确,现有市面上仍然没有这样功能的工具,我们可以在 app-wininfo-m 工具中定制开发。
一个新开发工具,往往要经过无数次的版本迭代和优化,接下来的方向,就是对工具进行以下功能扩展和优化。
扩展功能 | 优化 |
---|---|
模拟拖拽操作 | 优化鼠标移动计算方式 |
元素定位 | 优化 app-wininfo-m 代码 |
图像定位 | 优化数据输出方式 |
增加断言方式(如:搜索) | 优化键盘输入传值方式 |
模拟触摸操作 |