简介:本教程面向自动化测试初学者,系统讲解HP开发的功能测试工具QTP(现称UFT)的核心概念与实战技能。内容涵盖QTP基础原理、对象识别机制、录制回放技术、VBScript脚本编程、数据驱动测试及智能识别、检查点、事务和恢复场景等高级功能。通过学习本教程,读者将掌握使用QTP构建高效自动化测试流程的方法,并结合TestDirector(ALM)等测试管理工具实现项目级应用,显著提升软件测试效率与质量。
QTP/UFT自动化测试实战精要:从入门到企业级框架构建
在当今敏捷与DevOps盛行的软件交付体系中,手动回归测试早已无法满足高频迭代的需求。一个典型的Web应用每月可能经历数十次发布变更,而每次更新都必须确保核心功能不受影响——这正是自动化测试的价值所在。但现实是,许多团队的自动化项目最终沦为“鸡肋”:脚本脆弱、维护成本高、执行不稳定。问题的根源往往不在于工具本身,而在于对底层机制的理解缺失。
Micro Focus UFT(原HP QuickTest Professional)作为业界老牌的功能自动化测试平台,历经多年演进,其能力远不止于简单的“录制回放”。真正发挥UFT潜力的关键,在于深入掌握其对象识别模型、VBScript编程范式以及数据驱动架构设计。本文将带你穿透界面层,直击UFT的核心技术脉络,帮助你构建一套 高稳定性、易维护、可扩展的企业级自动化测试体系 。
环境准备不是第一步,而是成败的前提 🧰
很多初学者一上来就急着安装UFT开始录制,结果卡在浏览器兼容性或插件配置上浪费半天时间。别忘了,UFT本质上是一个Windows桌面级自动化工具,它的运行环境极为敏感。跳过这一步?那你离“对象找不到”错误就不远了。
首先明确一点: UFT 15.x 及以上版本已全面支持Chrome和Firefox ,但底层仍依赖IE引擎进行DOM解析(尤其是Web测试)。这意味着即使你用Chrome跑脚本,也必须正确配置IE的安全区域设置。
✅ 必须完成的基础配置清单:
- 操作系统 :Windows 10 Pro/Enterprise 或 Windows Server 2016+
- 权限要求 :以管理员身份运行安装程序
- .NET Framework :至少4.7.2
- 浏览器信任站点设置 :
- 将被测系统URL添加至IE“受信任的站点”
- 关闭“启用保护模式”(每个安全区域)
- 启用“允许ActiveX控件运行”
💡 小贴士:如果使用虚拟机,请关闭Hyper-V加速,否则可能导致QTP崩溃。
安装过程中最关键的一步是选择Add-ins(附加组件),它决定了你能测什么类型的应用:
| Add-in 类型 | 支持的应用场景 |
|---|---|
| Web | 所有主流浏览器上的网页应用 |
| ActiveX | 嵌入式控件、旧版银行插件 |
| .NET | WinForms、WPF桌面程序 |
| Java | Swing/AWT开发的企业客户端 |
| SAP | SAP GUI for Windows |
选错Add-in?那你的对象识别就会失败。比如你要测一个基于Electron的内部管理系统,就必须勾选 .NET 和 Web 两个模块。
许可证激活也不容忽视。如果你使用的是浮动许可(Floating License),请确保LMTOOLS服务已启动,并能通过端口连接到License Server。节点锁定(Node-locked)虽然简单,但在CI/CD流水线中难以部署——这也是为什么越来越多企业转向UFT Developer + ALM/OCTANE集成方案。
对象识别:自动化测试的“心脏” 💓
你可以不会写代码,但不能不懂对象识别。因为所有操作的本质,都是“找到某个控件并对其施加动作”。当页面刷新后按钮消失了,你以为是BUG?其实很可能是UFT根本没认出它。
🤖 UFT的对象模型长什么样?
想象一下,整个应用程序界面被UFT抽象成一棵树结构:
Browser("MyApp")
└── Page("Login")
├── WebEdit("Username")
├── WebEdit("Password")
└── WebButton("Submit")
每一层节点都有自己的“身份证信息”,也就是属性集合。例如一个登录按钮的典型属性如下:
| 属性名 | 值 | 是否关键 |
|---|---|---|
micclass | WebButton | ✔️ 必须 |
html tag | INPUT | ✔️ |
type | submit | ✔️ |
name | loginBtn | ✅ 推荐 |
value | 登录 | ❌ 可变 |
这些属性共同构成了UFT查找该元素的依据。一旦其中某些属性发生变化(比如前端重构把 name="loginBtn" 改成了 btn-login ),原来的脚本就会报错:“Cannot identify the object”。
这时候你就需要理解两种核心机制: 对象仓库(Object Repository) 和 描述性编程(Descriptive Programming) 。
🗃️ 共享 vs 本地对象仓库:选哪个?
新手常犯的错误就是只用本地OR(Local OR),导致每个Action里都要重复添加相同的登录框、导航栏等元素。结果呢?改一处UI,几十个脚本全得重录。
| 维度 | 本地OR | 共享OR (.tsr) |
|---|---|---|
| 存储位置 | 内嵌在Action内部 | 独立文件,集中管理 |
| 复用性 | ❌ 仅限当前Action | ✅ 跨测试、跨项目共享 |
| 版本控制友好度 | ⚠️ 难以追踪变更 | ✅ 可提交至Git/SVN |
| 团队协作效率 | 低 | 高 |
👉 建议实践 :建立标准组件库!
比如创建一个名为 Common_UI.tsr 的共享仓库,专门存放:
- 登录页的所有字段
- 主菜单栏、侧边栏链接
- 弹窗确认/取消按钮
- 分页控件、搜索框
这样新来的同事只需要加载一次这个文件,就能立即开始编写脚本。
加载共享仓库的代码示例:
' 初始化阶段统一加载
RepositoriesCollection.Add "C:\UFT_Repo\Common_UI.tsr"
' 后续直接调用预定义对象
Browser("MyApp").Page("Login").WebEdit("Username").Set "admin"
Browser("MyApp").Page("Login").WebButton("Submit").Click
🛠️ 技巧:可以用相对路径配合环境变量来提升可移植性:
vbscript RepositoriesCollection.Add Environment.Value("REPO_PATH") & "\Common_UI.tsr"
🔍 描述性编程:应对动态ID的利器
有些前端框架喜欢给元素生成随机ID,比如React中的 id="input-8a9b2c" ,每次刷新都不一样。这种情况下,靠对象仓库录制等于白费功夫。
解决方案:放弃固定对象,改用属性组合动态查找!
Set dynamicField = Browser("MyApp").Page("Form").WebEdit("html tag:=INPUT", "placeholder:=请输入邮箱")
dynamicField.Set "test@example.com"
语法要点:
- 使用
"property:=value"格式传递条件 - 多个条件用逗号分隔
- 不依赖OR,完全在运行时匹配
📌 适用场景包括:
- 动态生成的表格行
- Ajax异步加载的内容
- 富文本编辑器内的嵌套iframe
- 循环遍历一组相似按钮
不过要注意,过度使用DP会导致脚本可读性下降。最佳策略是 混合使用 :静态部分走OR,动态部分用DP补充。
🤯 智能识别(Smart Identification):最后的救命稻草
当主属性全部失灵时,UFT还有最后一招——智能识别(SI)。它像侦探一样,先看有没有明显的特征(Base Filter Properties),再结合其他线索(Optional Filter Properties)缩小范围。
工作流程如下:
graph LR
A[开始查找对象] --> B{主属性是否匹配?}
B -- 是 --> C[成功返回]
B -- 否 --> D{启用SI?}
D -- 否 --> E[抛出错误]
D -- 是 --> F[按Base属性筛选候选]
F --> G{唯一匹配?}
G -- 是 --> H[返回]
G -- 否 --> I[加入Optional属性过滤]
I --> J{只剩一个?}
J -- 是 --> K[返回]
J -- 否 --> L[报错:歧义或多匹配]
举个例子:原来按钮 name="Login" 变成了 Sign In ,主属性失效。但如果它的 html tag=INPUT 且 type=submit 没变,SI仍然可以定位到它。
但注意⚠️:SI是一把双刃剑!
如果有多个submit按钮同时存在,它可能会点错地方。所以建议:
- 开发阶段关闭SI,确保脚本能靠精确属性运行;
- 生产环境开启SI作为容错手段;
- 定期检查日志,确认SI未误触发。
关键字驱动测试:让非程序员也能参与自动化 📊
很多人觉得自动化=写代码,其实不然。UFT最强大的设计理念之一就是 关键字驱动测试(KDT) ,它把复杂的逻辑拆解为一个个“动词+名词”的操作步骤,就像Excel表格一样直观。
打开关键字视图(Keyword View),你会看到类似这样的结构:
| Item | Operation | Value | Comment |
|---|---|---|---|
| Username Field | Set | ${UserName} | 输入用户名 |
| Password Field | SetSecure | ${EncryptedPwd} | 输入加密密码 |
| Login Button | Click | 提交登录 | |
| Welcome Msg | Check | chk_WelcomeMsg | 验证登录成功提示 |
是不是一眼就能看懂?这就是KDT的魅力所在。QA人员不需要懂VBScript,只要会填表就可以设计测试用例。
背后发生了什么?其实每一步都被自动翻译成了VBScript:
Browser("MyApp").Page("Login").WebEdit("Username").Set DataTable("UserName", dtGlobalSheet)
Browser("MyApp").Page("Login").WebEdit("Password").SetSecure DataTable("EncryptedPwd", dtGlobalSheet)
Browser("MyApp").Page("Login").WebButton("LoginBtn").Click
If Browser("MyApp").Page("Home").WebElement("Welcome").Exist(5) Then
Reporter.ReportEvent micPass, "Validation", "Passed"
Else
Reporter.ReportEvent micFail, "Validation", "Not found!"
End If
也就是说, 关键字视图只是专家视图的可视化外壳 。你可以随时切换过去修改细节,也可以反过来——在专家视图写完代码,关键字视图会自动生成对应步骤。
如何提升KDT的复用性?
随着项目扩大,你会发现很多操作反复出现:登录、登出、清理缓存……每次都重新录一遍?太low了!
答案是使用 Reusable Action(可重用动作) 。
假设你录好了一个登录流程,右键点击Action → Properties → 勾选“Reusable action”,它就变成了一个独立模块。之后任何测试都可以通过以下语句调用:
RunAction "Login_Action", oneIteration, "user01", "pass@123"
参数说明:
-
"Login_Action":目标Action名称 -
oneIteration:执行一次;也可设为AllIterations循环执行 -
"user01", "pass@123":传入的用户名密码
更高级的做法是结合函数库(.qfl文件)封装通用方法:
' Utils.qfl
Function GetCurrentTimeFormatted()
GetCurrentTimeFormatted = Year(Now) & "-" & Right("0" & Month(Now), 2) & "-" & Day(Now)
End Function
Sub LogMessage(level, msg)
Reporter.ReportEvent Eval("mic" & UCase(level)), "Log", msg
End Sub
主脚本中加载并使用:
ExecuteFile "C:\Libraries\Utils.qfl"
LogMessage "Pass", "Start at: " & GetCurrentTimeFormatted()
这样一来,整个团队都能共享同一套工具函数,避免重复造轮子。
VBScript:UFT的灵魂语言 🧠
别被名字骗了,“Script”不代表简单。VBScript虽然是轻量级语言,但它具备完整的编程能力:变量、数组、条件判断、循环、异常处理……掌握它,你才能真正掌控UFT。
📦 变量与作用域:别让拼写错误毁掉一天
先看这段代码:
Option Explicit ' 强制声明变量!
Dim userName, loginCount
userName = "admin"
cnt = 10 ' 错误!未声明变量cnt
如果没有 Option Explicit ,上面这段代码会默默创建一个新变量 cnt ,而 loginCount 仍是空值——调试起来极其痛苦。
所以记住: 所有脚本顶部第一行必须加上 Option Explicit 。
关于作用域,有三种层级:
- 过程级 :在
Sub或Function内定义,外面看不见 - 脚本级 :在外部用
Dim声明,整个测试可用 - 全局级 :用
Public声明,在多个Action间共享
推荐原则:尽量缩小变量作用域,防止命名冲突污染。
➕ 运算符优先级:别让表达式出乎意料
下面这个表达式结果是多少?
result = 5 + 3 * 2 > 10 And Not IsNumeric("abc")
分解来看:
-
3 * 2 = 6 -
5 + 6 = 11 -
11 > 10 → True -
IsNumeric("abc") → False -
Not False → True -
True And True → True
所以结果是 True 。但如果不确定优先级,最好加括号:
result = ((5 + 3) * 2 > 10) And (Not IsNumeric("abc"))
清晰多了吧?
还有一个坑:字符串连接千万别用 + !
a = "10": b = "20"
c = a + b ' 结果是"30"!因为它当成数字相加了
d = a & b ' 正确,结果是"1020"
永远用 & 做字符串拼接,避免意外转换。
🔁 控制结构:模拟真实业务流
真正的测试不是线性执行,而是要覆盖各种分支路径。
条件判断:If vs Select Case
' 多重If容易嵌套过深
If status = "Ready" Then
RunAction "Login"
ElseIf status = "Skip" Then
ExitTestIteration
ElseIf status = "Block" Then
Reporter.ReportEvent micFail, "Blocked", ""
Else
Reporter.ReportEvent micWarning, "Unknown", status
End If
换成 Select Case 更清爽:
Select Case status
Case "Ready"
RunAction "Login"
Case "Skip"
ExitTestIteration
Case "Block"
Reporter.ReportEvent micFail, "Blocked", ""
Case Else
Reporter.ReportEvent micWarning, "Unknown", status
End Select
循环结构:批量处理的基石
| 循环类型 | 用途 |
|---|---|
For...Next | 已知次数,如遍历DataTable |
While...Wend | 条件成立则继续,如等待加载 |
Do...Loop Until | 至少执行一次,适合重试机制 |
经典案例:实现三次重试登录
Dim retry
retry = 0
Do Until Browser("Home").Page("Main").Exist(3) Or retry >= 3
retry = retry + 1
Browser.Refresh
Wait(2)
Loop
If retry >= 3 Then
Reporter.ReportEvent micFail, "Retry Failed", "Still not loaded after 3 attempts"
End If
数据驱动测试:一次编写,无限执行 💡
手工测试10组数据要花1小时?用DDT,10秒搞定。这才是自动化的真正价值。
UFT的数据驱动主要依靠 DataTable 和 外部文件 实现。
📁 从Excel读取测试数据
准备一个 LoginData.xlsx :
| TestCaseID | Username | Password | Expected |
|---|---|---|---|
| TC001 | admin | pass123 | Success |
| TC002 | guest | guest | Failed |
| … | … | … | … |
导入并遍历:
DataTable.ImportSheet "C:\TestData\LoginData.xlsx", "Sheet1", "Global"
For i = 1 To DataTable.GetRowCount
DataTable.SetCurrentRow(i)
username = DataTable("Username", dtGlobalSheet)
password = DataTable("Password", dtGlobalSheet)
expected = DataTable("Expected", dtGlobalSheet)
' 执行登录 & 验证
Call ExecuteLogin(username, password, expected)
Next
你会发现, 测试逻辑只写一遍,数据却可以无限扩展 。新增100条用例?只需往Excel加行即可。
🔄 参数化输出值:构建数据闭环
不仅要输入数据,还要提取结果用于后续验证。
比如下单后获取订单号:
orderID = Browser("Checkout").Page("Receipt").WebElement("OrderNum").GetROProperty("innertext")
DataTable.Value("GeneratedOrder", dtLocalSheet) = orderID
然后把这个 GeneratedOrder 作为参数传给数据库检查点,验证后端是否正确落库。
这就形成了完整的端到端验证链:
UI输入 → 操作执行 → 提取结果 → 写入DataTable → 参数化 → DB验证
🌐 多环境适配:一套脚本跑遍QA/DEV/PROD
不同环境有不同的URL、超时策略、浏览器配置。硬编码进去?迟早会出错。
做法是用XML或INI文件做配置注入:
<!-- config.xml -->
<Config>
<Env name="QA">
<URL>https://qa.app.com</URL>
<Timeout>30</Timeout>
<Browser>Chrome</Browser>
</Env>
<Env name="PROD">
<URL>https://app.com</URL>
<Timeout>15</Timeout>
<Browser>Edge</Browser>
</Env>
</Config>
运行时读取:
Set xml = CreateObject("Microsoft.XMLDOM")
xml.Load("C:\Config\config.xml")
env = Environment.Value("RUN_ENV")
url = xml.SelectSingleNode("//Env[@name='" & env & "']/URL").Text
Browser("MyApp").Navigate url
通过CI变量控制 RUN_ENV ,就能实现“一次提交,多环境冒烟”。
异常处理:让脚本学会“自救” 🛟
网络抖动、弹窗干扰、服务短暂不可用……这些都不是代码的错,但它们会让自动化失败。
UFT提供了两层防御机制:
🛑 Recovery Scenarios:系统级容错
可以在“Recovery Scenario Manager”中定义四类异常响应:
| 触发条件 | 应对措施 |
|---|---|
| 弹窗出现 | 自动点击“确定”关闭 |
| 对象状态异常 | 刷新页面重试 |
| 运行错误 | 记录日志并跳过当前迭代 |
| 应用崩溃 | 重启浏览器继续执行 |
配置完成后保存为 .qrs 文件,并绑定到测试或全局策略。
🐞 On Error Resume Next:精细错误捕获
对于特定操作,建议手动捕获错误:
On Error Resume Next
Browser("Settings").Page("Profile").WebButton("Save").Click
If Err.Number <> 0 Then
Reporter.ReportEvent micFail, "Save Failed", "Err=" & Err.Number & ", " & Err.Description
Err.Clear
End If
On Error GoTo 0
记得最后要用 On Error GoTo 0 恢复默认行为,否则后面的错误会被忽略。
还可以配合FileSystemObject写日志:
Set fso = CreateObject("Scripting.FileSystemObject")
Set log = fso.OpenTextFile("C:\Logs\uft_run.log", 8, True)
log.WriteLine "[" & Now & "] ERROR: " & message
log.Close
总结:通往企业级自动化之路 🚀
UFT的强大之处,从来不只是“录制回放”。当你掌握了对象识别机制、灵活运用关键字驱动、熟练编写VBScript逻辑、并建立起数据驱动框架时,你就已经超越了80%的使用者。
更重要的是,这套方法论完全可以迁移到其他工具中。无论是Selenium+TestNG,还是Playwright+Cucumber,其背后的自动化思想是一致的: 分离关注点、提高复用性、增强稳定性 。
所以别再问“UFT会不会被淘汰”,而应该思考:“我能不能用任何工具搭建出同样可靠的测试体系?”
这才是自动化工程师的核心竞争力。
简介:本教程面向自动化测试初学者,系统讲解HP开发的功能测试工具QTP(现称UFT)的核心概念与实战技能。内容涵盖QTP基础原理、对象识别机制、录制回放技术、VBScript脚本编程、数据驱动测试及智能识别、检查点、事务和恢复场景等高级功能。通过学习本教程,读者将掌握使用QTP构建高效自动化测试流程的方法,并结合TestDirector(ALM)等测试管理工具实现项目级应用,显著提升软件测试效率与质量。
4万+

被折叠的 条评论
为什么被折叠?



