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属性用于取出数组中指定位置的控件,比如为0时返回第一个,为1时返回第二个...并且将识别到的所有控件信息显示在模型管理器左下方。

可以认为index属性默认为0,也就是始终操作第一个匹配控件。因此即使没有识别到多个控件,index属性为0也能生效,但此时如果使用其它index值则会返回 错误1003:不能找到这个对象

当模型管理器发现对象节点匹配到多个控件时,会在左下角显示当前识别到的第一个控件坐标以及匹配到的控件数量(如下图),这表示该对象节点没通过唯一性验证,操作该节点可能会带来错误的结果,可以使用自动添加索引或者由自己手动添加索引来解决。

验证唯一性

index属性适用的场景非常广,但是也有其局限性。前文提到,index属性是根据识别到多个控件时返回的数组中的定位。对于控件布局不会变化的应用来说是可以的,但是如果某个应用它的控件布局、控件数量可能会变化,比如Qt自动化中针对List和Tree控件的自动化,index或许不可靠。下面这篇演练可以帮助你了解index在实际开发中的应用:

searchHint

控件对象的搜索指示信息,可以帮助测试程序快速找到目标控件对象,并减少识别失败的情况。目前支持的属性值为 fromPoint

  • fromPoint:表示从一个指定的屏幕坐标点开始,沿着控件树向上查找符合条件的控件对象。这个属性值可以用来通过控件中心点识别一些脱离控件树的控件对象,例如部分ATL或DevExpress等技术开发的应用控件。 使用fromPoint属性值时,默认使用其父控件的中心点坐标。"searchHint: fromPoint"的搜索指示属性应该加在控件树从上最上层的无法搜索到的节点。
  • navigate:表示当前控件会使用导航方法进行定位,而不是基于UIA提供的搜索API。这个属性值可以用来规避一些控件定位会卡住(可能导致了UIA服务的崩溃)的情况,例如部分比较旧的应用。使用navigate属性值时,会在定位到当前控件的父控件后,改用firstChild()next()两个导航方法搜索,直到找到与当前控件的识别属性一致的控件。 searchHint

objectType

目标控件的抽象类型。由于控件的类型type、所属的控件类classType都是不可改变的,在开发完成的时候就确定了,而objectType是告诉CukeTest该控件应该作为什么类型的控件来处理而设计的。

比如表格控件Table中的行,没有实际对应的控件类型,只是一个空属性的容器控件,但是CukeTest会在识别时将其objectType设为TableRow,从而会被当作TableRow控件使用,可以调用和调试TableRow控件的操作和属性方法。并且将调用代码复制到脚本编辑器中时,脚本会呈现如下:

JavaScript
Python
await model.getTableRow("TableRow"); // 有控件相关的智能提示
model.getTableRow("TableRow"); # 有控件相关的智能提示

在上面的脚本中,会出现方法的智能提示;而在没有使用objectType属性的较旧的CukeTest版本中复制的脚本则不会有提示:

JavaScript
Python
await model.getGeneric("TableRow");  // 只有通用方法的提示
model.getGeneric("TableRow");  # 只有通用方法的提示

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 ""