-
QTP编码问题
2008-07-16 13:57:58
by jiale
前段时间有个同学问我他在记事本里编辑的QTP代码文件scrīpt.mts,在QTP里打开是乱码了,当时想到之前使用executefile方法执行vbs时出现“非法字符”错误是由于vbs文件非ANSI编码造成的。
因此尝试将scrīpt.mts用记事本打开,并保存为ANSI编码格式,再用QTP打开,一切OK。
-
watir中,类似QTP object spy等方法替代实行
2008-07-06 23:57:01
by Wiston Li
我们知道,QTP提供object spy工具,对象库录制功能,或描述性编程提供给我们快捷识别对象,
一定程度上可以做到脚本批处理生成。相应的,我在想如此好的工具和技术,为啥watir没有支持?
也许将来,在自动化同学与watir开发团队努力下,可满足这一需求。另一个问题抛出,是否为了准备watir脚本,我们一定要在那么冗长的代码,查找并挑选我们想要操作的对象?
给出我的简单总结,1, 类似object spy工具,为微软为开发人员做的工具ie developer toolbar,可以借助它通过指针指示
对象,在attribute view中找到相应属性。2,类似描述性编程,
在cmd中运行irb,
如: puts 2+2
打印4,可以通过命令实现所见即所得,如:
require ‘watir’
ie=Watir::IE.start(‘http://localhost:8080’)
ie.show_all_objects结果:
-----------Objects in page -------------
text name=name id=如:ie.text_field(:name, 'name').flash
结果:使操控对象webedit框有黄色闪动效果.
更有意思的是,当我把鼠标焦点移到某个webedit上,
然后:
irb> puts ie.show_active
text name=name
id= value=
alt= src=
innerText=
=> nil
在这里,watir将帮助我们标识当前active的对象.
对于button和其他对象,也可以通过tab key来实现焦点移动,
再用alt + tab 激活irb窗口,用相同show active方法实现.再如:
irb> puts ie.show_active
submit name=submit_logon
id= value=Login
alt= src=
innerText=
=> nil
irb> ie.text_field(:name, 'name').set(‘Test1’)
=> nil可以参照watir api对web edit对象进行内容清除,追加等.
另外可以输出当前IE对象的HTMLirb> puts ie.html
<H1>
<P align=center>Create the First Job </P></H1>
<TABLE cellSpacing=0 cellPadding=3 border=0>
<TBODY>
<TR>
<TD align=middle width="40%">
<FORM id=job name=job action=job method=get><INPUT type=hidden value=22909012 name=session></INPUT>
<TABLE cellSpacing=0 cellPadding=3 border=0>
<TBODY>或只输出text :
irb> puts ie.text
Create the First Job
Please create the first jobMake it a background job
If you make this job a background job, it will be a job that accumulates time when you're not doing any specific task. You'll start it in the morning,
do your work - starting and pausing other jobs - then stop it when you're done for the day.
Each time you pause another job, the background job will resume accumulating time.
If you don't have a background job, you'll have to manage time more explicitly.
=> nil
irb(main):024:0>
对于页面中只有一个同特征对象时可以用index, 如:
ie.text_field(:index, 1).set(‘Testing for Bugs’)irb> ie.button(:index,1).click
=> nil可以借用show_all_objects方法显示页面中所有对象
也可以显示某一特定类型对象, 像:
show_images Show all the images in the document
show_spans Show all the span tags in the document
show_labels Show all the labels in the document
show_links Show all the links in the document
show_divs Show all the div tags in the document
show_frames Show all the frames in the document
show_forms Show all the forms in the document如这里用ie.show_table作为示例
irb> ie.show_tables
Found 8 tables
1 id= rows=1 columns=3
2 id= rows=2 columns=1
3 id= rows=3 columns=1
4 id= rows=2 columns=1
5 id= rows=3 columns=1
6 id= rows=1 columns=1
7 id= rows=3 columns=1
8 id=recent_records rows=2 columns=1
=> nil我们可用flash方法来标识对象,
irb> ie.table(:id , ‘recent_records’).flash也可以只显示特定table的html code,
irb> puts ie.table(:id , ‘recent_records’).html
<TABLE id=recent_records cellSpacing=0 cellPadding=3 width="66%" align=center border=1><TBODY>
<TR bgColor=#66ffff>
<TD align=middle colSpan=4>Recent Records </TD></TR>
<TR bgColor=#ccffff>
<TD>Testing for Bugs </TD>
<TD>10:05 PM </TD>
<TD>0.00 hours </TD>
<TD><B>running</B> </TD></TR></TBODY></TABLE>这里可用ruby内置函数 to_a输出行记录数组,
irb> irb(main):009:0> my_array = ie.table(:id , 'recent_records').to_a
=> [["Recent Records"], ["Testing for Bugs", "10:05 PM",以上可以看到,采用 show_XXX方法,枚举同特征对象,
是否感觉到类似QTP:create descrīption.../ mic class='web object'/...的方法?类似,甚至可以通过修改底层show_XXX代码,来批处理生成脚本,
如生成已经填值的text field操作脚本,呵呵...
-
如何破解快速变化的web网站测试自动化困境?
2008-07-05 19:09:47
by liangjz
网站业务复杂度倍增,为了改善由于开发改动一点内容,而QA需要大面积验证相关受影响的模块导致
工作量剧增的状况,故引入网站自动化测试。
目前针对网站主干流程核心业务做了粗粒度的验证。技术: qtp + 页面验证 + 数据库验证,业务流
采用excel管理。 运行了一段时间,发现了一些BUG(自动化目的不是找BUG,而是一种质量保证手段)
,但更多的问题也引爆出来.
经过和微软技术专家的交流,产品线的自动化测试特征如下:
1) 微软强调单元级的验证粒度非常细致
2) 微软强调每一个业务模块的数据输入都是全新创建而非利用系统原有数据;自动化退出时环境RESET
我们问题主要集中在几块
1) 业务经常变更,导致页面元素发生变化,需要及时调整自动化脚本。这个成本居高不下
2) 自动化采用的脚本是依赖数据库原有的定制化的数据,有时候被QA测试时修改,干扰脚本运行。
但如果全新创建,需要跨别的系统且需要人工审核的环节,这个成本也很高昂
3) 目前的验证点粒度比较少, 但如果页面验证点颗粒很细,大多数时候页面元素不发生变化,这种验证效用大么?验证点增加也会带来脚本运行速度下降,维护成本增强等问题
4) 自动化测试脚本主要用于项目发布前的回归验证。没有用到项目测试中,原因有需要更换一批新的数据、脚本需要更快速和业务变化同步等
不知道其他业务型的互联网公司如何运作,让自动化脚本最大化发挥功效的?
目前开发尚无单元测试代码,无法做到daily test。而开发没有清晰的API接口说明,开发和测试的工
作边界不够清晰导致测试无法写单元测试。
-
自动化中特殊对象的变通处理
2008-07-03 08:47:41
by jiale
在做自动化项目中碰到了怪异的对象,它是一个第三方提供的控件,被QTP识别为winobject,对操作进行录制结果是click了控件上的一个坐标:Window("").Window("").Page("").Frame("Frame").WinObject("ActiveX").Click 388,9,显然由于坐标受到页面大小的影响,成功回放几乎变成不可能,这有什么办法可以解决呢,我们发现可以使用tab键使控件得到焦点,于是想到了使用SendKeys,首先定位到可识别的对象使其获得焦点,然后SendKeys tab键使光标移动到需要输入的控件,再用SendKeys输入想输入的字符,ok,一切变得简单了
好了,下面是SendKeys的使用方法
Dim oWinApp
Set ōWinApp=createobject("Wscrīpt.Shell")
oWinApp.sendkeys InputText
Set ōWinApp = nothing键盘给特殊键对应的入参
Key Argument
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL or DELETE {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER} or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS or INSERT {INSERT} or {INS}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1 {F1}
F2 {F2}
F3 {F3}
F4 {F4}
F5 {F5}
F6 {F6}
F7 {F7}
F8 {F8}
F9 {F9}
F10 {F10}
F11 {F11}
F12 {F12}
F13 {F13}
F14 {F14}
F15 {F15}
F16 {F16}
-
[论坛] 获取页面上所有指定属性的对象
2008-06-17 17:00:45
by jack
在QTP脚本编写的时候,我们可能会遇到这种检查点:比如获取checkbox的个数等等,这时会提出“获取页面上所有指定属性的对象”的需求。下面是用descrīption对象实现的一个函数,作用就是实现上述需求。
Function getItemList(PageObject,PropertyName,PropertyValue)
Dim oItemDesc
Dim nSet ōItemDesc=descrīption.Create
If isarray(PropertyName) and isarray(PropertyValue) Then
Dim iCountPropertyName
Dim iCountPropertyValue
iCountPropertyName = ubound(PropertyName)
iCountPropertyValue = ubound(PropertyValue)If iCountPropertyName <= iCountPropertyValue Then
For n=0 to ubound(PropertyName)
oItemDesc(PropertyName(n)).value=PropertyValue(n)
Next
Else
'lost property value
'msgbox "lost property value"
Exit Function
End If
Else If (not isarray(PropertyName)) and (not isarray(PropertyValue)) Then
oItemDesc(PropertyName).value=PropertyValue
Else
'error
'msgbox "error"
Exit Function
End If
End IfSet getItemList=PageObject.childobjects(oItemDesc)
End Function
输入参数有3个,page对象,属性名,属性值;其中属性名和属性值可以为数组,应用举例:
'取出页面所有编辑框
set ōChildList = getItemList(page("51Testing软件测试网"),"micclass","WebEdit")
'编辑框数量
iCountChildList = oChildList.count
'取出页面所有name含有“测试”的链接
set ōChildList = getItemList(page("51Testing软件测试网"),array("micclass","name"),array("Link","测试.*"))'点击第二个链接
oChildList(1).click
-
对象识别怪现象
2008-06-06 09:34:52
by jiale
最近在做中文站自动化脚本时,碰到了一个奇怪的现象,是一个image对象,用qtp的object spy获取这个对象的filename属性用来识别它,但回放的时候总是提示无法识别该对象,filename属性是可以用来作为识别image对象的唯一属性的,而且这个页面也只有一个image对象,相当的奇怪呀,多次用object spy抓取时发现,抓取前与抓取后的filename是不一致的,赶紧打开源代码看看缘由,原来该对象的onmouse事件将这个对象的图片source给改变了,当鼠标移到该对象时,改变图片A为图片B,因此object spy抓取的filename属性是图片B,而回放时并没有onmouse为图片A,当然用图片B作为识别属性就无法识别该对象,只有用(filename:=图片A)才能正常识别。
-
使用ADO查询Oracle中文乱码问题
2008-06-06 09:34:20
by jiale
QTP做自动化脚本,用MS ADO对象操作数据库的时候,发现一个奇怪的问题,查询中带有中文时如:select count(*) from xxx where xxx like '中文%',查询失败,有数据也返回0,同样insert语句插入中文时乱码,初步判断是客户端字符集的问题,当前使用的客户端字符集与服务器端不匹配,select * from V$NLS_PARAMETERS WHERE parameter = 'NLS_CHARACTERSET'查询,发现服务器端为US7ASCII,查看客户端注册表HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE下NLS_LANG键值为NA,而HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0下NLS_LANG键值为AMERICAN_AMERICA.us7ascii,统一修改为AMERICAN_AMERICA.us7ascii,以为问题解决,可是查询仍然失败。
后来想到我们使用前面讲到的OraOleDb.Oracle字串链接数据库,那是不是OraOleDb.Oracle与MS的ADO配合有问题呢?我们将OraOleDb.Oracle改成MS的MSDAORA,查询一切ok。
因此这个中文乱码是两个错误的叠加,1、客户端没有使用正确的字符集——修改注册表ORACLE字符集,2、ADO的数据库连接没有使用正确的容器——MS的ADO就使用MS提供的MSDAORA数据库连接。 -
利用wshell.exec方法执行命令信息交互
2008-06-04 20:57:15
By Wiston Li
自动化通常碰到cmd执行窗口,可以用qtp的操作对象的方法控制窗口,并取到命令执行后返回的文本,
如:
Syntax : object.GetVisibleText ([Left], [Top], [Right], [Bottom])
但当命令返回多于一屏时,此命令就不行了,可以用下面的替代方法来解决:
Option Explicit
Const SystemFolder = 1
Dim wShell, exec, fso
Dim dirList
Set wShell = CreateObject( "Wscrīpt.Shell" )
Set fso = CreateObject("scrīpting.FileSystemObject")
dirList = fso.GetSpecialFolder( SystemFolder ) & "\*.exe"
Set exec = wShell.Exec( "%comspec% /C dir " & dirList & " /B /O-N /L" )
Do While True
If Not exec.StdOut.AtEndOfStream Then
dirList = exec.StdOut.ReadAll
If exec.ExitCode = 1 then
Reporter.ReportEvent micWarning, "Command failed", dirList
End If
Exit Do
End If
If Not exec.StdErr.AtEndOfStream Then
dirList = "STDERR: " & exec.StdErr.ReadAll
Reporter.ReportEvent micFail, "Command failed", dirList
Exit Do
End If
Wait 1
Loop
Print dirList
-
解压缩文件到目标目录
2008-06-04 20:51:47
by Wiston Li
解压文件
Dim sZIPFile
Dim sExtractToPath
Dim oShell
Dim oZippedFiles
sZIPFile="d:\bid.zip"
sExtractToPath="d:\temp"
Set ōShell = CreateObject("Shell.Application")
'取到zip包中的内容
Set ōZippedFiles=oShell.NameSpace(sZIPFile).items
' 释放到目标目录
oShell.NameSpace(sExtractToPath).CopyHere(oZippedFiles)
' 释放对象
Set ōZippedFiles = Nothing
Set ōShell = Nothing -
压缩文件到某个zip文件中
2008-06-04 20:49:07
by Wiston Li
通常,为了传送与保存大文件时,可以考虑打包到zip的方法,
'变量定义
Dim sSourceFolder
Dim sArchiveFile
Dim oShell
Dim oZIP
Dim oSourceFolder
'初始化sSourceFolder = "d:\bid"
sArchiveFile = "d:\bid.zip"
set ōShell = CreateObject("Shell.Application")
'建立zip对象,namespace是oshell内置对象
Set ōZIP= oShell.NameSpace(sArchiveFile)
'得到源目录
Set ōSourceFolder=oShell.NameSpace(sSourceFolder)'加文件到zip包中。
oZIP.CopyHere(oSourceFolder.Items) -
用CDO对象发邮件
2008-06-04 20:44:21
By wiston Li
今天,开始和大家分享一下,基于windows scrīpting tips,
此类小知识,可能在大家准备自动化脚本时碰到,有些windows开放的com对象,应用到自动化测试中
特别时调用com对象内置的方法与属性,能起到事半功倍的作用。
在这里整理一下:
Function sendmailbysmtp(Mailto, FilePath)
Dim objEmail
Set ōbjEmail = CreateObject("CDO.Message")
objEmail.From = "B2bTA@b2btest.com"
objEmail.To = Mailto
objEmail.Subject = "This is an email sent by TA"
objEmail.Textbody = "Pls see the enclosed for the TA execution log"objEmail.AddAttachment (FilePath)
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = _
"10.0.32.124"
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Update
objEmail.Send
End Function这个函数,也是我们现在自动化框架用到的发邮件,
另外,也除了发送txt文本格式的邮件,也可以发送基于html格式的,详见:
Set ōbjMessage = CreateObject("CDO.Message")
objMessage.Subject = "Example CDO Message"
objMessage.From = "wiston.lifb@alibaba-inc.com"
objMessage.To = "wiston.lifb@alibaba-inc.com" objMessage.CreateMHTMLBody "file://d|/temp/test.htm" ' 把d:/temp/test.htm作为邮件内容发送。
objMessage.Bcc = "wiston.lifb@alibaba-inc.com"
objMessage.Cc = "wiston.lifb@alibaba-inc.com"
objMessage.Send -
excel对象池(二)
2008-05-15 18:09:01
by jiale
完成对象数据池的实现后,又遇到了一个问题,我们是在代码里手工释放对象池的,但当脚本遇到对象无法识别,qtp自动启动场景恢复重启脚本时,我们是否对象池的语句大部分情况不能被执行,因此会导致excel进程一直驻留,所以就需要在启用场景恢复时杀掉所有的excel进程,幸好qtp的场景恢复提供了在场景恢复时可以执行外部vbs的某个方法,这样我们将杀excel进程动作就放到vbs的某个方法中完成。
下面的脚本利用WMI杀excel进程:
Function KillExcel
dim oCIMV2
dim oExelEXE
dim i
Set oCIMV2=getobject("winmgmts:\\.\root\cimv2")
Set ōEXCELEXE=oCIMV2.execquery("select * from win32_process where name='EXCEL.EXE'")
For Each i In oEXCELEXE
i.terminate()
next
Set oCIMV2 = nothing
Set ōEXCELEXE = nothing
End Function -
excel对象池
2008-05-15 12:36:37
by jiale
自动化框架遇到了脚本执行时间长的问题,也就有了性能优化的需求,我们分析了影响性能的几个方面,其中一个是由于我们框架数据池是使用excel实现,每次读写数据池参数都要打开关闭excel.exe,打开excel.exe的时间就需要1-2秒,大大的影响性能,因此我们准备引入excel对象池,相同的excel文件只打开一次,打开后一直驻留在内存中,直到完成全部对该excel文件读写后关闭,这样读写数据池参数时不做打开关闭excel的动作,而改为读取excel对象池,打开关闭excel都有对象池方法来完成,
对象池方法:
一、从对象池获取excel对象:在对象池中查找是否存在该excel文件excelworkbook对象,存在则返回excelworkbook对象,不存在则打开文件后返excelworkbook对象
Function xlsGetPoolWorkbook(path)
Dim i
Dim oTempWorkBook
If IsEmpty(oPoolExcelApp) Then
Set ōPoolExcelApp = xlsCreateExcel()
End If
'对象池中存在则返回
For i = 0 To iPoolMaxNumber
If sPoolFilePath(i) = path Then
Set xlsGetPoolWorkbook = oPoolWorkBook(i)
Exit Function
End If
Next
'对象池中不存在则打开
On Error Resume Next
Set ōTempWorkBook = xlsOpenWorkbook(oPoolExcelApp,path)
If Err.Number <> 0 Then
Set xlsGetPoolWorkbook = nothing
Else
iPoolMaxNumber = iPoolMaxNumber + 1
ReDim oPoolWorkBook(iPoolMaxNumber)
ReDim sPoolFilePath(iPoolMaxNumber)
Set oPoolWorkBook(iPoolMaxNumber) = oTempWorkBook
sPoolFilePath(iPoolMaxNumber) = path
oTempWorkBook = nothing
Set xlsGetPoolWorkbook = oPoolWorkBook(iPoolMaxNumber)
End If
End Function二、释放对象池中某个excel对象
Function xlsFreePoolWorkbook(path)
Dim i
If IsEmpty(oPoolExcelApp) Then
xlsFreePoolWorkbook = 1
Exit Function
End If
'对象池中存在则释放
For i = 0 To iPoolMaxNumber
If sPoolFilePath(i) = path Then
Set oPoolWorkBook(i) = nothing
xlsFreePoolWorkbook = 1
Exit Function
End If
Next
End Function三、释放对象池中所有excel对象
Function xlsFreeAllPoolWorkbook()
Dim i
If IsEmpty(oPoolExcelApp) Then
xlsFreeAllPoolWorkbook = 1
Exit Function
End If
For i = 0 To iPoolMaxNumber
Set oPoolWorkBook(i) = nothing
sPoolFilePath(i) = ""
Next
iPoolMaxNumber = -1
oPoolExcelApp.quit
Set ōPoolExcelApp = nothing
xlsFreeAllPoolWorkbook = 1
End Function -
用字典对象实现堆栈的数据结构
2008-05-12 20:32:57
By Wiston Li
堆栈的数据结构的特征是Last in First out, 并被广泛应用,如错误的保护于处理,后出现的问题先处理,直到所有错误处理完毕。
下面一个程序采用字典对象实现堆栈, 用class 实现:
Class clsStack '定义堆栈
Private m_stack ' Dictionary Private member
' ** Class Constructor
Private Sub Class_Initialize
Set m_stack = CreateObject( "scrīpting.Dictionary" )
m_stack.Add "next", 0
End Sub
' ** Class Destructor
Private Sub Class_Terminate
If m_stack.Count > 0 Then
m_stack.RemoveAll
End If
Set m_stack = Nothing
End Sub ' 初始化变量与函数
Public Property Get Count() ' 定义count方法
Count = CLng( m_stack( "next" ) )
End Property
Public Property Get IsEmpty() ' 定义isEmpty方法
IsEmpty = CBool( Me.Count = 0 )
End Property
Public Sub Push( ByVal data ) ' 定义push方法
m_stack.Item( m_stack.Item( "next" ) ) = data
m_stack.Item( "next" ) = CLng( m_stack.Item( "next" ) ) + 1
End Sub
Public Function Pop()' 定义pop方法
If Me.IsEmpty Then
Reporter.ReportEvent micFail, "Stack", "The Stack is empty"
Pop = Empty
End If
Pop = m_stack.Item( m_stack.Item( "next" ) - 1 )
m_stack.Remove m_stack.Item( "next" ) - 1
m_stack.Item( "next" ) = CLng( m_stack.Item( "next" ) ) - 1
End Function
Public Function Peek() ' 定义peek方法
If Me.IsEmpty Then
Reporter.ReportEvent micFail, "Stack", "The stack is empty"
Peek = Empty
End If
Peek = m_stack.Item( m_stack.Item( "next" ) - 1 )
End Function
Public Sub Clean() ' 定义clean方法
If Not Me.IsEmpty Then
m_stack.RemoveAll
m_stack.Add "next", 0
End If
End Sub
Public Function Clone()' 定义clone方法
Dim m_cloned, key
Set m_cloned = CreateObject( "scrīpting.Dictionary" )
For Each key in m_stack.Keys
m_cloned.Add key, m_stack( key )
Next
Set Clone = m_cloned
End Function
Public Function ToArray()' 定义ToArray方法
Dim m_cloned
Set m_cloned = Me.Clone()
m_cloned.Remove( "curr" )
m_cloned.Remove( "next" )
ToArray = m_cloned.Items
End Function
End Class
' How it works?
Set stack = New clsStack
Print "stack.Count : " & stack.Count ' Prints zero
Print "stack.IsEmpty : " & stack.IsEmpty ' Prints True
' ** Adding a value
stack.Push "Message 1″
Print "stack.Count : " & stack.Count ' Prints 2
Print "stack.IsEmpty : " & stack.IsEmpty ' Prints False
Print "stack.Peek : " & queue.Peek() ' Prints "Message 2″
Print arr = stack.ToArray()
Do While stack.IsEmpty = False
Print stack.Pop()
Loop
Set stack = Nothing
-
excel采用usedRanage 与jet用select实现单元格访问
2008-05-12 20:08:18
By Wiston Li
在访问excel时,可用如下两种机制来进行单元格的访问遍历,
1,excel采用usedRanage 遍历到二维数组 2,采用jet用select into 到变量中去
二者都是放在内存中,从这两者的实现思路可以看到提高excel的i/o性能的可能着手地方,
代码如下:
1,
tmpArray = ReadExcel ("d:\devtmp\ADOtest.xls", "join")For i= 1 to ubound(tmpArray, 1) ' 输出二维数组
For j = 1 to ubound(tmpArray, 2)
msgbox tmp(i,j)
Next
NextFunction ReadExcel(sFileName,sSheetName)
Dim oExcel
Dim oRange
Dim arrRangeOn Error Resume Next
Set ōExcel = CreateObject("Excel.Application")
oExcel.Workbooks.Open(sFileName)
Set ōRange = oExcel.Worksheets(sSheetName).UsedRange ' 输出到二维数组中oRange
If Err.Number <> 0 Then
ReadExcel = Array("Error")
msgbox ReadExcel
Exit Function
End If
On Error Goto 0
arrRange = oRange.Value
Set ōRange = Nothing
oExcel.Quit
Set ōExcel = Nothing
ReadExcel = arrRange
End Function2, Function xlsGetSpecifiedDataFromDPForParameterbak(sFilePath, sSheetName, sVarible )
Dim sConnStr
Dim oConn
Dim oRS
Dim oFSO
Dim sSql
Dim iFirstEnd
Dim iSecondEnd
On Error Resume Next
Set ōFSO = CreateObject("scrīpting.FileSystemObject") ' check the file if exists
If not oFSO.FileExists(Trim(sFilePath)) Then
MsgBox "No Datapool File Found"
Exit Function
End If
If Trim(sSheetName)= "" Then ' check the worksheet if exists
MsgBox "No Sheet Found"
Exit Function
End If
' create the jet connection and get the DB object
sConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &sFilePath & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""; "
Set ōConn = CreateObject("ADODB.Connection")
oConn.Open sConnStr
Set ōRS = CreateObject("ADODB.Recordset")
iFirstEnd=4 ' mark the start flag
iSecondEnd=1000 ' mark the end flag, but unlimit depend on your requirement
sSql="Select * from [" &sSheetName & "$A" &iFirstEnd &":B" & iSecondEnd &"]"
' find the data you want to search
oRS.Open sSql, oConn
If Trim(sVarible) <> "" Then
Do While Not oRS.EOF
If Trim(oRS(0)) = "&end&" Then ' terminal the find until end
Exit Do
End If
If trim (oRS(0)) =trim (sVarible) Then
xlsGetSpecifiedDataFromDPForParameter=oRS(1)
Exit function
End If
oRS.MoveNext
Loop
Else
MsgBox "No data matched"
End If
Set ōConn = nothing
Set ōRS = nothing
Set ōFSO = nothing
If Err.Number <> 0 Then
MsgBox ("Error # " & CStr(Err.Number) & " " & Err.Descrīption & Err.Source)
End If
On Error Goto 0
End Function
-
类似ruby中hash table数据结构在QTP中的应用
2008-05-12 17:08:14
by wiston
计算机在处理数据时,很重要的数据结构类型,如: 顺序表(数组,队列,链表,堆栈),二叉树,图与hash表等,在vbs programming时大家经常用到顺序表如数组等,今天介绍一下,QTP vbs中类似hash结构的字典对象的处理
1, 初始化:
Set ōSettings = CreateObject("scrīpting.Dictionary")
oSettings.Add "10.0.32.124", "b2btest.com"
oSettings.Add "10.0.32.123", "b2bqa.com"2, 遍历:
skeys = oSettings.keys ' 取到关键词集合
sitems = oSettings.items ' 取到值集合
For i = 0 to oSettings.count -1msgbox skeys(i) & " " & sitems(i) ' 输出
Next
3, 删除:
oSettings.Remove("10.0.32.123")
4, 判断:
If oSettings.Exists("10.0.32.123") Then
msgbox "Specified key exists."
Else
msgbox "Specified key doesn't exist."
oSettings.Add "10.0.32.123", "b2bqa.com"
End If上面的数据结构非常实用,比如:与hosts文件交互,把此hash结构中key与value值,自动化去访问文件
即可以解决需要手工去配置hosts中域名绑定,而实现自动化无人职守方法之一。
-
无人值守运行自动化脚本
2008-05-12 14:00:02
by jiale
脚本越来越多,需要运行的场景越来越多,运行时间越来越长,需要无人值守的运行自动化脚本,并能在报告中体现运行情况,对于我们的自动化脚本框架业务驱动的实质,mainaction用callaction的方法调用子action,子action中的错误是不能在mainaction中用On Error的方法捕捉,自然当子action出现对象无法识别等异常时mainaction不能做出容错处理,程序自动stop,需要人工干预。
这是个无法回避的问题,这时我们想到了使用QTP的场景恢复功能,他能够识别到子action的对象无法识别等异常,并重启mainaction,那我们只需要告诉mainaction从哪里开始继续执行下去就可以了,之前已经运行的场景、action就不需要再运行,这时又出现一个问题,是从场景运行,或者从哪个组成场景的子action运行,首先如果从同一个场景的子action往下运行,有可能前一个错误的action是下一个action的必要条件,那么继续运行没有意义,而我们设置的场景却是相对独立的,且出错场景的再次运行出错的概率会很大,因此我们让mainaction从出错场景的下一个场景开始运行,有了这个思路,程序的实现就相对容易了,只需要在本地文件中记录当前正在运行的场景号,一旦出错,QTP场景恢复重启mainaction后,读取该文件的场景号,然后从场景号+1的场景继续运行,直到结束。
值得注意的是,当然每个场景开始运行需要打印开始标志,结束时打印结束标志,以得到该场景是否成功完成运行的信息。
目前这个方案实施的效果不错,但QTP的场景恢复无法识别vbs的语法错误,一旦有vbs语法错误仍然无法做到无人值守,因此子action的编码就需要有一定的质量保证。
-
ADODB.Connection使用OraOLEDB.OracleOracle字串链接数据库
2008-04-14 09:35:52
我们自动化脚本很多时候需要链接数据库进行数据验证或者数据准备,一般是用ADODB.Connection对象的open方法获取数据库链接,open方法的链接字串可以有很多种的形式,如:使用odbc、OraOLEDB.OracleOracle,但我们需要只需读取某个配置文件中的host、port、sid、userid、password就可以获得adobd的数据库链接,而不想在运行脚本的每台机器单独配置odbc或者oracle的tnsnames.ora,我们可以用OraOLEDB.OracleOracle字串获取链接adodb的数据库链接
strHost=从配置文件获取
strPort=从配置文件获取
strSID=从配置文件获取
strUser=从配置文件获取
strPassword=从配置文件获取
strConnectionString = "Provider=OraOLEDB.Oracle;Persist Security Info=True;"&_
"Data Source=(DEscrīptION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST ="+strHost +")(PORT = "+strPort+")))"&_
"(CONNECT_DATA =(SID = "+strSID+")));User ID="+strUser+";Password="+strPassword+";"Set ōConnection= createobject("ADODB.Connection")
oConnection.ConnectionString = strConnectionString
On error Resume Next
oConnection.open
If err.Number <> 0 Then
msgbox "数据库连接失败"
End -
如何得到localmachine的odbc driver安装配置?
2008-04-08 14:31:20
同样,在获取odbc driver时,也可以用下面方法来实现:
Const HKLM = &H80000002
Set reg = GetObject( "winmgmts:\\.\root\default:StdRegProv" )
keyPath = "SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"
reg.EnumValues HKLM, keyPath, valueNamesArr, valueTypeArr
For i = 0 to UBound( valueNamesArr )
reg.GetStringValue HKLM, keyPath, valueNamesArr( i ), valueStr
Print valueNamesArr( i ) & " –> " & valueStr
Next打印显示条目,具体可以参照附件。
-
如何得到odbc数据源中系统DSN的安装配置?
2008-04-08 14:22:28
上个月在研究框架excel遍历提速时,起初设想通过dsn对象来访问excel,
但需要遍历操作系统中是否安装excel driver和是否已经存在dsn, 但迫于这种方案比较土。后来没有这么做而是采用jet对象直接动态访问excel数据源. 其间在实现上述提到的方案,后来找到相关实现方法, 没有用到任何wmi和com对象,只是遍历与访问注册表。
Const HKLM = &H80000002 '定义常量
Set reg = GetObject( "winmgmts:\\.\root\default:StdRegProv" )
keyPath = "SOFTWARE\ODBC\ODBC.INI\ODBC DATA SOURCES" ' 欲取注册表分支
reg.EnumValues HKLM, keyPath, valueNamesArr, valueTypeArr '前面两个参数是传入,后面两个是传出参数, 均为数组。
For i = 0 to UBound( valueNamesArr )
reg.GetStringValue HKLM, keyPath, valueNamesArr( i ), valueStr
Print valueNamesArr( i ) & " –> " & valueStr
Next