Qt的远程自动化

CukeTest 支持对 Qt 应用程序进行远程自动化。这意味着您可以在一台电脑上运行 CukeTest,同时控制另一台电脑上的 Qt 应用。这种跨机器的自动化解决方案非常灵活,例如,您可以在 Windows 系统上运行 CukeTest 脚本,而实际的 Qt 应用则在 Linux 环境中执行。

远程自动化工作原理

远程自动化的核心是 Worker 服务。您需要在安装了 Qt 应用的远程电脑上启动这个服务。然后,您的本地 CukeTest 脚本会通过网络连接到该服务,并发送自动化指令。Worker 服务接收到指令后,会执行相应的 Qt 自动化操作,并将结果反馈给本地脚本。

要启动 Worker 服务,只需在远程电脑的命令行中执行以下命令:

cuketest worker

有关远程自动化的更多详细信息,请参考 远程自动化 文档。

示例代码

以下是一个完整的 Qt 远程自动化脚本示例。

JavaScript
Python
const { CukeTest } = require('cuketest');
const { setDefaultTimeout, Given, When, Then } = require('cucumber');

let QtAuto, modelQt;
setDefaultTimeout(20 * 1000);

BeforeAll(async function () {
    // 1. 连接到远程 Worker 服务
    let auto = await CukeTest.connect({
        wsEndpoint: 'ws://192.168.1.5:3131/ws'
    });
    // 2. 从远程实例中获取自动化对象
    QtAuto = auto.qtAuto;
    const { runSettings: RunSettings } = auto;
    
    // 3. 设置慢速执行模式,便于观察
    await RunSettings.set({ slowMo: 500 });
    
    // 4. 加载本地的模型文件
    modelQt = await auto.qtAuto.loadModel('./basiclayouts.tmodel');

    let capabilities = await auto.capabilities();
    let homeDir = capabilities.homePath; // "C:\Program Files\LeanPro\CukeTest"
    let qtAppPath = [  // 针对不同操作系统传入多个路径,Worker 会自动选择可用的路径
        `${homeDir}/bin/basiclayouts`, // Linux
        `${homeDir}\\bin\\basiclayouts.exe`, // Windows
        '/Applications/CukeTest.app/Contents/Frameworks/basiclayouts', // Mac
    ]
    
    // 5. 启动 Qt 应用
    await QtAuto.launchQtProcessAsync(qtAppPath);

    // 6. 等待应用主窗口出现
    await modelQt.getApplication("basiclayouts").exists(10);
})

AfterAll(async function () {
    // 7. 测试结束后,退出应用并关闭远程连接
    await modelQt.getButton("OK").click();
    await modelQt.getApplication("basiclayouts").quit();
});

Given("自动化basiclayouts", async function () {
    // 8. 自动化操作示例
    await modelQt.getButton("Button_1").click();
    await modelQt.getEdit("Edit").click();
    await modelQt.getEdit("Edit").set("something");
    await modelQt.getEdit("Edit1").click();
    await modelQt.getEdit("Edit1").set("something else");
    await modelQt.getSpinBox("SpinBox").increment();
    await modelQt.getSpinBox("SpinBox").increment();
    let snapshot = await modelQt.getSpinBox("SpinBox").takeScreenshot();
    this.attach(snapshot, "image/png");
});
from auto.sync_api import sync_auto
from pytest_bdd import scenarios, given, when, then, parsers
from pytest_html import extras
import pytest
import os

scenarios("../features")

@pytest.fixture(scope="session")
def remote_worker():
    # 1. 使用 sync_auto 连接到远端 Worker 服务
    with sync_auto("ws://192.168.1.5:3131/ws") as auto:
        RunSettings = auto.runSettings
        QtAuto = auto.qtAuto
        
        # 2. 设置慢速执行模式和报告步骤
        RunSettings.set({"slowMo":500, "reportSteps": True})
        
        # 3. 加载本地模型文件
        modelQt = QtAuto.loadModel('models/model.tmodel')
        capabilities = auto.capabilities()
        install_path = capabilities['homePath'] # "C:\Program Files\LeanPro\CukeTest"
        
        # 4. 启动 Qt 应用
        QtAuto.launchQtProcessAsync([  # 针对不同操作系统传入多个路径,Worker 会自动选择可用的路径
            f"{install_path}/bin/basiclayouts", # Linux
            f"{install_path}\\bin\\basiclayouts.exe", # Windows
            f"/Applications/CukeTest.app/Contents/Frameworks/basiclayouts" # Mac
        ])
        
        # 5. 等待应用主窗口出现
        modelQt.getApplication("basiclayouts").exists(10)
        
        # 6. 在测试运行之前建立远程链接并启动应用
        yield auto
        
        # 7. 在测试函数运行之后执行清理工作
        modelQt.getButton("OK").click()
        modelQt.getApplication("basiclayouts").quit()


