-
揭秘QTP的DeviceReplay对象
2009-02-17 16:50:55
为什么要用DeviceReplay?
有些时候我们需要针对界面做一些指定的动作,例如右键单击一个对象,使用功能键(Fx)来激活某些热键的功能,这时候就可以使用DeviceReplay对象,或者在Object.Set和Object.Type方法不生效时使用DeviceReplay。
并且DeviceReplay在输入特殊符号以及不同语言的文字时会很有用,因为不需要安装指定的字体或改变键盘布局,这对于测试多语言环境的应用程序会非常有用。
在鼠标操作方面,我发现DragDrop方法非常有用,可以使用它来执行拖拽的操作,把一个Item从一个Frame拖动到另外一个Frame,或者在应用程序之间拖动。
Mercury.DeviceReplay对象
Mercury.DeviceReplay对象用于模拟鼠标单击和移动,还有键盘输入等操作。要使用DeviceReplay,你必须确保被测试的应用程序(AUT)是处于激活状态的窗口。如果你想对某个对象执行一项操作,则该对象必须拥有焦点(focus)。对于Windows应用程序,可以使用Activate方法:
Window( "W" ).Activate micLeftBtn
如果想把焦点设置到某个指定的对象上,通常使用Click方法可以完成。
对于Web环境的应用程序,Activate方法不被支持,因此可以使用下面的技巧来完成:
hwnd = Browser( "B" ).GetROProperty( "hwnd" )
Window( "hwnd:=" & hwnd ).Activate micLeftBtn
通常可以使用FireEvent “onfocusin”或object.focus,例如WebEdit(“WE”).Object.focus或WebEdit(“WE”)。FireEvent “onfocusin”。
在调用DeviceReplay对象的方法之前,你需要首先创建DeviceReplay对象:
Set deviceReplay = CreateObject( "Mercury.DeviceReplay" )
Microsoft.VisualBasic.Devices.Keyboard类
为什么我要在介绍DeviceReplay对象之前介绍这个.NET的类呢?DeviceReplay是一个强大的未被文档化的对象,但是有一定的局限性。其中一个局限就是不能判断一个Control键是否已经被按下。在输入一个大写字母之前,我们需要知道CAPS-LOCK键是否已经按下。在使用数字键盘之前我们需要检查NUM-LOCK键是否已经被按下。否则我们在切换键盘输入状态时可能得到的并不是我们想要的状态。
Devices.Keyboard类提供了属性,可用于获取当前的键盘状态,例如当前什么键被按下了,并且提供一个方法用于向激活的窗口发送键盘敲击事件。
几个有用的属性包括:
AltKeyDown - 判断ALT键是否处于按下状态。
CapsLock - 判断CAPS LOCK键是否处于打开状态。
CtrlKeyDown - 判断CTRL 键是否处于按下状态。
NumLock - 判断NUM LOCK键是否处于打开状态。
ScrollLock - 判断SCROLL LOCK键是否处于打开状态。
ShiftKeyDown - 判断SHIFT键是否处于按下状态。
Set Keyboard = DotNetFactory.CreateInstance(
"Microsoft.VisualBasic.Devices.Keyboard", "Microsoft.VisualBasic" )
Print CBool( Keyboard.AltKeyDown )
Print CBool( Keyboard.CapsLock )
Print CBool( Keyboard.CtrlKeyDown )
Print CBool( Keyboard.NumLock )
Print CBool( Keyboard.ScrollLock )
Print CBool( Keyboard.ShiftKeyDown )
注意:在使用DotNetFactory时数据类型必须被转换
System.Windows.Forms.Control 类
DeviceReplay的另外一个局限是不能获取当前鼠标(光标)在屏幕的位置。而System.Windows.Forms.Control这个类定义了那些拥有视觉表现的控件的基类。
通过MousePosition属性可以获取当前鼠标光标在屏幕坐标的位置。访问MousePosition属性时,可以返回代表鼠标光标位置的Point数据。
我的鼠标在哪?
Set ctlr = DotNetFactory.CreateInstance("System.Windows.Forms.Control")
For i = 1 To 10
Wait 2
Print "1. X=" & ctlr.MousePosition.X & "; Y=" & ctlr.MousePosition.Y
Next
Mercury.DeviceReplay的方法
SendString方法
描述
向激活的窗口发送一个或多个键盘按键,就像敲击键盘一样。
语法
object.SendString( str )
参数
object : Mercury.DeviceReplay对象。
str : 敲击的字符串。
返回值
无。
例子
下面的例子会激活记事本(notepad)并输入一段字符:
Set deviceReplay = CreateObject( "Mercury.DeviceReplay" )
SystemUtil.Run "notepad.exe", "", "", "open"
' ** this line always identifies the notepad window.
Window( "nativeclass:=Notepad", "index:=0" ).Activate micLeftBtn
deviceReplay.SendString( "DeviceReplay" )
Set deviceReplay = Nothing
KeyDown方法
描述
模拟一个按键的按下并保持(相当于Win32的KEY_DOWN事件)。
语法
object.KeyDown( key )
参数
object : Mercury.DeviceReplay对象。
key : 按键的数值码。可查阅后面的“Key Codes 参考”。
返回值
无。
例子
下面的例子会激活记事本(notepad)程序并使用大写和小写的方式输入字符串。注意在发送第一个字符串时,SHIFT键保持被按下的状态:
Const VK_SHIFT = 42
Const VK_RETURN = 28
Set deviceReplay = CreateObject( "Mercury.DeviceReplay" )
SystemUtil.Run "notepad.exe", "", "", "open"
Window( "nativeclass:=Notepad", "index:=0" ).Activate micLeftBtn
' ** Typing uppercase
deviceReplay.KeyDown VK_SHIFT
deviceReplay.SendString( "devicereplay" )
deviceReplay.PressKey VK_RETURN
deviceReplay.KeyUp VK_SHIFT
' ** Typing in lower case
deviceReplay.SendString( "devicereplay" )
Set deviceReplay = Nothing
提示
在KeyDown后应该有相应的KeyUp方法的调用。
KeyDown方法就像人工按下一个按键并保持按下的状态。
KeyUp方法
描述
模拟通过键盘释放某个按下的按键。
语法
object.KeyUp( key )
参数
object : Mercury.DeviceReplay对象。
key : 按键的数值码。可查阅后面的“Key Codes 参考”。
返回值
无。
例子
下面的例子会激活并并使用热键CTRL+O来打开记事本(notepad)的菜单,然后用ESC键关闭对话框。
Const VK_O = 24
Const VK_CONTROL = 29
Const VK_ESCAPE = 1
Set deviceReplay = CreateObject( "Mercury.DeviceReplay" )
SystemUtil.Run "notepad.exe", "", "", "open"
Window( "nativeclass:=Notepad", "index:=0" ).Activate micLeftBtn
' ** Typing uppercase
Wait 1
' ** Opening the menu Ctrl + O
deviceReplay.KeyDown VK_CONTROL
deviceReplay.PressKey VK_O
deviceReplay.KeyUp VK_CONTROL
Wait 2
' ** Closing the menu
deviceReplay.PressKey VK_ESCAPE
deviceReplay.SendString "Menu Open, was closed."
Set deviceReplay = Nothing
提示
KeyUp方法应该与KeyDown方法配对使用。
多个KeyUp不会对应用程序造成影响。
如果需要组合热键,仅需要像人工执行的方式一样即可。
PressKey方法
描述
模拟通过键盘按下一个按键并立即释放。
语法
object.PressKey( key )
参数
object : Mercury.DeviceReplay对象。
key : 按键的数值码。可查阅后面的“Key Codes 参考”。
返回值
无。
例子
下面的例子会激活记事本并使用热键CTRL+O来模拟选择文件打开菜单,然后用ESCAPE按键关闭对话框。
Const VK_O = 24 : Const VK_F = 33
Const VK_CONTROL = 29 : Const VK_ESCAPE = 1 : Const VK_MENU = 56
Set deviceReplay = CreateObject( "Mercury.DeviceReplay" )
SystemUtil.Run "notepad.exe", "", "", "open"
Window( "nativeclass:=Notepad", "index:=0" ).Activate micLeftBtn
Wait 1
' ** Opening the menu Alt + F + O
deviceReplay.PressKey VK_MENU
deviceReplay.PressKey VK_F
deviceReplay.PressKey VK_O
Wait 2
' ** Closing the menu
deviceReplay.PressKey VK_ESCAPE
deviceReplay.SendString "Open menu was closed."
Set deviceReplay = Nothing
PressNKeys方法
描述
模拟通过键盘多次按下一个按键并立即释放。
语法
object.PressNKey( key, N )
参数
object : Mercury.DeviceReplay对象。
key : 按键的数值码。可查阅后面的“Key Codes 参考”。
N:重复的次数。
返回值
无。
例子
例1 – 美国的州
Option Explicit
Const VK_RETURN = 28 : Const VK_F = 33 : Const VK_O = 24
Const VK_TAB = 15 : Const VK_F5 = 63
Const VK_CAPITAL = 58 : Const VK_NUMLOCK = 69
Const VK_SUBTRACT = 74 : Const VK_MULTIPLY = 55
Const VK_MENU = 56
Dim deviceReplay
Private Sub SetupKeyboard()
Const CLASS_NAME = "Microsoft.VisualBasic.Devices.Keyboard"
Const ASSEMBLY = "Microsoft.VisualBasic"
Dim Keyboard
Set Keyboard = DotNetFactory.CreateInstance( CLASS_NAME, ASSEMBLY )
If CBool( Keyboard.CapsLock ) Then
deviceReplay.PressKey VK_CAPITAL
End If
If CBool( Keyboard.NumLock ) = False Then
deviceReplay.PressKey VK_NUMLOCK
End If
Set Keyboard = Nothing
End Sub
Private Sub SetupNotepad()
deviceReplay.PressKey VK_MENU
deviceReplay.PressKey VK_O
deviceReplay.PressKey VK_F
deviceReplay.SendString "Courier New"
deviceReplay.PressKey VK_TAB
deviceReplay.PressKey VK_TAB
deviceReplay.SendString "14"
deviceReplay.PressKey VK_RETURN
Wait 1
End Sub
Private Sub PrintRow( ByVal state, ByVal usps, byVal capital )
deviceReplay.SendString state
deviceReplay.PressKey VK_TAB
If Len( state ) < 8 Then
deviceReplay.PressKey VK_TAB
End If
deviceReplay.SendString usps
deviceReplay.PressKey VK_TAB
deviceReplay.SendString capital
deviceReplay.PressKey VK_RETURN
End Sub
Set deviceReplay = CreateObject( "Mercury.DeviceReplay" )
SystemUtil.Run "notepad.exe", "", "", "open", 3
Window( "nativeclass:=Notepad", "index:=0" ).Activate micLeftBtn
' ** Setup Notepad - Font courier new, size 14,
' ** NUM-LOCK pressed and CAPS-LOCK unpressed
Call SetupKeyboard()
Call SetupNotepad()
' ** inserting date
deviceReplay.PressKey VK_F5
deviceReplay.PressKey VK_RETURN
' ** Inserting Title
deviceReplay.PressNKeys VK_TAB, 3
deviceReplay.SendString "
QTP识别和操作对象的原理
2009-02-17 16:49:14
转自51论坛网友yabest的文章.
呵呵,这个文章本来是在给别人的帖《GetROProperty,GetTOProperties,GetTOProperty的区别 》回复时写的,没有独立出来。
http://bbs.51testing.com/viewthread.php?tid=13554&page=1#pid369327
写完后,在网上被多处转载。没想到今天又被转贴回51testing来了。虽然在精华版里,也赚了几朵花,但没独立总是不方便。所以修整了一下,独立成帖,以方便大家阅读。
欢迎大家拍砖!(当然更欢迎大家送花sdlkfj5)
一、QTP识别对象的原理(by yabest,http://www.yabest.net)QTP里的对象有两个概念,一个是Test Object(简称TO),一个是Runtime Object(简称RO)。
这两个概念从字面上不大好理解,也容易混淆。
但从实际作用上来看,应该说TO就是是仓库文件里定义的仓库对象,RO是被测试软件的实际对象。QTP识别对象,一般是要求先在对象仓库文件里定义仓库对象,里面存有实际对象的特征属性的值。
然后在运行的时候,QTP会根据脚本里的对象名字,在对象仓库里找到对应的仓库对象,
接着根据仓库对象的特征属性描述,在被测试软件里搜索找到相匹配的实际对象,最后就可以对实际对象进行操作了。仓库对象TO一般在录制/编写脚本时加入仓库文件,它不仅可以在录制编写时进行修改,
也可以在运行过程中进行动态修改,以匹配实际对象。和TO、RO相关的几个函数有:
GetTOProperty():取得仓库对象的某个属性的值
GetTOProperties():取得仓库对象的所有属性的值
SetTOProperty():设置仓库对象的某个属性的值GetROProperty():取得实际对象的某个属性的值
理解了TO的含义,你就可以自由的用SetTOProperty()定义TO,以灵活的操作RO比如有个测试任务,窗口上有很多待检查的记录,每条记录右边都有一个Check按钮,用来检查各条记录。
记录个数不定,所以Check按钮个数也就不定,只有一个Edit显示记录个数。
我们要对每条记录进行检查,也就是要点击每个Check按钮。
但是Check按钮个数不定,不好录制,而且个数可能也很多(上百个),即使能一一录制,那也很麻烦。那我有一个好办法,只录制一个按钮对象,它设有两个特征属性 label=OK, index=0
然后用下面的脚本,就可以完成测试buttonNum = CInt(JavaWindow("Test").JavaEdit("Record Num").GetROProperty("value"))
For buttonIndex = 0 to buttonNum - 1
JavaWindow("Test").JavaButton("Check").SetTOProperty("index", buttonIndex)
JavaWindow("Test").JavaButton("Check").Click
Next
或者窗口上有New、Modify、Delete、Check等好几个按钮,要把这几个按钮一一按过去
我在对象仓库里只设置一个按钮对象AnyButton,label特征属性值填任意值,然后用下面脚本执行测试JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "New")
JavaWindow("Test").JavaButton("AnyButton").ClickJavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "Modify")
JavaWindow("Test").JavaButton("AnyButton").ClickJavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "Delete")
JavaWindow("Test").JavaButton("AnyButton").ClickJavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "Check")
JavaWindow("Test").JavaButton("AnyButton").Click另外,QTP还支持脚本描述的方法来定义和访问对象,即不需要在仓库里定义,也能访问和操作实际对象
( Written by yabest,http://www.yabest.net)如上面两个任务,可以如下实现
1. 不需要在仓库里定义Check按钮对象,直接用下面脚本来实现测试
buttonNum = CInt(JavaWindow("Test").JavaEdit("Record Num").GetROProperty("value"))
For buttonIndex = 0 to buttonNum - 1
JavaWindow("Test").JavaButton("label:=Check", "index:="+CStr(buttonIndex)).Click
Next2. 不需要在仓库里定义New、Modify、Delete、Check按钮对象,直接用下面脚本来实现测试
JavaWindow("Test").JavaButton("label:=New").Click
JavaWindow("Test").JavaButton("label:=Modify").Click
JavaWindow("Test").JavaButton("label:=Delete").Click
JavaWindow("Test").JavaButton("label:=Check").Click二、QTP操作对象的原理(by yabest,http://www.yabest.net)
QTP为用户提供了两种操作对象的接口,一种就是对象的封装接口,另一种是对象的自身接口。
对象的自身接口是对象控件本身的接口,只要做过软件开发,使用过控件的人应该很清楚。
对象的封装接口是QTP为对象封装的另一层接口,它是QTP通过调用对象的自身接口来实现的。
两种接口的脚本书写格式的差别在于:
自身接口需要在对象名后面加object再加属性名或方法名,
封装接口就不用在对象名后面加object。具体格式如下:
对实际对象的操作:
对象.object.自身属性
对象.object.自身方法()
对象.GetROProperty("封装属性")
对象.封装方法()对仓库对象的操作:
对象.GetTOProperty("封装属性")
对象.GetTOProperties() ’获取所有封装属性的值
对象.SetTOProperty("封装属性", "封装属性值")比如操作JavaEdit对象,通过QTP封装的封装接口,脚本如下:
设置JavaEdit的内容:
JavaDialog("Add NE").JavaEdit("NE Name").Set "NE1"
读取JavaEdit的内容:
msgbox JavaDialog("Add NE").JavaEdit("NE Name").GetROProperty("value")如果通过JavaEdit的自身接口,脚本如下:
设置JavaEdit的内容:
JavaDialog("Add NE").JavaEdit("NE Name").object.setText("NE1")
读取JavaEdit的内容:
Msgbox JavaDialog("Add NE").JavaEdit("NE Name").object.getText()QTP执行JavaEdit().Set语句时,是通过执行JavaEdit().object.setText()来实现的。
QTP执行JavaEdit().GetROProperty("value"),是通过执行JavaEdit().object.getText()来实现的。
JavaEdit对象的封装接口Set()和GetROProperty("value"),是QTP封装JavaEdit对象的自身接口setText()和getText()而得来的。对象的封装接口是QTP使用的缺省接口,我们录制出来的脚本都是使用封装接口,大家用的也都是封装接口。
但是封装接口不如自身接口丰富,因为QTP只是封装了部分常用的自身接口嘛。
所以我们在需要时,可以绕过封装接口,直接调用对象的自身接口。
不过有些自身接口不够稳定,在实践中偶尔会出现问题,但是概率很少。
封装接口有相应功能的话,就尽量用封装接口吧!
( Written by yabest,http://www.yabest.net)理解了封装接口和自身接口的原理,我们就可以更加灵活的操作对象了。
但是我们怎么知道对象都有哪些封装接口和自身接口呢?
其实很简单,用对象查看器(Object Spy)查看对象,在查看窗口里有列出这些接口,包括属性和方法。
窗口中间有选择栏让你选择Run-time Object或者Test Object,
当你选择Runtime Object时,它显示的就是对象的自身接口(自身的属性和方法)
当你选择Test Object时,它显示的就是对象的封装接口(封装的属性和方法)(注意:GetROProperty访问的是实际对象的封装接口,GetTOProperty访问的是仓库对象的封装接口,
两者访问的都是对象的封装接口,即Object Spy窗口里选Test Object时显示的属性。
不要以为GetROProperty访问的是自身接口,即Object Spy窗口里选Run-time Object时显示的属性。
QTP里的Test Object/Run-time Object的概念太容易让人混淆了!
它既用来区分仓库对象和实际对象,又用来区分对象的封装接口和自身接口。
)
明白了这些,你还等什么呢?快拿起对象查看器,看看对象都有哪些封装接口和自身接口,肆意的操作它,玩弄它吧!比如执行
JavaDialog("Add NE").JavaEdit("NE Name").object.setVisible(false)
哈哈,你的JavaEdit对象就当场消失不见了!!!你可以拿这个做恶作剧,指着这个窗口逼问开发人员,JavaEdit对象哪去了?
模拟鼠标右键
2008-10-21 12:04:56
Set x = createobject("wscrīpt.shell")
cur_replay_type = Setting.WebPackage("ReplayType")
Setting.WebPackage("ReplayType") = 2
browser("Google").Page("Google").WebEdit("q").Click ,,micRightBtn
For i = 1 to 4
wait(1)
x.sendkeys "{DOWN}"
Next
x.sendkeys "{ENTER}"
Set x = nothing
Setting.WebPackage("ReplayType") = cur_replay_type
'browser("Google").Page("Google").WebEdit("q").Click ,,2IE浏览器的最大最小化
2008-10-21 11:57:31
'Open an IE browser with the method CreateObject()
Dim objIE, hwndIE
Set ōbjIE = CreateObject("internetexplorer.application")
objIE.Visible = true
objIE.Navigate "http://www.google.cn" 'The parameter URL is the destination address for the IE browser'Wait a while till the page is fully loaded
Wait(10)'Move and resize the browser
hwndIE = objIE.HWND
'Operate the IE browser as a window object with descrīptive programming
'The window object can be uniquely identified by the parameter hwndIE, which is the window's handle of the browser
'Window ("hwnd:=" & hwndIE).Minimize
Window ("hwnd:=" & hwndIE).Maximize'Release the object after the adjustment
Set ōbjIE = nothingDeviceReplay对象使用
2008-08-14 11:49:27
Function Mouse_Click(x , y)
Dim device
Set MouseObject = CreateObject("Mercury.DeviceReplay")
MouseObject.MouseMove x , y
MouseObject.MouseClick x , y , LEFT_MOUSE_BUTTON
End FunctionDeviceReplay很实用的一个对象
这个对象用来模拟鼠标的单击和移动、键盘输入等,但有个前提,实用该对象前,需要保证键盘状态正确
如NUMLOCK是否打开等,因为DeviceReplay不能检测键盘状态
Mercury.DeviceReplay方法如下:
1、SendString方法
向激活的窗口发送一个或多个键盘按键:object.SendString( str )
2、KeyDown方法
模拟一个按键的按下并保持:object.KeyDown( key ) key : 按键的数值码
3、KeyUp方法
模拟通过键盘释放某个按下的按键:object.KeyUp( key )
4、PressKey方法
模拟通过键盘按下一个按键并立即释放:object.PressKey( key )
5、PressNKeys方法
模拟通过键盘多次按下一个按键并立即释放:object.PressNKey( key, N ) N:重复次数
6、DragAndDrop方法
用于执行从一点拖动到另外一点的操作:object.DragAndDrop( dragX, dragY, dropX, dropY, Button )
Button 的值包括
LEFT_MOUSE_BUTTON = 0
MIDDLE_MOUSE_BUTTON = 1
RIGHT_MOUSE_BUTTON = 2
7、MouseClick方法
在指定的屏幕位置执行鼠标左键或右键的单击操作:object.MouseClick( x, y, Button )
8、MouseDbClick方法
在指定的屏幕位置中执行鼠标左键或右键的双击事件:object.MouseDblClick( x, y, Button )
9、MouseDown方法
在屏幕指定位置按下鼠标左键或右键,并保持按下状态:object.MouseDown( x, y, Button )
10、MouseUp方法
用于释放之前执行的MouseDown方法所按下的鼠标按键:object.MouseDown( x, y, Button )
11、MouseMove方法
用于模拟鼠标移动:object.MouseMove( x, y)
12、SetSynchronizationTimeout方法
设置一个新的同步超时的时间值:object. SetSynchronizationTimeout(nSyncTimeout , is_sec)
nSyncTimeout : 同步超时的时间值。
is_sec : 指定设置的时间值是否以秒为单位
标题搜索
我的存档
数据统计
- 访问量: 4195
- 日志数: 8
- 建立时间: 2007-03-16
- 更新时间: 2009-03-14