视觉 AI界面控件自动化测试:TestComplete 能测什么,不能测什么
2026 年 6 月,SmartBear 在 TestComplete 中正式启用 Vision AI(官方称 visual object detection)。官方将其描述为"首个把属性识别、OCR 与视觉 AI 统一的平台"——这是厂商表述,不是第三方结论。本文只依据官方文档与实际脚本行为,讲清它能做什么、现在还做不到什么。
一、先搞懂它站在哪一层
很多人的第一个误解,是以为视觉 AI 来了就可以抛弃属性识别。恰恰相反。
TestComplete 的对象识别是分层的:
- 属性识别——读控件暴露出来的属性(UIA、DOM、MSAA 等)。属性齐全且稳定时,这是首选,最快也最稳。
- OCR——把界面当图片,读里面的文字。
- 视觉识别(Vision AI)——把界面当图片,用视觉模型判断"这是个按钮"“那是个输入框”。
官方文档的定位很明确:视觉识别是对属性识别的补充,可在属性识别碰壁时作为自动兜底(automatic failover)。属性还在的时候刻意用视觉识别,是拿快而稳的路换慢而软的路。
真正必须动用第三层的,是下面这四类界面:
- canvas 自绘界面:交易终端、BI 仪表盘、地图类应用,内容直接画成像素,DOM 与可访问属性一概没有
- 自定义图形引擎:CAD、医学影像、仿真类软件,用私有渲染,不暴露标准属性
- 遗留桌面程序:早于现代可访问性标准建成,业务上又不能重写
- 虚拟桌面(Citrix / 远程桌面):整屏以图像流呈现,自动化工具看不到任何独立控件
它们的共同点是:不是定位难,是根本没有可定位的东西。
二、开工前:四个前置条件,漏一个就白忙
- 许可:需 Pro Bundle,或单独购买 Intelligent Quality (IQ) add-on
- 扩展:
File → Install Extensions → Intelligent Quality,勾选 Visual Object Detection,完成后重启 TestComplete - 网络:开启后,被测应用截图与 UI 元数据会发往 SmartBear 托管的 AI 服务,需放通端点
https://ocr-service.prod.testcomplete.com。内网、涉密或有数据出境限制的环境,务必提前与 IT 和合规部门确认,否则功能等于不可用 - 进程优先级:
项目 → Properties → Visual Object Detection,添加要启用视觉识别的进程名;填*表示对所有进程生效。未列入的进程仍走标准识别顺序
三、实战一:VOD 录制出来的代码长什么样
开启后正常录制,交互时 TestComplete 会把截图送去做视觉检测,返回的元素目录进入 Object Browser,脚本里通过 VODWindow 访问。官方录制产物大致如下:
// 录制 Vision AI 操作后自动生成的脚本(官方示例)
function Test1() {
Sys.Process("xtop").VODWindow("HCS16139P", "*").Click(1058, 215);
Sys.Process("xtop").VODWindow("HCS16139M").BOTTOM.Click();
Sys.Process("xtop").VODWindow("HCS16139P", "*").Click(1057, 223);
Sys.Process("xtop").VODWindow("HCS16139M").TOP.Click();
Sys.Process("xtop").VODWindow("HCS16139M").StandardOrientation.Click();
}
注意第一、三行的 Click(1058, 215)——这是录制时刻的绝对坐标。窗口位置、分辨率、DPI 缩放一变,这两行最先崩。
改进办法:用控件自身尺寸算中心点,而不是复刻坐标。
/**
* 按控件路径定位 VOD 元素,并以中心点点击,规避录制坐标漂移。
* @param {string} processName 目标进程名,如 "xtop"
* @param {string} windowId VOD 窗口标识
* @param {string} controlPath 子控件路径,多级用 "." 分隔,无子控件传 ""
* @param {number} timeout 等待毫秒数
* @returns {boolean} 是否点击成功
*/
function clickVodControl(processName, windowId, controlPath, timeout) {
var win = Sys.Process(processName).VODWindow(windowId, "*");
if (!win.Exists) {
Log.Error("VOD 窗口未找到", "process=" + processName + ", windowId=" + windowId);
return false;
}
var ctrl = win;
if (controlPath !== "") {
var parts = controlPath.split(".");
for (var i = 0; i < parts.length; i++) {
ctrl = ctrl.WaitChild(parts[i], timeout || 10000);
if (!ctrl.Exists) {
Log.Error("VOD 子控件未找到",
"路径=" + controlPath + ",在 \"" + parts[i] + "\" 处中断");
return false;
}
}
}
// 用控件自身尺寸计算中心点,比照搬录制坐标稳得多
ctrl.Click(Math.round(ctrl.Width / 2), Math.round(ctrl.Height / 2));
Log.Message("已点击 VOD 控件: " + (controlPath === "" ? windowId : controlPath));
return true;
}
// 调用
clickVodControl("xtop", "HCS16139M", "StandardOrientation", 10000);
WaitChild 是 TestComplete 通用的等待子对象方法,在 VOD 返回的对象上同样可用;若你的版本在该对象上不支持,直接以属性方式访问(如 .BOTTOM)亦可。
四、实战二:三种识别怎么串起来
真实项目几乎不会只用一种识别方式。下面场景很典型:Citrix 里跑着终端,外层是普通可识别窗口,中间行情区是 canvas 自绘,数值还画在图里。
function MixedRecognitionFlow() {
// —— 第一层:属性识别。外层窗口属性完整,走 Name Mapping 别名,最快最稳
var shell = Aliases.citrixShell;
shell.Activate();
// —— 第二层:视觉识别。canvas 自绘的工具栏,属性层拿不到,交给 VOD
if (!clickVodControl("xtop", "HCS16139M", "Refresh", 10000)) {
return false;
}
// 等待行情区完成重绘,视觉识别阶段务必留足渲染时间
var canvasHost = Aliases.citrixShell.QuotePanel;
if (!canvasHost.WaitProperty("Enabled", true, 15000)) {
Log.Warning("行情区在 15 秒内未完成重绘,后续断言可能不稳定");
}
// —— 第三层:OCR。数值是画在图上的,只能读图取字
var quoteArea = canvasHost.Picture(120, 60, 420, 260); // x, y, width, height
var doc = OCR.Recognize(quoteArea);
Log.Message("行情区 OCR 结果", doc.FullText);
return aqString.Find(doc.FullText, "最新价", 0, false) > -1;
}
三段各司其职:能拿属性的绝不浪费视觉识别,拿不到属性的才降级,需要读图里的字就交给 OCR。这也是官方推荐的混合思路。
五、首版没有检查点,断言怎么办
官方文档写明:当前版本 Vision AI 不支持 checkpoints、operations 与 Object Spy,仅支持在测试录制阶段捕获对象。视觉识别现在主要负责"找到并操作",断言这一环要自己补。有两条可行路径。
文本断言:弃用 CheckText,改用 FullText
CheckText 只在日志里丢一个通过或失败,排查时拿不到上下文。改用 FullText 自行比对,失败时能留下 OCR 实际读到的内容:
/**
* 在指定图像区域中断言文本存在,失败时输出完整 OCR 结果与区域截图。
*/
function assertTextInPicture(picture, expected, caseSensitive) {
var text = OCR.Recognize(picture).FullText;
var hit = aqString.Find(text, expected, 0, caseSensitive === true) > -1;
if (hit) {
Log.Message("命中预期文本", "期望=" + expected);
} else {
Log.Error("未找到预期文本",
"期望=" + expected + "\r\nOCR 实际识别结果:\r\n" + text);
Log.Picture(picture, "断言区域截图"); // 把现场一并存档,便于复盘
}
return hit;
}
视觉断言:像素比对 + 差异图落盘
对图表、仪表盘这类"没法用文字描述正确性"的对象,用基线图片做像素级回归,并把差异图存下来:
/**
* 与基线图片做像素比对,失败时生成差异图并落盘。
* 用于替代首版缺失的 VOD 检查点。
*/
function assertVisualBaseline(obj, region, baselineName, pixelTolerance) {
var actual = (region === null)
? obj.Picture()
: obj.Picture(region[0], region[1], region[2], region[3]);
// Regions.Compare(图1, 图2, 透明, 含鼠标, 报差异, 容差, 消息类型)
var ok = Regions.Compare(baselineName, actual, false, false, true,
pixelTolerance || 0, lmError);
if (!ok) {
var baseline = Regions.GetPicture(baselineName);
var diff = baseline.Difference(actual);
if (diff !== null) {
var stamp = aqConvert.DateTimeToFormatStr(aqDateTime.Now(), "%Y%m%d_%H%M%S");
var outFile = "D:\\QA\\Diff\\" + baselineName + "_" + stamp + ".png";
diff.SaveToFile(outFile);
Log.Error("视觉基线比对失败", "差异图已保存至: " + outFile);
}
}
return ok;
}
// 调用:对 Citrix 中的图表区域做视觉回归,容忍 50 个像素的差异
assertVisualBaseline(Aliases.citrixShell.ChartPanel, [40, 30, 800, 420],
"Baseline_Chart", 50);
容差建议留余量:字体渲染、抗锯齿、远程桌面压缩都会带来几个像素的差异,设 0 容易被噪声反复误伤。
六、跑进 CI:命令行与退出码
GUI 测试上 CI 的两个坑:一是需要交互式用户会话(Session 0 隔离下服务账户无法模拟键鼠),二是退出码处理。
@ECHO OFF
SET TE="C:\Program Files (x86)\SmartBear\TestExecute 15\Bin\TestExecute.exe"
SET PROJ="D:\QA\TradingClient\TradingClient.pjs"
SET OUT=D:\QA\Reports\%BUILD_NUMBER%
%TE% %PROJ% /run /SilentMode /ForceConversion /ns /exit ^
/project:CitrixRegression ^
/ExportLog:%OUT%\result.mht ^
/ExportLog:%OUT%\result.htmlx ^
/ErrorLog:%OUT%\error.txt ^
/DoNotShowLog
IF ERRORLEVEL 4 GOTO Timeout
IF ERRORLEVEL 3 GOTO CannotRun
IF ERRORLEVEL 2 GOTO Errors
IF ERRORLEVEL 1 GOTO Warnings
IF ERRORLEVEL 0 GOTO Success
:Timeout ECHO 执行超时 & EXIT /B 4
:CannotRun ECHO 无法运行:检查项目、测试项与插件配置 & EXIT /B 3
:Errors ECHO 测试存在错误 & EXIT /B 2
:Warnings ECHO 测试通过但有警告 & EXIT /B 1
:Success ECHO 无错误无警告 & EXIT /B 0
退出码含义:0 无错误无警告,1 有警告无错误,2 有错误,3 无法运行(项目打不开、测试项缺失、插件未启用、脚本语法错误等),4 超时,-1 许可检查失败。
CI agent 建议跑在真实用户会话下而非 SYSTEM 账户;否则即使逻辑全过,也可能因弹窗在静默模式下无法处理而返回 -1。
七、清单:它现在还不能做什么
| 限制 | 说明 |
|---|---|
| 不支持检查点 | 首版无 checkpoint,断言需用 OCR 或图片比对自行实现 |
| 不支持 Object Spy | 无法用 Spy 探查视觉识别出的元素 |
| 仅录制阶段捕获 | 检出对象发生在测试录制时 |
| 需要外网端点 | 需放通 ocr-service.prod.testcomplete.com |
| 许可门槛 | 需 Pro Bundle 或 IQ add-on |
| 不替代属性识别 | 属性可用且稳定时,属性识别仍是首选 |
至于"视觉识别会不会让脚本永不失效"——不会。它解决的是属性根本不存在的问题,外观大幅改版时同样要重新捕获。当成"多一层兜底"比"免维护"准确得多。
八、结语:下一步可以做什么
视觉 AI 打开的空间不小——那些长期被划进"只能手工测"的区域,第一次有了进入自动化回归体系的可能。对受监管行业还有一层意义:流程一旦可重复执行,产出的就是可留存、可追溯的执行记录,而不是一堆人工截图。
如果被测对象里有这类界面,建议分三步推进:
- 盘点场景——把至今只能手工测的界面列出来,判断属于 canvas 自绘、自定义图形引擎、遗留桌面还是虚拟桌面
- 确认前置条件——许可形态、扩展是否安装、内网能否放通 AI 服务端点,这三条决定项目能否起步
- 小范围 POC——挑一个高频稳定的流程先验证,不要一上来铺全量
如果你正在做类似场景,或卡在许可选型、内网部署这些环节,欢迎评论区留言,把界面类型和控制件情况说清楚,一起判断走哪层识别更合适;涉及报价、POC 环境搭建等问题,也可以站内私信,看到会回复。

更多推荐



所有评论(0)