智能界面压力测试

“智能界面压力测试”功能(又称智能 Monkey 测试)是一款专为 Qt 应用设计的自动化压力测试工具。它能够智能地识别界面控件,并模拟真实用户的随机操作(点击、输入、拖拽等),从而帮助开发者发现应用在长时间运行或极高频操作下的稳定性问题、内存泄漏或崩溃异常。

Note

本功能目前主要针对 Qt 应用。它通过遍历控件树实现智能探索,比传统的屏幕像素级随机点击具有更高的有效操作率。

为什么使用它?

传统的自动化测试侧重于验证功能逻辑的正确性,而 Monkey 测试侧重于:

  • 稳定性测试:通过成千上万次的随机操作,触发难以预见的边界情况或竞态条件。
  • 鲁棒性测试:验证应用在非预期操作序列下的行为。
  • 资源泄漏检测:长时间运行以观察内存、CPU 等资源的使用趋势。

快速上手步骤

1. 打开功能面板

在 CukeTest 的 AI 助手 侧边栏中,点击或搜索进入 “智能界面压力测试” 功能。

2. 配置测试参数

在界面左侧填写相关参数:

  • 被测 Qt 应用: 选择已知的应用,或点击“...”按钮指定可执行文件路径 (.exe)。
  • 操作次数上限: 测试过程中允许进行的随机操作总数。
  • 执行时间 (分钟): 测试的最长持续时间。
  • 排除控件: 输入不希望被点击的控件的 text 属性(如“注销”、“退出”),多个控件用半角分号 ; 分隔。

Tip

如果未设置操作次数和执行时间上限,系统将默认在完整遍历界面所有可识别控件一次后停止。

3. 生成并运行代码

确认参数后,点击 “生成执行代码” 按钮。界面右侧将自动创建脚本文件(例如 monkey_script_1.js)。

脚本解析

生成的脚本基于 leanpro.monkey 库。以下是核心代码结构:

JavaScript
const { Keyboard } = require('leanpro.common');
const { QtAuto } = require("leanpro.qt");
const { SmartMonkey } = require("leanpro.monkey");

async function smartTest() {
    Keyboard.disableIme(); // 禁用输入法防止干扰

    const monkey = new SmartMonkey({
        launchApp: () => { return QtAuto.launchQtProcessAsync("C:/path/to/your/app.exe"); },
        appName: "YourAppName",
        maxActions: 30,            // 操作次数
        maxDuration: 1 * 60,       // 最长持续时间,单位为秒
        excludes: ["注销","退出"],  // 被排除控件 text 属性列表
        code: true,                // 生成运行代码
        verbose: true,             // 输出详细日志
        overwrite: true            // 覆盖旧数据
    });

    // 可以在此处自定义控件筛选逻辑
    monkey.onControl(async (control, interested) => {
        if (!interested) return;
        // console.log('正在探索控件:', await control.modelProperties());
    });

    // 定义压力测试的起始视图/容器
    let view = QtAuto.getGeneric([...]); 
    
    // 启动测试
    await monkey.start(view);

    // 生成报告
    await monkey.generateReport();
}

smartTest();

运行与报告

运行测试

您可以在 CukeTest 界面直接运行生成的脚本。运行过程中,被测应用会自动启动,并开始在界面上进行快速的模拟操作。

Note

如果需要中途停止,可以直接关闭测试终端或点击 CukeTest 的“停止运行”按钮。

查看报告

测试完成后,项目目录下会生成以 monkey_YYYY-MM-DD 命名的文件夹。

  • JSON 报告: 包含所有操作的结构化原始数据。
  • HTML 报告: 提供可视化的测试概览,操作序列以及由于操作导致的错误统计。

高级配置 (SmartMonkey 选项)

通过手动修改脚本中的 SmartMonkey 构造参数,可以更精细地控制测试:

参数 类型 说明
slowMo number 动作之间的延迟时间(毫秒),默认为 0。增加此值可放慢测试速度。
maxActions number 最大操作步数。
maxDuration number 最大执行时间(秒)。
excludes string[] 排除的控件 text 属性列表。
onEvent Function 监听测试事件(如 start, end, startIteration 等)。

注意事项

Warning

数据安全:由于 Monkey 测试是随机的,存在点击“删除”、“格式化”等毁灭性操作的可能。请务必在独立的测试环境(如测试虚拟机)中运行,切勿在包含重要生产数据的系统上测试。

SmartMonkey类型说明

JavaScript
export interface SmartMonkeyOptions {
    launchApp?: () => Promise<void>; // 启动应用的回调函数
    appName: string;    // 应用名称
    verbose?: boolean;  // 详细日志输出
    slowMo?: number;    // 动作执行减速(毫秒)
    maxActions?: number;    // 最大动作数量
    maxDuration?: number;    // 最大执行时长(毫秒)
    code?: boolean;    // 是否生成代码
    overwrite?: boolean;    // 是否覆盖已有文件
    excludes?: any[];    // 排除的元素列表
}

// 进程状态枚举
export enum ProcessState {
    skip = 'skip',  // 跳过
    close = 'close',// 关闭
    stop = 'stop',  // 停止
    act = 'act'     // 执行动作
}

// 动作执行结果接口
export interface IActionResult {
    name: string    // 动作名称
    params: any[],  // 动作参数列表
    error?: string  // 动作错误信息
}

// SmartMonkey 事件枚举
export enum MonkeyEvent {
    start = 'start',    // 开始事件
    end = 'end',        // 结束事件
    startIteration = 'startIteration',  // 开始迭代
    endIteration = 'endIteration',      // 结束迭代
    startDialog = 'startDialog',        // 开始对话框
    endDialog = 'endDialog',            // 结束对话框
    launchApp = 'launchApp',            // 启动应用
}

// SmartMonkey 主类
export class SmartMonkey {
    constructor(options: SmartMonkeyOptions);
    // 开始执行自动化测试
    start(startControl?: any): Promise<void>;
    // 获取感兴趣的控件类型
    get interestedControls(): QtControlType;
    // 为每个控件触发回调,ProcessState 可以控制如何处理该控件
    onControl: (listener: (control: IQtControl, interested: boolean) => Promise<void | ProcessState>) => () => void;
    // 事件回调,可以是 start, end, startDialog, endDialog 等事件
    onEvent: (listener: (eventName: MonkeyEvent, ...params: any[]) => Promise<void>) => () => void;
    // 在执行每个动作后触发回调
    onAction: (listener: (control: IQtControl, action: IActionResult) => void) => () => void;
    // 生成测试报告
    generateReport(): Promise<void>;
}

results matching ""

    No results matching ""