@pytest.fixture(scope="session")
def modelQt(remote_worker):
    model = remote_worker.qtAuto.loadModel('models/model.tmodel')
    return model


@given("自动化basiclayouts")
def automated_basiclayouts(modelQt, request):
    # 8. 自动化操作示例
    modelQt.getButton("Button_1").click()
    modelQt.getEdit("Edit").click()
    edit = modelQt.getEdit("Edit")
    modelQt.getEdit("Edit").set("something")
    modelQt.getEdit("Edit1").click()
    modelQt.getEdit("Edit1").set("something else")
    modelQt.getSpinBox("SpinBox").increment()
    modelQt.getSpinBox("SpinBox").increment()
    snapshot = modelQt.getSpinBox("SpinBox").takeScreenshot()
    request.attach(snapshot, "image/png")

简便方法:本地录制与修改

您无需从零开始编写远程自动化脚本。一个更简单高效的方法是:

  1. 在本地对 Qt 应用进行录制,生成基础脚本和对象模型。
  2. 在生成的脚本中,添加连接到远程 Worker 的代码。
  3. 将启动路径 (QtAuto.launchQtProcessAsync() 中的参数) 修改为远程机器上的相应路径。
  4. 将连接地址 (wsEndpointsync_auto 参数) 设置为远程 Worker 的网络地址。

本地录制代码示例

JavaScript
Python
const { RunSettings } = require("leanpro.common");
const { QtAuto } = require("leanpro.qt");
(async () => {
    await RunSettings.set({slowMo: 1000, reportSteps: true});
    let modelQt = QtAuto.loadModel(__dirname + "/recording_2.tmodel");
    await QtAuto.launchQtProcessAsync("C:\\Program Files\\LeanPro\\CukeTest\\bin\\basiclayouts.exe");
    await modelQt.getApplication("basiclayouts").exists(10);
    await modelQt.getButton("Button_1").click();
    await modelQt.getWindow("Basic_Layouts").close();
    await modelQt.getApplication("basiclayouts").quit();
})();
import os
from leanproAuto import RunSettings, QtAuto

def recording():
    RunSettings.set({"slowMo": 1000, "reportSteps": True})
    modelQt = QtAuto.loadModel(os.path.dirname(os.path.realpath(__file__)) + "/recording.tmodel")
    QtAuto.launchQtProcessAsync("C:\\Program Files\\LeanPro\\CukeTest\\bin\\basiclayouts.exe")
    modelQt.getApplication("basiclayouts").exists(10)
    modelQt.getButton("Button_1").click()
    modelQt.getWindow("Basic_Layouts").close()
    modelQt.getApplication("basiclayouts").quit()


if __name__ == "__main__":
    recording()

修改后的远程执行代码示例

JavaScript
Python
const { CukeTest } = require("cuketest");
(async () => {
    // 建立远程连接,并获取远程自动化对象
    let auto = await CukeTest.connect({
        wsEndpoint: 'ws://192.168.3.58:3131/ws'
    });
    const { runSettings: RunSettings } = auto;
    const { qtAuto: QtAuto } = auto;

    // 以下为原先的本地代码,无需修改
    await RunSettings.set({slowMo: 1000, reportSteps: true});
    let modelQt = await QtAuto.loadModel(__dirname + "/recording_1.tmodel");
    await QtAuto.launchQtProcessAsync("C:\\Program Files\\LeanPro\\CukeTest\\bin\\basiclayouts.exe");
    await modelQt.getApplication("basiclayouts").exists(10);
    await modelQt.getButton("Button_1").click();
    await modelQt.getWindow("Basic_Layouts").close();
    await modelQt.getApplication("basiclayouts").quit();
    auto.close();
})();
import os
from auto.sync_api import sync_auto

def recording():
    # 建立远程连接,并获取远程自动化对象
    with sync_auto("ws://192.168.3.58:3131/ws") as auto: 
        RunSettings = auto.runSettings
        QtAuto = auto.qtAuto

        # 以下为原先的本地代码,无需修改
        RunSettings.set({"slowMo": 1000, "reportSteps": True})
        modelQt = QtAuto.loadModel(os.path.dirname(os.path.realpath(__file__)) + "/recording.tmodel")
        QtAuto.launchQtProcessAsync("C:\\Program Files\\LeanPro\\CukeTest\\bin\\basiclayouts.exe")
        modelQt.getApplication("basiclayouts").exists(10)
        modelQt.getButton("Button_1").click()
        modelQt.getWindow("Basic_Layouts").close()
        modelQt.getApplication("basiclayouts").quit()


if __name__ == "__main__":
    recording()

results matching ""

    No results matching ""