UFT 对象定位的问题及技巧(含正则实战 & 无代码对比)

这几天,忙着找国内推广自己无代码的自动化测试平台的事情,所以“混迹”在几个测试群中,看大家插科打诨。虽然大家群里各类八卦聊的不少,也有“正经”的时候。就在我问“为什么不用自动化测试”时,居然有个“正经”的回答,说,“搞不起”。我以为是定价,我记得红杉印度投资的一个测试平台,一个月要几十刀。本来,我计划在国内推广时候,采用低价策略,所以我说,一个月不到10块总搞得起吧。后来才知道,是“搞不起来”的意思。

现在的脚本式自动化测试平台确实是“搞不起来”。对象的定位就是首要的问题。GUI 的测试的首要任务就是对象的定位。如果连对象定位都磕磕碰碰,怎么测试?怎么快速回归?怎么快速迭代?

AI 时代尤其需要回归测试系统的高效、正确,这也是对自动化测试系统的首要挑战之一。那么,这里就聊聊 Unified Functional Testing(以下简称 UFT)的对象定位问题。


一、UFT 的对象分类机制:先看插件

UFT 的对象识别是基于技术栈插件的:

  • swf*:.NET WinForm

  • wpf*:WPF

  • java*:Java

  • win*:Win32 / VC++

  • web*:Web

如果插件没加载,对象直接降级为 WinObject
后面所有定位技巧都白搭。

第一原则:

先确认 Add-in,再谈定位。


二、.NET 下常见关键属性

在 .NET 应用中常见定位属性:

  • swfName

  • swfType

  • swfNamePath

  • text

UFT 内部有一套优选机制,会自动组合属性。

但问题是:

自动选的,未必是最稳的。


三、对象“搞不起来”的核心原因

1️⃣ 控件改名

动态 ID:

TradeGrid_12345
TradeGrid_67890

下次执行直接挂。
我见过一个比较流行的金融资管系统TPG就是如此,控件是动态生成,导致普通的录制脚本,基本没法用。


2️⃣ 层级增加 / 减少

原来:

MainWindow;Panel;TradeGrid

后来:

MainWindow;Panel;GroupBox;TradeGrid

swfNamePath 立即失效。


3️⃣ 多语言问题

Text="Submit"

改成中文:

Text="提交"

全线崩溃。


四、正则表达式:应对改名的利器

UFT 支持正则表达式匹配属性,这是很多人忽略的武器。

示例一:匹配动态编号

SwfWindow("swfName:=TradeGrid_.*")

或者:


Set desc = Description.Create
desc("swfName").RegularExpression = True
desc("swfName").Value = "TradeGrid_\d+"

优势:

  • 不怕编号变化

  • 不怕流水号递增


示例二:应对名称前后缀变化

假设控件名:


OrderTradeGrid_Main
OrderTradeGrid_Backup

可以:


desc("swfName").Value = ".*TradeGrid.*"
desc("swfName").RegularExpression = True


五、正则应对层级变动(缩减层次问题)

很多人过度依赖 swfNamePath

这几乎是灾难。

解决策略:

1️⃣ 不用完整路径

改为:

  • 锁定稳定父对象

  • 子对象使用 index 或局部匹配

示例:


Window("Main").SwfWindow("Trade").ChildObjects(desc)(0)


2️⃣ 使用正则模糊路径


desc("swfNamePath").RegularExpression = True
desc("swfNamePath").Value = ".*TradeGrid"

这样即便中间多嵌套一层,也不会崩。


3️⃣ 局部层级锁定策略(推荐)

不要锁死:


Main;Panel;Group;Grid

改成:

  • 锁定 Window

  • 锁定核心容器

  • Grid 用正则匹配

这叫“层级缩减策略”。

核心原则:

层级越少,稳定性越高。


六、描述性编程:替代对象库的关键

大型项目里 Object Repository 是维护灾难。

建议使用描述性编程:


Set gridDesc = Description.Create
gridDesc("swfType").Value = "DataGridView"
gridDesc("visible").Value = True

Set grids = Window("Main").ChildObjects(gridDesc)
grids(0).Click

优点:

  • 可组合

  • 可封装

  • 可正则扩展


七、Grid 才是真正的“雷区”

金融系统几乎全是 Grid。

问题包括:

  • 虚拟滚动

  • Cell 不可直接识别

  • 自定义绘制

常用技巧:

gridObj.ActivateCell 3, "Amount"
gridObj.SetCellData 3, "Amount", "1000000"

这里讲一个Finastra(国内已经被恒生电子收购)的拳头产品之一:Opics。这个系统架构(个人认为)及其优秀。几乎是配置化软件的“巅峰”,通过配置文件加载交易录入,审批等模块。而这些模块的表达几乎全部用Infragistics的Grid实现,而且支持“随心所欲”的个性化。所以,UFT上面的定位那一套几乎全失效。

如果是复杂自定义控件:

  • 使用 NativeObject

  • 或调用 .NET 方法

这已经进入高级阶段。


八、对象定位的四个稳定原则

  1. 不信任动态 Name

  2. 尽量减少层级依赖

  3. 使用正则匹配变化部分

  4. 避免全局对象库爆炸

当定位不稳定时:

自动化永远搞不起来。


九、AI 时代下的现实问题

很多人问:

“现在都 AI 了,还研究 UFT 定位?”

我要说一句现实的话:

AI 生成脚本 ≠ 定位问题解决。

如果对象识别层不稳:

  • AI 生成的脚本只会更脆弱

  • 回归失败率更高

  • CI/CD 变成摆设


十、为什么我后来做无代码自动化系统

传统脚本式自动化的痛点:

  • 依赖技术栈插件

  • 依赖属性稳定性

  • 依赖工程师水平

  • 维护成本极高

后来我做自动化系统时,核心改进在三点:

1️⃣ 语义层封装

不是针对某个技术栈的直接操作:


SwfButton("xxx").Click
JavaButton("xxxxx").Click

而是操作:

ClickButton("xxxx", parameter)

2️⃣ 对象抽象层独立于工具

不把定位写死在脚本。

而是建立对象模型库。


3️⃣ 无代码化

在我现在做的 MARS 自动化体系中:

  • 对象通过语义建模

  • 支持动态匹配

  • 自动适应层级变化

  • 非技术人员也可维护

对比传统 UFT:

维度 UFT 脚本式 MARS 无代码
定位方式 属性匹配 语义 + 模型
维护成本
技术依赖

结语

对象定位,是 GUI 自动化的地基。

UFT 很强,但必须懂技巧:

  • 正则表达式

  • 层级缩减

  • 描述性编程

  • 语义封装

否则,“搞不起”就会变成“搞不起来”。

如果大家愿意,下一篇可以讲:

  • 金融桌面系统自动化架构设计

  • UFT 插件识别原理深度解析

  • 或 AI + 无代码自动化的融合路径

评论区见。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