Qt的远程自动化

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

远程自动化工作原理

远程自动化的核心是 CukeTest 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 ""