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")
简便方法:本地录制与修改
您无需从零开始编写远程自动化脚本。一个更简单高效的方法是:
- 在本地对 Qt 应用进行录制,生成基础脚本和对象模型。
- 在生成的脚本中,添加连接到远程 Worker 的代码。
- 将启动路径 (
QtAuto.launchQtProcessAsync()中的参数) 修改为远程机器上的相应路径。 - 将连接地址 (
wsEndpoint或sync_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()