Windows的识别属性

Windows平台上的控件识别依赖于一系列属性,这些属性帮助测试框架定位和操作界面元素。

一. 通用识别属性

通用识别属性是所有控件共有的,不依赖于特定控件类型的属性。

name

控件的内部名称,用于标识控件。

type

控件的类型,这是一个必需属性,影响控件提供的操作API。 例如:Button、Text、Window、List、Table、Tree等。

className

控件所属的类名称,源自控件在代码中的类定义。 例如,Qt中常用于窗口的控件是QWidget,因此窗口的type为Window,而className为QWidget,如图所示:
Window控件的className
由于className的值通常只与type和应用使用的框架(Qt、WPF、WinForm等等)相关,所以有时可用于识别应用的技术栈。

automationId

一般来自.NET框架,是目标控件中用于自动化测试的一个属性,在官方文档中的解释为:

An ID for an element that is unique among siblings within its container.
相对于同一个容器中的兄弟姐妹们来说控件唯一的标识。

因此适用于.NET框架(比如WPF、WinForm等)应用和控件的自动化,对于其它类型的应用中的控件而言一般都是空值。

accessKey

目标控件的快捷键,与automationId类似,都是用于自动化的一个属性,但通常为空值。

value

目标控件的值(通常是可变的值),并且与value属性方法返回的结果相同。作为其它属性,可以手动将其添加为识别属性。

通常情况下,像value这种可变的属性并不是理想的识别属性,因为当控件的值发生改变后就会出现识别不到的问题。但是由于部分应用在开发过程中,会将可编辑的控件设置为不可编辑,在这个时候value就能够充当识别属性了。

appName

appName属性存在于根节点窗口对象中,用来标识应用。它的值是可执行文件名不包含后缀的部分。例如Windows记事簿的可执行文件是"notepad.exe",那么识别记事簿应用的窗口对象时会获得appName="notepad"的属性值。

缺省情况下,appName在识别到以后不会作为标识属性,而是作为其他属性存在。如果发现应用程序的顶层窗口识别属性非常少,不足以唯一标识被测应用,可以手动把appName添加到标识属性中。

对于Electron应用,appName会有更重要的作用。因为Electron应用使用Chrome的实现,它的顶层窗口的识别属性类似于Chrome,另一方面,由于CukeTest也时使用Electron,在自动化时,使用appName属性,也有助于区分CukeTest和被测应用。因此在使用Windows侦测方式识别Electron应用界面时,会主动将appName作为标识属性。

二. 辅助识别属性

控件索引:index

index 属性用于指定目标控件在多个匹配控件中的位置,特别是在识别属性过少或不够唯一时,可以通过 index 来确定具体的控件。这里以模型管理器的 高亮 功能为例,说明一下识别到多个控件时的处理方式:

识别到多个控件时:当模型管理器/侦测器同时识别到多个控件(可能由于识别属性不够具体,或者应用中存在多个同名控件等情况),所有匹配到的控件会被以数组的形式返回。此时,index 属性可以帮助选择数组中的特定控件。例如,index = 0 时选择第一个控件,index = 1 时选择第二个,依此类推。同时,模型管理器会在左下方显示识别到的控件信息。

通常情况下,index 属性默认值为 0,即始终选择第一个匹配控件。因此,即便只有一个控件被识别到,index = 0 也能正常使用,但若使用其他索引值(如 12),则会返回 错误1003:不能找到这个对象

当模型管理器发现同一个对象节点匹配到多个控件时,会在左下角显示当前匹配的第一个控件的坐标和总的匹配控件数量,如下图所示。这种情况说明当前对象节点未能通过唯一性验证,继续操作该节点可能会带来错误的结果。为解决这一问题,您可以使用“自动添加索引”功能,或者手动添加 index 属性。

验证唯一性

index 属性的适用场景及局限性

index 属性在大多数场景下都适用,但它也有一定局限性。它的定位是基于控件返回的数组顺序,因此在控件布局不经常变化的应用中比较可靠。然而,对于布局或控件数量经常变化的应用(例如在 Qt 自动化中处理 ListTree 控件时),index 属性的使用可能不够稳定。更多关于 index 在实际开发中的应用,您可以参考以下演练文档:

搜索提示:searchHint

searchHint 属性提供了一种帮助测试程序更快速、精准地找到目标控件的搜索提示信息,减少控件识别失败的可能性。当前支持的 searchHint 属性值包括 fromPointnavigate

searchHint

1. 基于坐标的控件搜索:fromPoint

fromPoint 是一种通过遍历控件区域中的坐标点来搜索子控件的方式,适用于那些在控件结构树中不可见但可以被检测到的控件(例如使用 ATL 或 DevExpress 技术开发的控件)。这些控件的特点通常是:它们可以被侦测到,但无法高亮显示,父控件下也看不到任何子控件(即 findControls() 返回空数组)。

