Meir Bar-Tal给我们展现了用VBS的类实现面向对象的QTP自动化测试框架:
http://www.advancedqtp.com/knowledge-base/articles/qtp-tricks4/descriptive-programming/implementing-a-gui-layer-with-classes/
这种框架的核心思想是把某个窗口的测试对象和相关业务核心操作都封装在VBS的类中,称之为GUI层,或者叫GUI-业务桥接层。例如下面的登录界面类:
' 登录界面类,封装了界面对象数据以及相关业务操作
Class Login
Private m_htChildObjects 'As Scripting.Dictionary
Public Property Get ChildObjects()
Set ChildObjects = m_htChildObjects
End Property
Public Property Let ChildObjects(ByRef dic)
Set m_htChildObjects = dic
End Property
' 初始化界面对象并验证对象是否存在
Public Function Init()
ChildObjects = CreateObject("Scripting.Dictionary")
With ChildObjects
.Add "LoginDialog", Dialog("text:=Login")
.Add "AgentName", ChildObjects.Item("LoginDialog").WinEdit("attached text:=Agent Name:")
.Add "Password", ChildObjects.Item("LoginDialog").WinEdit("attached text:=Password:")
.Add "Submit", ChildObjects.Item("LoginDialog").WinButton("text:=OK")
End With
'IsContextLoaded is a function that iterates through the Dictionary and checks if the GUI objects "exist"
Init = IsContextLoaded(ChildObjects) ' 检查界面层对象是否存在
End Function
' 与界面对象绑定的各类业务操作
' 测试数据从GlobalDictionary中获取(放在Data层),这里把测试数据做成函数参数可能会更好?!
Public Function SetUsername()
ChildObjects.Item("AgentName").Set GlobalDictionary.Item("AgentName")
End Function
Public Function SetPassword()
ChildObjects.Item("Password").Set GlobalDictionary.Item("Password")
End Function
Public Function Submit()
ChildObjects.Item("Submit").Click
End Function
End Class
Public Function CreateLogin()
Dim objLogin
Set objLogin = New Login
Set CreateLogin = objLogin
End Function
在业务层的类中封装业务操作流程的代码,例如下面的登录流程:
' 登录业务类,封装了登录过程的业务操作流程
Class do_login
Public Default Function Run()
Dim intStatus
Set objLogin = CreateLogin() ' 调用GUI层的Login类
If objLogin.Init() Then ' 如果所需的界面对象都存在,则执行业务操作流程
objLogin.SetUsername()
objLogin.SetPassword()
objLogin.Submit()
intStatus = micPass 'If login succeeds
Else
intStatus = micFail
End If
Run = intStatus
End Function
End Class
Public Function Create_do_login()
Dim bzLogin
Set bzLogin = New do_login
Set Create_do_login = bzLogin
End Function
这种写法的好处,除了可以细粒度地抽象、分解业务的测试代码,提高可重用性外,还可以在业务层的代码执行前,先让界面层检查验证所需的测试对象是否都存在( 例如上面代码中的objLogin.Init() ),避免了QTP在运行过程中碰到对象不存在的时候卡住的现象。
在界面层的Init方法中,通过描述性编程把测试对象都存入Dictionary中,然后用IsContextLoaded方法遍历对象,检查是否在运行时都存在:
' 检查界面层对象是否存在并写入测试报告
Public Function IsContextLoaded(ByRef htContext)
Dim ix, items, keys, strDetails, strAdditionalRemarks
IsContextLoaded=true
items = htContext.Items
keys = htContext.Keys
For ix = 0 To htContext.Count-1
IsContextLoaded = IsContextLoaded And items(ix).Exist(0)
strDetails = strDetails & vbNewLine & "Object #" & ix+1 & ": '" & keys(ix) & "' was"
If IsContextLoaded Then
intStatus = micPass
strDetails = strDetails & ""
strAdditionalRemarks = ""
Else
intStatus = micWarning
strDetails = strDetails & " not"
strAdditionalRemarks = " Please check the object properties."
End If
strDetails = strDetails & " found." & strAdditionalRemarks
Next
Reporter.ReportEvent intStatus, "IsContextLoaded", strDetails
End Function