描述模式
描述模式是一种通过直接在代码中使用属性构造测试对象的方式。这种方式与传统的使用对象模型加载测试对象的方法不同。在描述模式中,可以通过WinAuto
或QtAuto
等对象调用get[ControlType]
方法(如WinAuto.getWindow()
、WinAuto.getButton()
等)。这些get[ControlType]
方法需要一个包含一组属性的对象作为参数,这些属性以逻辑“AND”的形式组合,定义了用于查找界面上控件的查询条件。
描述模式的优点在于无需依赖于对象模型,可以动态构建测试对象,或访问界面上动态创建的控件。其缺点是不能集中管理测试对象,也不能使用对象管理器的编辑界面修改或验证测试对象,维护成本较高。因此,您可以根据具体场景选择是否使用描述模式。
从属性构造测试对象
下面的示例展示了如何通过描述模式直接从属性构造测试对象,而无需加载对象模型:
const { WinAuto } = require('leanpro.win');
await WinAuto.getWindow({ "className": "ApplicationFrameWindow", "title": "计算器" })
.getWindow({ "className": "Windows.UI.Core.CoreWindow", "title": "计算器" })
.getGeneric({ "type": "Group", "automationId": "NumberPad", "name": "数字键盘" })
.getButton({ "automationId": "num5Button" }).click();
from leanproAuto import WinAuto
WinAuto.getWindow({"className": "ApplicationFrameWindow","title": "计算器"}).getWindow({"className": "Windows.UI.Core.CoreWindow","title": "计算器"}).getGeneric({"type": "Group","automationId": "NumberPad","name": "数字键盘"}).getButton({"automationId": "num5Button"}).click()
在上述示例中,每个方法调用都传递了一个对象参数,其中包含多个键值对。这些键值对组合起来形成了用于查找测试对象的过滤条件。
省略中间层次结构
如果您要操作的对象具有唯一标识,可以省略中间的层次结构,直接使用顶层窗口对象和目标操作对象级联,如下所示:
const { WinAuto } = require('leanpro.win');
await WinAuto.getWindow({ "className": "ApplicationFrameWindow", "title": "计算器" })
.getButton({ "automationId": "num5Button" }).click();
from leanproAuto import WinAuto
WinAuto.getWindow({ "className": "ApplicationFrameWindow", "title": "计算器" }).getButton({ "automationId": "num5Button" }).click()
在这个示例中,由于按钮“5”具有唯一的识别属性automationId
,因此无需通过中间对象也能直接定位到该按钮,从而简化了代码。
批量传递属性
您还可以选择以数组形式一次性传递属性,从而避免多次调用:
在模型管理器的对象属性界面,点击
复制级联节点属性
即可自动复制数组形式的属性到剪贴板。
const { WinAuto } = require('leanpro.win');
await WinAuto.getGeneric([
{ "className": "ApplicationFrameWindow", "title": "计算器" },
{ "className": "Windows.UI.Core.CoreWindow", "title": "计算器" },
{ "type": "Group", "automationId": "NumberPad", "name": "数字键盘" },
{ "automationId": "num5Button" }
]).click();
from leanproAuto import WinAuto
WinAuto.getGeneric([
{ "className": "ApplicationFrameWindow", "title": "计算器" },
{ "className": "Windows.UI.Core.CoreWindow", "title": "计算器" },
{ "type": "Group", "automationId": "NumberPad", "name": "数字键盘" },
{ "automationId": "num5Button" }
]).click()
利用模型中保存的对象属性
在默认情况下,第一个参数表示对象名,第二个参数表示识别属性。识别属性的可选值参考 Criteria 类。
覆盖已有标识属性
以下示例展示了如何覆盖识别属性:
await model.getButton("五", { automationId: "num6Button" }).click();
model.getButton("五", { "automationId": "num6Button" }).click()
在这个示例中,脚本首先获取模型中名为 五
的按钮的识别属性,然后将 automationId
替换为新的值 num6Button
。因此,这行代码点击的按钮是计算器上的“6”而不是“5”,因为 automationId
被覆盖了。
动态添加属性
以下示例展示了如何为已知控件添加额外的识别属性:
await model.getButton("Button", { index: 2 }).click();
model.getButton("Button", { "index": 2 }).click()
此代码会点击匹配到的第3个 Button
控件(假设至少有3个按钮控件符合条件)。这种方法类似于对象继承,通过添加新的属性来扩展已有对象的定义。
动态构建叶子节点
你还可以将模型对象与描述模式结合使用,以简化代码结构。这种方法适用于在测试过程中动态生成的子控件,如 treeItem
、tableItem
等。
await modelWin.getList("ListBox").getListItem({
"type": "ListItem",
"className": "ListBoxItem",
"name": "First Normal Item"
}).click();
modelWin.getList("ListBox").getListItem({
"type": "ListItem",
"className": "ListBoxItem",
"name": "First Normal Item"
}).click()
这段代码首先获取 ListBox
控件,然后通过描述模式获取 ListItem
控件,最后点击名为 First Normal Item
的项。
代码生成
描述模式的代码可以手动编写,但使用模型管理器生成代码更为便捷。
生成操作代码
- 选择控件:在模型管理器中,选择要操作的控件。
- 切换标签页:切换到对应的“控件操作”标签页。
- 开启描述模式:点击描述模式开关 (按钮按下表示开启)。
此时,复制的控件操作代码即为描述模式代码。
生成对象查找代码
节点属性
在模型管理器的“对象属性”标签页,点击 复制节点属性
按钮,会将控件节点的信息复制,并以对象形式呈现。复制得到的属性可以直接作为 get[ControlType]
方法的参数。
例如,复制后会得到如下内容:
{"type": "Button", "automationId": "plusButton", "name": "加"}
级联节点属性
在对象属性界面,点击 复制级联节点属性
按钮,将控件节点及其所有父节点的信息一并复制,并以数组形式呈现。复制得到的属性可直接作为 getGeneric()
方法的参数在批量传递属性时使用。
例如,复制后会得到如下内容:
[
{"type": "Window", "className": "ApplicationFrameWindow", "appName": "ApplicationFrameHost"},
{"type": "Group", "automationId": "StandardOperators", "name": "标准运算符"},
{"type": "Button", "automationId": "plusButton", "name": "加"}
]
在侦测控件时生成描述代码
点击“添加对象”并检测到控件后,在弹出的“添加对象”对话框中点击“复制代码”,即可将描述模式代码复制到剪贴板(默认会生成 click()
方法的描述模式代码)。