当为控件指定了 fromPoint 属性后,执行时将改变默认的子控件搜索方式。通常情况下,程序会调用 UIA 的 FindAll API 搜索子控件;但使用 fromPoint 时,程序会以 10 像素为间隔遍历控件区域,并通过坐标定位子控件。

何时使用 fromPoint

如果满足以下情况,可以考虑使用 fromPoint 属性:

  • 某个控件在模型管理器中能被检测到,并且通过了唯一性验证,但保存后无法高亮显示(操作期间控件属性未发生变化,且应用未重启)。
  • 浏览控件树中查看时,父控件下未显示任何子控件(或者 findControls() 返回空数组)。

此时,您可以为该控件的父控件添加 fromPoint 属性,确保其子控件能够正确定位。

注意:fromPoint 的行为自 CukeTest 1.8.3.108 版本起有所调整,以上说明适用于该版本及之后的版本。

navigate 属性通过使用导航方法来定位子控件,而不是依赖 UIA 的搜索 API。该方式适用于解决某些控件在定位时导致卡顿或 UIA 服务崩溃的问题,尤其在较旧的应用程序中更为常见。

使用 navigate 属性时,程序首先定位到当前控件的父控件,接着使用 firstChild()next() 方法依次导航,直到找到符合条件的控件。

使用注意事项
  • navigate 会忽略容器控件内的子控件(如 listItemtreeItemtableItem)。在这些场景下,需要在 item 控件的上层指定其容器,例如为 listItem 指定 list 作为容器。

以下是在描述模式中使用 navigate 定位 listItem 的示例代码:

Python
listItem = WinAuto.getGeneric([
    {
        "type": "Window",
        "automationId": "MainForm",
        "appName": "ProgramName",
        "searchHint": "navigate"
    },
    {
        "type": "List",
        "className~": "^WindowsForms10\\.SysListView32\\.app\\.",
        "index": "2"
    }, {
        "type": "ListItem",
        "automationId": "ListViewItem-6"
    }
])

objectType

目标控件的抽象类型。objectType 是为了更精确地控制和操作这些控件而设计的一个属性。它允许我们告诉CukeTest应该如何理解和处理特定的控件,即使这个控件的原生类型 (typeclassType) 在开发阶段已被确定。

以 Windows 11 的资源管理器为例,展示文件分组的控件类型被识别为 Group,这意味着它们本身不提供直接获取数据的 data() 方法。但是,通过将这些控件的 objectType 设置为 List,我们便能够按照列表控件的方式对它们进行操作,从而使用列表控件的所有方法和属性。

实际操作中,当我们将 objectType 设为 List 后,就可以在脚本中使用列表的相关操作,如下所示:

JavaScript
Python
await model.getList("上月").data();  // 设置为List类型后,还可以使用List控件的智能提示,提升编码效率
model.getList("上月").data()

这种做法不仅增强了脚本的可读性,还通过智能提示功能加速了脚本的编写和调试过程。

levelToParent

目标控件的所处层次。对于多层次的应用来说,有时会出现目标控件存在同名的子控件或父控件,这个时候通过限制识别层级可以避免识别到不需要的控件,如下图所示:
levelToParent属性识别示意图

三. 特有属性

特有属性是指只存在于某些特定类型控件的属性。

text

目标控件的文本内容,存在于Text控件中。

url

目标控件指向的链接,存在于Hyperlink控件中。

title

目标控件的标题,通常存在于Window控件中。

hWnd

目标控件的窗口句柄,只存在于Window控件中。

helpText

目标控件的帮助文字,大部分控件都有该属性,但常常为空。

processId

目标控件所处应用的进程标识,也就是PID,在描述模式中比较常用到。

四、其他属性

boundingRectangle

目标控件的形状信息,由一组长度为4的数组描述,数组中的值代表:[x, y, width, height],其中的xy分别代表控件在桌面坐标系中的横纵坐标,widthheight代表控件的宽度和高度。
boundingRectangle通常用于绘制控件的高亮框,由于应用窗口化启动时的大小和位置都不确定,boundingRectangle就会十分不稳定,因此也极少作为识别属性使用。如果应用中的控件无法被很好的识别,必须要使用控件的坐标等信息作为操作目标,那么推荐使用虚拟控件作为解决方案。

appPath

类似于appName属性,appPath属性也只存在于顶层窗口对象中,它是被测应用首次被侦测到时的执行路径。不同的是,appPath不能作为识别属性。它可以协助启动被测应用,如果根对象有这个属性,那么在这个对象上点击右键,弹出菜单中会出现"启动应用"的选项,选择这个选项会直接启动这个应用,前提是appPath的值能定位到这个执行文件。

在代码中使用识别属性

在一些情况下,我们可以跳过模型管理器直接在代码中通过识别属性来取得目标控件,这在很多情况下可以完成更加灵活的自动化,就像Qt的几个演练一样。而使用的就是findControls方法,关于它的用法说明可以点击查看获取对象API

results matching ""

    No results matching ""