Text识别技术
对于一些较旧的技术开发的Windows应用程序,CukeTest对控件对象识别的支持可能有限。但通过GuiText插件,CukeTest增强了对使用Windows GDI绘图机制在屏幕上显示文本的控件的识别能力。
如果控件中的特定文本位置无法被识别为控件,那么可以通过使用文字对象(GuiText)和文字表格对象(TextTable)来解决这个问题。
文字对象(GuiText)
文字对象(GuiText)允许您将界面上的文本视为可操作的对象,便于实现对特定文本的精确控制和操作。其实现原理是从图形渲染的底层机制入手,通过定位文本位置,在已有的控件树上实现更精确的定位。
添加文字对象
与其他测试对象一样,文字对象也需要在模型管理器中进行侦测、识别和管理。打开模型文件或模型管理器后,点击“添加文字对象”(位于“添加Windows对象”按钮的下拉列表中)来侦测和添加文字对象。
编辑属性
文字对象目前只有一个标识属性——text
。该属性支持使用正则表达式进行匹配,详情请参考修改匹配模式。
编辑父节点
在编辑文字对象的父节点时需谨慎,因为文字对象对其直接容器控件有特定要求。如果删除文字对象最近的容器控件(如Pane、Window、Tree、Menu等),可能会导致文字对象无法被正确识别。
文字对象的API
类型定义
export interface IGuiTextControl {
click(x?: number, y?: number, mousekey?: number): Promise<void>;
dblClick(x?: number, y?: number, mousekey?: number): Promise<void>;
exists(seconds?: number): Promise<boolean>;
highlight(duration?: number);
moveMouse(x?: number, y?: number, seconds?: number): Promise<void>;
rect(): Promise<Rect>;
text(): Promise<string>;
takeScreenshot(filePath?: string): Promise<string>;
modelImage(options?: {encoding: 'buffer' | 'base64'}): Promise<string | Buffer>; //base64 is the default
modelProperties(all?: boolean): {[x: string]: any};
}
class GuiTextControl(ControlBase):
def click(x: Optional[int]=None, y: Optional[int]=None, mousekey: Optional[int]=None) -> None
def dblClick(x: Optional[int]=None, y: Optional[int]=None, mousekey: Optional[int]=None) -> None
def exists(seconds: Optional[int]=None) -> bool
def highlight(duration: Optional[int]=None) -> None
def moveMouse(x: Optional[int]=None, y: Optional[int]=None, seconds: Optional[int]=None) -> None
def rect() -> Rect
def text() -> str
def takeScreenshot(filePath: Optional[str]=None) -> str
def modelImage(encoding: Optional[str]=None) -> Union[str, bytearray]
def modelProperties(all: Optional[bool]=None) -> TypedDict
操作方法
- click(x, y, mousekey)
- dblClick(x, y, mousekey)
- takeScreenshot(filePath)
- moveMouse(x, y)
- highlight(miliseconds?: number)
- modelProperties()
- modelImage(options?: {encoding: 'buffer' | 'base64'})
- exists(time)
属性方法
需要注意的控件的属性方法都是异步的,在调用后CukeTest会与目标控件通信,获取控件当前的属性,即实时属性,而不是模型对象中的识别属性。下面列出的属性所有控件都支持,但不一定都有值,可以根据建议尝试类似的属性方法来获取目标属性。
文字表格对象(TextTable)
当您需要操作位于同一控件下的多个文本对象时,文字表格对象(TextTable)提供了一种高效的解决方案。如果在目标Windows控件下识别到多个同级的文字对象,CukeTest会在识别结果中提供一个特殊的节点——文字表格对象(TextTable)。通过将这个对象添加到控件树中,您可以像操作表格一样使用它,实现对多个文本对象的集中管理和操作。
添加文字表格对象
在模型管理器中识别到多个同级文字对象时,CukeTest会自动提供添加文字表格对象的选项。选择“添加文字表格对象”后,CukeTest将这些同级文字对象组织成一个表格结构,便于您后续的测试操作。
一旦文字表格对象被添加到控件树中,您就可以通过指定行列号来访问和操作其中的文本。这包括但不限于点击特定的单元格,获取特定单元格的文本内容、验证单元格文本的正确性,或者在表格中执行搜索和比较操作。
裁剪识别区域
clip
属性使您能够为文字表格对象(TextTable)定义一个明确的识别区域,从而专注于表格的特定部分。通过设置clip
属性的值为一个对象,并指定left
、top
、right
、bottom
中的一个或多个参数,您可以精确控制要识别的区域边界。
举例说明:
- 设定
clip
为{left: 147, top: 98}
,则系统只会识别表格右下方的区域,而忽视其他部分。这一设置通过对表格的左边界右移147个像素,以及从顶部下移98个像素,来裁剪出具体的识别区域。 - 若
clip
设置为{right: 147}
,则只有表格左侧的内容会被识别,其他区域则被忽略。这是通过将表格的右边界左移147个像素,来确定识别的范围。
利用clip
属性,您可以更精确地定位并操作文字表格对象中的文本,尤其是在处理大型表格或只关注表格特定区域时非常有用。
编辑父节点
在编辑文字表格对象的父节点时需谨慎,因为文字表格对象对其直接容器控件有特定要求。如果删除文字表格对象最近的容器控件(如Pane、Window、Tree、Menu等),可能会导致对象无法被正确识别。
使用示例
假设您正在测试一个包含多个联系人信息的应用,每个联系人的信息(如姓名、电话、邮箱等)以列表形式显示。通过添加文字表格对象,您可以轻松地验证列表中每一行的联系人信息,或者查找特定联系人的信息。
(async function() {
let textTable = await model.getTextTable("ContactsList");
let contactInfo = await textTable.getCellText(1, 2); // 获取第1行第2列(假设为电话号码)的文本
console.log(`联系人电话: ${contactInfo}`);
// 执行其他文本验证或操作...
})();
文字表格对象的API
类型定义
export interface ITextTable extends ITextGuiText {
clickCell(rowIndex: number, columnNameOrIndex: string | number): Promise<void>;
cellValue(rowIndex: number, columnNameOrIndex: string | number): Promise<string>;
columnName(index: number): Promise<string>;
columnHeaders(): Promise<string[]>;
columnCount(): Promise<number>;
data(): Promise<string[][]>;
rowCount(): Promise<number>;
rowData(rowIndex: number): Promise<string[]>;
}
class TextTableControl(ControlBase):
def clickCell(rowIndex: int, columnNameOrIndex: Union[str, int]) -> None
def cellValue(rowIndex: int, columnNameOrIndex: Union[str, int]) -> str
def columnName(index: int) -> str
def columnHeaders() -> List[str]
def columnCount() -> int
def data() -> List[List[str]]
def rowCount() -> int
def rowData(rowIndex: int) -> List[str]
操作方法
- clickCell(rowIndex: number, columnNameOrIndex: string | number)
- cellValue(rowIndex: number, columnNameOrIndex: string | number)
- columnName(index: number)
- columnHeaders()
- columnCount()
- data()
- rowCount()
- rowData(rowIndex: number)
data(): Promise<string[][]>
获取表格中的所有内容,并以二维数组的形式返回。
- 返回值:
Promise<string[][]>
类型,即二维的字符串数组。
假如表格数据如下:
学号 | 姓名 | 性别 |
---|---|---|
0001 | 小王 | 男 |
0002 | 小明 | 男 |
0003 | 小红 | 女 |
那么data()
方法返回的数组如下:
[
['0001', '小王', '男'],
['0002', '小明', '男'],
['0003', '小红', '女']
]