专家视图(Expert View)
补充知识点:
1.取消测试结果报告的自动弹出
Tools\Options\Run\View Results when test session ends复选框
2.手动打开测试结果报告
(1)工具栏中的报告图标
(2)Automation\Test Result
3.碌梅脮没脳篓录脪脢脫脥录脰脨脳脰潞脜
Tools\View Option\Fonts and Colors\Size
一、QTP专家视图代码的解读
1.示例:
Dialog("Login").WinEdit("Agent Name:").Set "sunny"
(1)操作对象的名称:Agent Name:
(2)操作对象的类型:WinEdit
(3)操作对象的父对象名称:Login
(4)操作对象的父对象类型:Dialog
(5)操作方法:Set
(6)操作数据:"sunny"
2.专家视图中每行代码的种类
(1)录制的一个操作步骤
(2)VBS语句--if
(3)系统函数--wait
(4)注释
3.操作步骤的格式
(1)对象的描述:对象类型("对象名称")
(2)顶级对象.父对象.父对象....操作对象
(3)父对象和子对象之间用点(.)分隔
(4)对象和操作方法之间用点(.)分隔
(5)操作方法和操作数据之间用半角空格( )分隔
(6)多个操作数据之间用半角逗号(,)分隔
4.WindowsApplication里常用控件和常用操作方法
(1)WinEdit(文本框)---Set "数据" (设置) SetSecure "加密数据"(加密设置)
(2)WinButton(按钮)---Click (点击)
(3)WinComboBox(组合框)---Select "选项内容" (选择)
(4)WinRadioButton(单选按钮)---Set (选中)
(5)WinCheckBox(复选框)---Set "ON" (选中) Set "OFF"(取消选中)
(6)WinList(列表框)---Select "选项内容" (选择)
(7)Window(窗体)---Close(关闭)Activate(激活)
(8)Dialog(对话框)---Close(关闭)
(9)ActiveX---Type "键入内容"(输入)
(10)WinMenu(菜单)---Select "父菜单;子菜单;..." (选择菜单项)
5.常用的WebApplication里常用控件和常用操作方法
(1)WebEdit(文本框)---Set "数据"(设置)
(2)WebButton(按钮)---Click(点击)
(3)WebList(下拉框)---Select "选项内容"
(4)WebRadioGroup(单选按钮组)---Select "选项内容"
(5)Browser(浏览器)---Close(关闭)
(6)Page(页面)---Sync(同步)
(7)Link(链接)---Click(点击)
(8)WebTable(表格)
6.常用的增强脚本的代码
(1)参数化的数据:
DataTable("加数1", dtGlobalSheet)
DataTable("加数1", dtLocalSheet)
(2)检查点
示例:
WinEdit("Order No:").Check CheckPoint("Order No:")
操作方法:Check
操作数据:CheckPoint对象
(3)输出值
示例:
WinEdit("Order No:").Output CheckPoint("Order No:")
操作方法:Output
操作数据:CheckPoint对象
注意:
在专家视图书写代码的方式不能完成检查点和输出值的实现
可以完成参数化的实现,前提必须先在DataTable中准备数据
可以在录完后补录,
或者Window("Flight Reservation").WinEdit("Order No:").Set,将光标定位到“Order No”上,点击Insert,
选择输出
输出值输出到:dataTable
Window("Flight Reservation").WinEdit("Order No:").Output CheckPoint("Order No:")
orderNo=dataTable(1,2)
输出值输出到:environment
Window("Flight Reservation").WinEdit("Order No:").Output CheckPoint("Order No:_2")
orderNo1=Environment("订单号2") ‘订单号2是environment的名称
7.函数
Set:脡猫脰脙脰碌
SetSecure:脡猫脰脙脙脺脗毛脰碌拢卢脪禄掳茫驴脡脪脭陆芦Se赂脛脦陋脙梅脗毛
Type:脢盲脠毛拢卢虏禄禄谩脟氓驴脮脰庐脟掳脪脩脫脨碌脛
Click:碌茫禄梅
Select:脩隆脭帽脰碌
Close:鹿脴卤脮
Check :录矛虏茅碌茫
Output :脢盲鲁枚脰碌
翻译
1、英译汉
Add-in插件
Property属性
Delete删除
Object对象
Repository仓库
Value值
Select选择
Set设置
Click点击
Dialog对话框
Local本地的
2、汉译英
添加Add/Insert
参数Parameter
数据表DataTable
表单Sheet
文本Text
日期Date
浏览器Browser
编辑Edit/Modify
检查点CheckPoint
输出值putValue
(VBS语法1)
二、VBS的基础知识
Option Explicit 要求变量要先定义,未定义,去使用会报错或警告
1.VBS是脚本语言,不需要编译就可以执行
2.VBS三要素:属性、方法、事件
3.VBS变量
(1)VBS定义一个变量语法:
Dim a '定义一个变量
Dim x,y '定义多个变量
(2)变量默认可以不经过定义直接使用
如果在代码的第一行添加语句Option Explicit,变量必须经过定义才能使用
(3)变量名约束
a.必须以字母开头
b.不能超过255个字符
c.特殊符号只能包含下划线
d.不能和VBS或者QTP里的关键词重复
e.在一个作用于内必须唯一
(4)变量的类型只有一种:Variant
但是数值信息,可以包含很多子类型
a.Integer
b.String
c.Boolean
d.Date
e.double
f.Object
...
(5)变量的数值信息具体是什么子类型,由使用的上下文决定
4.运算符和表达式
(1)运算符包括:括号()、算术运算符、字符串连接符(&)、关系运算符、逻辑运算符
(2)字符串连接可以使用&,+
建议使用&
(3)表达式包括:数学表达式、条件表达式
5.VBS语法中不区分大小写,字符串的内容区分大小写
6.Cint和Cstr
Cint转换为整型,四舍六入,.5取最接近的偶数
Cstr转换为字符串型
练习1:两位数加法器加法,两个加数使用变量替换
练习2:两位数加法器加法,两个加数使用一个数组的两个元素替换
cdbl 字符串轉浮點型
7.Msgbox和Inputbox
Msgbox:'第一个参数:提示内容
'第二个参数:对话框的样式,包括按钮和提示类型等,具体参见帮助
'第三个参数:提示对话框的标题
'返回值:点击的按钮的ID
Inputbox:第一个参数:提示框的显示内容
'第二个参数:提示框的标题
'返回值:如果点击确定,返回输入的内容,如果点击取消,返回空字符串
'注意:如果使用返回值,必须把所有参数用括号括起来,如果不使用返回值,不括起来
练习3:两位数加法器加法,两个加数使用Inputbox获取数据
num1&"+"&num2&"="&res1
8.数组
拢篓1拢漏脢媒脳茅碌脛露篓脪氓
碌脷脪禄脰脰路陆脢陆拢潞Dim 脢媒脳茅脙没鲁脝(脢媒脳茅碌脛脳卯麓贸脧脗卤锚) 脧脗卤锚麓脫0驴陋脢录
脌媒拢潞Dim Myarr(3) '脢媒脳茅碌脛鲁陇露脠脢脟4
Myarr(0) = 12
Myarr(1) = "abc"
Myarr(2) = "2016-01-01"
Myarr(3) = true
碌脷露镁脰脰路陆脢陆拢潞Dim 脢媒脳茅卤盲脕驴
脢媒脳茅卤盲脕驴 拢陆 array(碌脷1赂枚脰碌,碌脷2赂枚脰碌,...)
脌媒拢潞Dim myarr
myarr = array(12,"abc","2016-01-01",true)
9.运算符优先级
老徐 优先级
() 1
^ 次方 2
- 3
*和/ 乘除 4
\ 5
Mod 模,取余数 6
+和- 7
&和+ 字符串连接符 8
拢陆 9
<> 不等于 10
> 11
< 12
>= 13
<= 14
Is 15
And 16
Or 17
Not 18
Xor 脗脽录颅脪矛禄貌 19
Eqv 脗脽录颅碌脠脫脷 20
Imp 脗脽录颅掳眉潞卢 21
常用函数
1.常见系统函数
Cint
默认4舍5入,如果小数位是.5,则取就近的偶数
Cint("0.5")=0 Cint("1.5")=2
Cstr
Cdbl
作用:转换数据的子类型为double(双精度浮点数)
Cbool
Date
输出格式:yyyy-mm-dd
Time
输出hh-mm-ss
Year(Date)---年
Month(Date)---月
Day(Date)---日
Hour(Time)---时
Minute(Time)---分
Second(Time)---秒
Dim datev '日期值
Dim timev '时间值
Dim filev '文件名
datev=year(date)&month(date)&day(date)
timev=hour(time)&minute(time)&second(time)
filev=datev&"_"&timev
eg:20160307184511
IsNumeric
IsNumeric()
Instr
Instr(参数1,参数2,参数3)
x="12.7"
Msgbox instr(1,x,".")--->
Len
Len()
1.随机数参数化
(1)可以通过关键字视图完成,也可以通过在专家视图中书写代码完成
RandomNumber(范围初值, 范围终值)
作用:系统函数RandomNumber,产生初值到终值的随机整数
2.Print系统函数
作用:把内容输出到Print log中
和Msgbox的区别:Print不会打断程序的运行,Msgbox会打断程序的运行
2.getROProperties
作用:取得当前被测系统运行时对象的某个属性值
示例:
cname=Window("Flight Reservation").WinEdit("Name:").GetROProperty ("text")
'取得当前被测系统运行时WinEdit("Name:")对象的text属性的值----方式二
3.建立输出值的操作,可以在录制过程中完成,也可以在录制结束后完成
录制结束后,可以通过ActiveScreen,右键\Insert Standard OutputValue建立标准输出值
4.检查点的返回值
(1)作用:在代码中获得检查点是否通过的结果
用这个结果值判断,做不同的业务处理
检查点如果通过,返回值为True
不通过,返回值为False
(2)方法:把check方法的参数checkpoint("xxx")用括号括起来,返回值可以使用
示例:
result=对象.Check(CheckPoint("xx"))
对象的常用方法
1.checkProperty方法
(1)语法:对象.checkProperty "属性名称",属性值,[超时时间]
(2)作用:等同于标准检查点,在超时时间范围内检查对象的属性值是否等于预期属性值
(3)注意:超时时间,单位为毫秒
超时时间不设置,默认为File\Settings\Run\Object synchronization Timeout时间
(4)返回值:检查结果
True---检查通过,False---检查不通过
2.WaitProperty方法
(1)语法:对象.WaitProperty "属性名称",属性值,[超时时间]
(2)作用:插入同步点,等待对象的属性变为预期属性值,最多等待时间等于超时时间
和wait系统函数作用相同,不同点是wait等待固定时间,wait的时间单位为秒 s
(3)注意:WaitProperty超时时间单位是毫秒 ms
如果超时时间内,没有等待到预期属性值,测试结果报告中出现警告(Warning)
(4)返回值:True---等待到属性的预期值
False---没有等待到属性的预期值
(5)同步点:下一条语句的输入,是上一条语句的输出,插入同步点。
同步点:
Tools\Options\Run\Run mode
wait系统函数
waitProperty方法
点击Insert Order后,校验
Window("Flight Reservation").ActiveX("Threed Panel Control").WaitProperty "text","Insert Done...",10
切记:timeout的单位是ms,切记有时就是以为是s出现很多莫名其妙的问题
3.Exist属性
(1)语法:a=对象.Exist(timeout时间,是对象同步超时时间)
如果没有指定判断时间,会用File/settings/Run/Object synchronization timeout默认的20s
(2)作用:判断对象是否在当前被测系统中存在
(3)取值:True---存在,False---不存在
4.Reporter系统对象(自定义测试报告,自定义检查点)
(1)语法:Reporter.ReportEvent micPass/micFail/micDone/micWarning,"步骤名称","详细描述"
reporter.reportEvent micDone, "卤锚脤芒(step name)","脛脷脠脻1(details)"
reporter.reportEvent micPass, "卤锚脤芒","脛脷脠脻2"
reporter.reportEvent micFail, "卤锚脤芒","脛脷脠脻3"
reporter.reportEvent micWarning, "卤锚脤芒","脛脷脠脻4"
(2)作用:向测试结果报告中书写测试步骤
5.自定义检查点
(1)确定检查内容
(2)通过If分支语句,判断条件成立时,调用Reporter.ReportEvent方法写入passed的步骤,不成立时,调用Reporter.ReportEvent方法写入failed的步骤
(VBS语法2)
if...then...end if
if...then...else...end if
if...then...elseif...then...end if
if...then...elseif...then...else...end if
一、VBS的IF语句(重点)
1.If...Then...End If
语法:If 条件表达式 Then
语句体
End If
作用:当条件表达式成立时,执行语句体
不成立时,直接执行End If后的语句
2.If...Then...Else...End If
语法:If 条件表达式 Then
语句体1
Else
语句体2
End If
作用:当条件表达式成立时,执行语句体1
不成立时,执行语句体2
3.If...Then...Elseif...Then...End if
语法:If 条件表达式2 Then
语句体1
Elseif 条件表达式2 Then
语句体2
End If
作用:当条件表达式1成立时,执行语句体1
当条件表达式2成立时,执行语句体2
不成立时,直接执行End if后的语句
4.If...Then...Elseif...Then...Else...End if
语法:If 条件表达式2 Then
语句体1
Elseif 条件表达式2 Then
语句体2
....
Else
语句体m
End If
作用:当条件表达式1成立时,执行语句体1
当条件表达式2成立时,执行语句体2
....
都不成立时,执行语句体m
二、Select Case语句
1.语法:Select Case 测试表达式
Case 表达式1
语句体1
Case 表达式2
语句体2
...
Case Else
语句体n
End Select
2.作用:
当测试表达式的值等于表达式1的值时,执行语句体1
当测试表达式的值等于表达式2的值时,执行语句体2
...
当所有的Case表达式的值都不等于测试表达式的值时,执行语句体n
注意:
(1)Case Else可以没有
(2)Select Case是If语句格式的变体,只有当If里的所有条件表达式都是某个表达式等于某个值时,才能使用Select Case替换
三、ForNext循环
1.语法:
For 循环变量=初值 to 终值 [Step 步长]
循环体
[Exit For]
Next
2.作用:完成指定次数的循环
每次循环时,循环变量自动加步长
当循环变量的值到达终值时,跳出循环,执行Next后的语句
3.注意:
(1)步长可有,也可没有,可是正数,也可是负数,当步长为正数时,初值要小于终值,当步长为负数时,初值要大于终值
步长默认值为1
(2)Exit For:当执行到此语句时,退出循环,执行Next后的语句
四、DoLoop循环
1.Do...Loop
2.Do While......Loop
3.Do...Loop While...
4.Do Until......Loop
5.Do ...Loop Until...
6.作用:不指定次数的循环
(1)While:当条件表达式为True时,执行循环体,取False时,跳出循环
(2)Until:当条件表达式为False时,执行循环体,取True时,跳出循环
(3)While\Until放在Do后,先判断循环条件,再执行循环体
(4)While\Until放在Loop后,先执行循环体,再判断循环条件
(5)Exit Do:当执行此语句时,退出循环
WhileWend循环和Do WhileLoop实现的功能相同
参数化高级(Datable的高级操作)
一、Datable的高级操作
3.0 DataTable
1.取值和赋值
2.导入和导出
3.行操作
4.表单操作
5.虏脵脳梅Parameters(脕脨)碌脛路陆路篓
6.卤盲脕驴Parameters碌脛脢么脨脭
7.count碌脛路陆路篓
3.1 取值和赋值
1.取值格式:DataTable("参数名称"/参数编号,dtGlobalSheet/dtLocalSheet/"表单名称"/表单编号)
2.参数编号和表单编号从1开始
3.赋值的格式:DataTable("参数名称"/参数编号,dtGlobalSheet/dtLocalSheet/"表单名称"/表单编号)="值"
4.如果第二个参数不写,默认Global表单
DataTable(ParameterID [,SheetID])
DataTable(ParameterID [,SheetID])=newValue
DataTable.value(ParameterID [,SheetID])
DataTable.value(ParameterID [,SheetID])=newValue
DataTable.rawValue(ParameterID [,SheetID])
3.2 DataTable导入导出
DataTable.Import "源文件.xls"
DataTable.ImportSheet "源文件.xls","源文件中表单名称"/表单编号,"DataTable中表单名称"/表单编号
DataTable.Export "目标文件名.xls"
DataTable.ExportSheet "目标文件名.xls","DataTable表单名称"/表单编号
1.导入---Import导入全部表单
(1)语法:DataTable.Import "源文件.xls"
(2)作用:按顺序导入表单,源文件中第一张表单导入到DataTable的第一张表单(Global),源文件中第二张表单导入到DataTable的第二张表单,以此类推
(3)注意:
a.源文件可以是绝对路径(例:D:\data.xls),也可以是相对路径(默认Test保存的目录,例:data1.xls)
b.导入表单数量以源文件中的表单数目和DataTable中表单数目较少的为准
c.导入代码运行前,必须把源文件关闭
d.源文件中的第一行数据作为DataTable中的参数名
2.导入---ImportSheet导入单张表单(重点)
(1)语法:DataTable.ImportSheet "源文件.xls","源文件中表单名称"/表单编号,"DataTable中表单名称"/表单编号
(2)作用:把源文件中指定表单的内容导入到DataTable中指定表单内
(3)注意:
a.双引号中的内容区分大小写
b.表单编号从1开始
c.不能通过dtGlobalSheet和dtLocalSheet来指定DataTable表单
3.导出---Export导出全部表单
(1)语法:DataTable.Export "目标文件名.xls"
(2)注意:如果文件不存在,创建新文件
如果文件存在,但是文件中不包含要导出的表单名称,在末尾新建表单,如果存在表单,覆盖表单内容
4.导出---ExportSheet导出单张表单(重点)
(1)语法:DataTable.ExportSheet "目标文件名.xls","DataTable表单名称"/表单编号
(2)注意:同Export
3.3行操作
1.SetCurrentRow方法(重点)
(1)语法:表单对象.SetCurrentRow 行号
(2)作用:设置表单的当前行
(3)注意:操作对象为表单对象,不是Datatable对象
2.GetCurrentRow
获得当前行
3.4表单操作
1.GetSheet方法(重点)
(1)语法:DataTable.GetSheet "表单名称"/表单编号
表单编号从1开始
(2)返回值:表单对象
2.AddSheet方法
(1)语法:DataTable.AddSheet "表单名称"
3.DeleteSheet方法
(1)语法:DataTable.DeleteSheet "表单名称"/表单编号
表单编号从1开始
3.5.DataTable的参数(列)操作
1.AddParameter方法
(1)语法:表单对象.AddParameter "参数名称","初始值"
(2)作用:在指定的表单对象中添加新参数,第一行的默认数据为设定的初始值
2.DeleteParameter方法
(1)语法:表单对象.DeleteParameter "参数名称"/参数编号
(2)作用:在指定的表单中删除一个参数
3.GetParameter方法
(1)语法:表单对象.GetParameter "参数名称"/参数编号
(2)返回值:取得的参数对象
表单对象.GetParameter ("参数名称"/参数编号).Name '取得参数名称
表单对象.GetParameter ("参数名称"/参数编号).Value '取得参数名称
例:Print DataTable.GetSheet(1).GetParameter(2).Value
等价于Print DataTable(2,1)
3.6.count统计
1.GetSheetCount方法
(1)语法:DataTable.GetSheetCount
(2)返回值:数值,运行时数据表的表单个数
2.GetParameterCount方法
(1)语法:表单对象.GetParameterCount
(2)返回值:指定表单在运行时的参数个数
3.GetRowCount方法
(1)语法:表单对象.GetRowCount
(2)返回值:指定表单在运行时的行数
二、RandomNumber的高级操作
3.7 随机数的参数化(RandomNumber)
1.Rnd函数
(1)作用:生成0-1的小数,包括0,不包括1
(2)限制:每次运行生成相同的随机数
解决限制方法:在前面调用Randomize函数
例:Randomize
Int((15-2+1)*Rnd+2) '2-15范围内的随机整数'
(3)生成随机整数的公式:
m-n范围内的随机整数:
Int((n-m+1)*Rnd+m)
例:Int((15-2+1)*Rnd+2) '2-15范围内的随机整数
2.Int函数
(1)作用:向下取整
(2)返回值:比参数小的最大整数
如果参数为正数,舍弃小数;如果参数为负数,舍弃小数后减一
3.带参数的RandomNumber随机数参数化
(1)步骤:
a.关键字视图中,点击Value列的<#>
b.选择Parameter,在参数化类型的下拉框中,选择RandomNumber
c.输入From(范围的下限),To(范围的上限)
d.选择Name的复选框,输入随机数名称
e.选择随机数的生成频率
e-1,for each action iteration(每次Action反复生成新的随机数)
e-2,for each test iteration(每次test反复生成新的随机数)
e-3,Once per entire test run(整个Test运行过程中,一共只生成同1个随机数)
三、Environment的高级操作
环境变量---相当天全局变量---作用相当天在Global中定义的变量,其它Action都可以使用
Settings/Environment/Variable type---分为Built-in和User-defined
Built-in: 内置环境变量
ActionIteration
ActionName
COntrollerHostName
GroupName
LocalHostName
OS
OSVersion
ProductDir
User-defined: 自定义的环境变量
Internal 内部的,可以修改
extual 外部的
关键字视图中 设置的是会记录在Settins中
专家视图中 手写的是临时的变量,不会记录在settings中
1.参数化时,可选环境变量(Environment)参数化,
可以在所有Action代码中通过Environment("参数名")使用
2.环境变量分为:
内置环境变量(Build-in) 不可修改内容
用户自定义环境变量(User-Defined)又分为2种
内部环境变量(Internal): 不可修改内容
外部环境变量(External): 可修改内容
3.Build-in和External不能修改内容,只有Internal可以修改
dataTable.ExportSheet environment("TestDir")&"\res.xls","新花名册"
输出值输出到:dataTable
Window("Flight Reservation").WinEdit("Order No:").Output CheckPoint("Order No:")
orderNo=dataTable(1,2)
输出值输出到:environment
Window("Flight Reservation").WinEdit("Order No:").Output CheckPoint("Order No:_2")
orderNo1=Environment("订单号2") ‘订单号2是environment的名称
正则表达式
一、正则表达式
1.为什么自动化测试要使用正则表达式
(1)预期结果是否满足某种格式
(2)满足某种格式的关键属性的对象可以被QTP正确识别
2.什么是正则表达式
描述规则的表达式
3.元字符
(1).匹配除了换行符以外的任意一个字符
(2)\w 匹配任意一个字母、数字、下划线、汉字
等同于 [0-9a-zA-Z_]
(3)\s 匹配任意一个空白符(空格、Tab空格、换行符)
(4)\d 匹配的任意一个数字
(5)\b 匹配单词的开始和结束的位置
\b123\b
\b\w*\b 以字母a开头的单词
(6)^ 匹配字符串的开始位置
(7)$ 匹配字符串的结束位置
例1:
正则表达式:^a\w$
可以匹配:a1,aa,aA,a_
不可以匹配:ba,1c,a14,a%
例2:
正则表达式:^a\w
可以匹配:a1,aa,aA,a_,a14,ab%
不可以匹配:ba,1c,a%
0\d{2}-\d{8} 直辖市固话
4.限定符
(1)* 重复0次或更多次 (前面可以是字符或者子表达式)
(2)+ 重复1次或更多次 (前面可以是字符或者子表达式)
()?重复0次或1次 (前面可以是字符或者子表达式)
(4){n}重复n次 (前面可以是字符或者子表达式)
(5){n,}重复n次或者更多次 (前面可以是字符或者子表达式)
(6){n,m}重复n次到m次 (前面可以是字符或者子表达式)
例13:
\d{8,10}:8-10位的数字
\w{5,}: 可以匹配:abcde,a1234,abc_567,不可以匹配:abc,a245
0\d{2}:可以匹配:026,不能匹配:0ac
A(AB)*b:可以匹配:AB,AabB,AababB,AabababB...,,不能匹配:AaabbB
13\d{9} 13开头的手机号
5.转义字符
正则表达式中的关键字,如果只匹配字符本身,前加\
例:\* 表示*本身,
\{ 表示{本身
\d+\.\d+ 小数
6.定义字符类
使用[]穷举所有可以匹配的字符
[]内中特殊字符,不用加\转义
例:^a[1-5]$:a1,a2,a3,a4,a5
[1-9] 1到9任意1个数字
注意:[1-12] 只能匹配 1或者2,
而不是1-12的数字
7.反义
(1)\W 匹配除了字母数字下划线以外的任意一个字符
(2)\S 匹配除了空白符(空格、Tab空格、换行符)以外的任意一个字符
(3)\D 匹配任意一个非数字的字符
(4)[^ab] 匹配任意一个非a非b的字符
[^1-9a-c]匹配任意一个除了1-9,a-c的字符
(5)\B 匹配任意一个非单词开始和结束的位置
8.替换
满足几种规则其中的任意一种规则,即匹配此规则,多个规则之间用|连接
从左向右匹配,一旦匹配成功,右边就不在进行判断
例1:[1-9]|10 ===:1-10
[1-9]|1[0-2] :1-12
[1-9]|[12]\d|3[01] :1-31 1-9,10-29,30,31
0?[1-9]|1[0-2] :1-12,01-09
0?[1-9]|[12]\d|3[01] :1-31,01-09
例2:
月份:1-12,01-12 =====1-9,10-12,01-09
正则表达式 [1-9] 匹配:1-9
正则表达式 1[0-2] 匹配:10-12
正则表达式 0[1-9] 匹配:01-09
最终:0?[1-9]|1[0-2]
例3:
0-25:
要匹配:0-9,00-19,20-25,
正则:[01]?[0-9] | 2[0-5]
或者 [01]?\d | 2[0-5]
0-255:
0-9,00-99,000-255
0-9,00-99,000-199,200-249,250-255
\d, \d\d, [01]\d\d, 2[0-4]\d, 25[0-5]
[01]?\d\d? | 2[0-4]\d | 25[0-5]
IP地址:
192.168.1.20 简单的IP
(\d{1,3}\.){3}\d{1,3}
IP地址中每个数字都不能大于255
000-255.000-255.000-255.000-255
0-255
0-9, 00-99, 000-199, 200-249, 250-255
\d,\d\d,[0-1]\d\d,2[0-4]\d,25[0-5]
[0-1]?\d\d?|2[0-4]\d|25[0-5]
([0-1]?\d\d?|2[0-4]\d|25[0-5]\.){3}([0-1]?\d\d?|2[0-4]\d|25[0-5])
0-365:
0-9,00-99,000-365
0-9,00-99,000-299,300-359,360-365
\d, \d\d, [0-2]\d\d, 3[0-5]\d, 36[0-5]
[0-2]?\d\d? | 3[0-5]\d, 36[0-5]
固定电话
0\d{2}-\d{8}|0\d{3}-\d{7}
固定电话(区号可以用小括号括起来,也可不括,可用-连接或者空隔,可不用)
\(0\d{2}\)[- ]?0\d{8}|0\d{2}[- ]?0\d{8}
|\(0\d{3}\)[- ]?0\d{7}|0\d{3}[- ]?0\d{7}
9.分组
某个子表达式重复多次,把子表达式用()括起来,构成一个分组
例1:正则表达式:A(ab)+
可以匹配:Aab,Aabab...
不可以匹配:Aaabb
练习1:0-255(允许下列格式:0,00,000,001,023)
0-9,00-99,000-099,100-199
[01]?\d\d?
200-249 2[0-4]\d
250-255 25[0-5]
[01]?\d\d?|2[0-4]\d|25[0-5]
IP地址:(([01]?\d\d?|2[0-4]\d|25[0-5])\.){3}([01]?\d\d?|2[0-4]\d|25[0-5])
练习2检查数字:
([-+]?[0-9]+\.?[0-9]+)
31,3.1 不能匹配3
=》
[-+]?[0-9]+(\.[0-9]+)?
31,3.1,3.26,3
练习3:
AgentName: ^.{4-10}$
Orderno: ^[1-9]\d*$
Price: ^\$\d+\.\d{2}$
date:
08/13/14
(0[1-9]|1[0-2])/(0?[1-9]|[12]\d|3[01])/\d{2}
检查日期
02-31 02.31 02/31
2-31 2.31 2/31
02-01 02.01 02/01
2-1 2.1 2/1
1-12 -./ 1-31
1-9 01-09 10-12 -./ 1-9 01-29 30-31
(0?[1-9]|1[0-2])[-./]([0-2]?[1-9]|3[0-1])
检查数字
[-+]?\d+\.?\d*
匹配非负整数(包括正整数+0)
0-9
^\+?\d+$
匹配正整数
^\+?\d*[1-9]\d*$
匹配非正整数(包括负整数+0)
^\-?\d*$
二、QTP中使用正则表达式
对象
To 对象仓库中的对象
RO 运行中对应的对象
1.识别对象时,对象(TO)关键属性(description properties)值使用正则表达式(非关键属性不影响对象的识别)
应用场景:被测系统中的对象(RO)实际关键属性值每次运行时变为不同值,都满足某个规则
步骤:
(1)定位回放时无法识别的对象名称
(2)打开对象仓库,找到该对象,查看其关键属性值
(3)使用ObjectSpy工具查看被测系统中实际对象运行时的关键属性值,和对象仓库中对比
(4)在对象仓库中,修改对象的关键属性值:
a.点击关键属性列表中变化的属性的值,再点击其后的<#>
b.在Value Configration Option(值配置选项)对话框中,选中Regular Expression(正则表达式)的复选框,点击“是”确认是否转义,在Constant内容中输入正则表达式
练习4:Flight创建新订单后,对新订单发送传真
2.检查点中检查对象的属性值使用正则表达式
应用场景:检查的不是具体数据,检查数据的格式
步骤:
(1)正常插入检查点,在检查点的编辑页面中,点击Constant后的"编辑"按钮
(2)在Constant Value Options(常量值选项)对话框中,选中Regular Expression(正则表达式)复选框,在Constant中输入正则表达式
练习5:Flight系统中订票日期输入比当前日期早的日期,使用检查点校验提示信息格式
08/13/14
01-09 10-29 3031
^Valid flight dates are after (0[1-9]|1[0-2])/(0[1-9]|[12]\d|3[01])/\d{2}$
3.还可使用在描述性编程中
三、校验正则表达式---S11001
Dim myre,result
Set myre=New RegExp
myre.pattern="正则表达式"
result=myre.Test("待校验字符串")
Msgbox result
返回值为True,表示字符串可以匹配正则表达式,为False,表示不匹配
作业:0-365(允许001,01格式)正则表达式
Set myreg=new RegExp
myreg.pattern="^小.*" '匹配规则
myreg.ignorecase=true '是否忽略大小写,true:忽略大小写, false:不忽略
myreg.global=true '是否全局匹配,true:找到1个继续找下1个,false:找到1个就不在找了
字符串操作
一、字符串的加密和解密
1.加密
(1)Password Encoder工具
开始\所有程序\QTP\Tools\Password Encoder
(2)DataTable的加密
待加密字符串输入到DataTable的单元格中,点击右键\Data\Encrypt
(3)Crypt系统对象的Encrypt方法
加密后字符串=Crypt.Encrypt("待加密字符串")
(4)Flight系统的密码框
待加密的字符串在录制Flight系统登录过程中输入到密码框中
2.解密
(1)修改非加密文本框的方法为SetSecure,值设置为加密串
(2)再使用GetROProperty取得非加密文本框的显示内容的属性值,即为原字符串
只有非加密文本框可以取出原始值
Dialog("Login").WinEdit("Agent Name:").SetSecure "56f537a5bcb2d5d1c4a9a21c8ec0"
str=Dialog("Login").WinEdit("Agent Name:").GetROProperty ("text") '这个属性值不一定是text,具体要看对象对应的具体属性,可用小人头Object spy工具查看
msgbox str
练习1:录制Mtours系统登录,输出解密后的密码
二、字符串处理常用方法
截取子字符串
Instr,Mid,Left,Right,Split
计算字符串长度
Len
字符串转数字
Cint
1.Instr系统函数
(1)语法:Instr [开始查找位置,]源字符串,目标字符串[,查找方式]
(2)作用:在源字符串中查找目标字符串第一次出现的位置
(3)返回值:位置的数字,如果找不到,返回0
(4)注意:
a.开始查找位置为数字
b.查找方式:0(二进制查找,区分大小写),1(文本查找,不区分大小写),0为默认值
c.当开始查找位置大于源字符串总长度时,返回0,开始查找位置1为默认值
d.如果给定第4个参数,第1个参数也需要给定
正则表达式TTS问题:
"^([012]?\d\d?|3[0-5]\d|36[0-5])$"
"^[012]?\d\d?$|^3[0-5]\d$|^36[0-5]$"
例:查找在字符串“abcdefg”中是否存在“cd”并返回其位置
pos=Instr(1,abcdefd","cd")------返回3
例:id="87444=ddddd"
instr(1,id,"=")-----返回6
2.Mid系统函数(重点)
(1)语法:Mid 源字符串,开始位置[,长度]
(2)作用:从源字符串的开始位置开始截取指定长度的子字符串
(3)返回值:截取到的子字符串,返回的是字符串,
(4)注意:
a.长度可以不指定,默认截取到整个源字符串的结尾
b.如果开始位置大于源字符串的长度,返回值为空串
c.如果长度大于可以截取的最大长度,返回值为从开始位置到源字符串的结尾
3.Len系统函数
(1)语法:Len 字符串
(2)作用:返回字符串的长度
(3)返回值类型是数值Integer
4.Left系统函数
(1)语法:Left 源字符串,长度
(2)作用:从源字符串的左侧截取指定长度的子字符串
(3)返回值:截取的子字符串
(4)注意:长度>源字符串的总长度,返回源字符串,长度=0,返回空字符串
源字符串中包含Null,则返回Null
5.Right系统函数
(1)语法:Right 源字符串,长度
(2)作用:从源字符串的右侧截取指定长度的子字符串
(3)返回值:截取的子字符串
(4)注意:长度>源字符串的总长度,返回源字符串,长度=0,返回空字符串
练习2:"$1112.01"
Mid("$112.01",2)
Right("$112.01",len("$112.01")-1)
练习3:随机取得"abcdefg"的随机长度的子字符串
练习4:自定义检查点,检查Flight的单价乘以票数是否等于总额
s1=123456.9
s2=123456.90
FormatNumber(s1,2) 保留2位小数
作业:PPT中将DataTable的数据,姓孔的姓名改为姓杨
6.FormatNumber(s1,2,,,true) 保留2位小数
第1个参数
待处理数值
第2个参数
2:保留2位小数
第5个参数
true:对数字使用逗号分隔
false:对数字不使用逗号分隔
返回的是数值,通常是double
四、截屏和启动程序
1.截屏
(插入检查点后,运行,报告中时会有截屏,如果是手动自定义的检查点,
像reporter.ReportEvent micPass,"检验总价是否正确", "正确",
这样是没有截屏,)
(1)语法:desktop.CaptureBitMap "文件名称",[是否覆盖已有文件]
对象.CaptureBitMap "文件名称",[是否覆盖已有文件]
(2)作用:对桌面或者某个对象截屏,保存到指定目录一张图片
(3)注意:文件类型只支持png,bmp格式,其中png占用空间较小
文件名称可以是绝对路径,也可以是相对路径(默认是存放在当前t脚本存放的目录中res文件夹中)
第2个参数,取值True/False,默认为False(不覆盖)
2.测试结果报告中添加截图
(1)语法:Reporter.ReportEvent 结果,步骤名,详细,[截图文件路径]
(2)作用:第4个参数把截图文件路径添加到测试结果报告中
'desktop.CaptureBitmap "abc.png",true
Window("Flight Reservation").CaptureBitmap "bjk.png",True
If cstr(formatnumber(fprice*tcount,2,,,false))=cstr(ftotal) Then
reporter.ReportEvent micPass,"检验总价是否正确", "正确", "abc.png"
else
reporter.ReportEvent micFail,"检验总价是否正确", "错误", "abc.png"
End If
练习5:Flight系统登录是否成功的自定义检查点,如果失败添加截图
3.启动程序
(1)语法:SystemUtil.Run "文件名称",[参数],[文件目录路径],[操作],[模式]
SystemUtil.Run file [params],[dir],[op],[mode]
file: 必填,是想要运行的文件的名称,也可以路径+名称
systemutil.Run "C:\WINDOWS\system32\notepad.exe"
systemutil.Run "c:\atlog.txt"
使用默认的软件打开
systemUtil.RUn "notepad" notepad是个系统指令,加入到了系统path下
params:可选,如果file参数中指定的是一个可执行文件,则可以使用params参数来指定该可执行文件的运行参数
systemutil.Run "c:\WINDOWS\system32\notepad.exe","c:\atlog.txt"
使用notepad 打开 atlog.txt文件
dir: 可选,应用程序或文件的默认目录
op: 可选,将要被执行的动作,如果该参数为空,则默认操作为open操作
mode: 可选,指定应用程序打开时的显示模式
(2)建议方式:
启动Windows程序:
'SystemUtil.Run "C:\Program Files\HP\QuickTest Professional\samples\flight\app\flight4a.exe"
启动Web程序:
'SystemUtil.Run "firefox","http://localhost:8080/mtours/" '--建议
'SystemUtil.Run "firefox.exe","http://localhost:8080/mtours/" '--建议
'SystemUtil.Run "iexplore","http://localhost:8080/mtours/" '--建议
'SystemUtil.Run "iexplore.exe","http://localhost:8080/mtours/" '--建议
systemutil.Run "C:\Program Files\Internet Explorer\IEXPLORE.EXE","http://localhost:8080/mtours"
systemutil.Run "C:\Program Files\Mozilla Firefox\firefox.exe","http://localhost:8080/mtours"
或者用
Dim sexe
Dim surl
sexe="firefox"
surl="http://localhost:8080/mtours/"
systemutil.Run sexe,surl
录制脚本时只能用IE,回放时,可以在代码中将浏览器改成其它浏览器,回放
作业
1.正则表达式中常用的元字符有哪些?分别能匹配哪些字符?
2.正则表达式中常用的限定符,以及他们的意义?
3.编写正整数的正则表达式,要求可以包含如下形式:1,10,+10,+0100
+?\d*[1-9]\d*
4.SystemUtil.CloseDescendentProcesses
(1)关闭所有由QTP启动的进程
包括:自动启动打开的程序,手动启动打开的程序,测试结果报告等
(2).关闭指定标题的进程
SystemUtil.CloseProcessByWndTitle "Login"
(3).关闭指定进程名称的进程
SystemUtil.CloseProcessByName "flight4a.exe"
'关闭进程名称为flights4a.exe的进程
作业1:PPT中SystemUtil对象的综合练习
5.锁定鼠标和键盘
(1)锁定BlockInput
SystemUtil.BlockInput
(2)解锁UnBlockInput
SystemUtil.UnBlockInput
(3)作用:在程序执行过程中,避免鼠标和键盘输入对程序的影响
五、Function(自定义函数)
1.Function作用:可读性和可维护性,复用性
2.Function语法:在Function和End Function之间的部分为自定义函数体
3.不带参数和返回值的Function
调用时,可以加Call,也可以不加Call
4.带参数的Function
调用时,需要给定相应形参里数量的参数值
5.带返回值的Function
返回值通过赋值给Function名来返回
用function同名的变量接收返回值
Function mymulti(num1,num2)
mymulti=num1*num2
End Function
以上返回值为mymulti
msgbox mymulti(10,2),,"结果"
使用返回值时,调用函数一定要加(),
不使用返回值,调用时,千万不可写(),会报错
6.Function中定义的变量,作用域为Function内,生存期为从调用Function开始,到调用Function结束
练习6:S13001中的正则表达式验证改成Function调用,参数1:正则表达式,参数2:待校验字符串,返回值:是否匹配
Function reTest(regex,str)
Dim myre
Set myre=New RegExp
myre.Pattern=regex
reTest=myre.Test(str)
End Function
result=reTest("^孔",namev) '调用Function reTest,给定实参为"^孔",namev
win/web对象的高级操作
一、Exist属性
(1)语法:对象.Exist([超时时间])
(2)返回值:对象是否在当前被测系统中出现,True---出现,False---未出现
(3)注意:超时时间的单位为秒
超时时间不给定,默认File\Settings\Run\ Object synchronization timeout(对象同步超时时间),20秒
二、Windows对象的常用方法和属性
1.Window对象(窗口对象)
Window("记事本").Activate ‘激活记事本的窗口
Window("记事本").Move 340,247
Window("记事本").Maximize
Window("记事本").Restore
Window("记事本").WinEditor("Edit").Type "1234567"
Window("记事本").WinEditor("Edit").Type micReturn ‘回车
Window("记事本").Close
Msgbox Window("记事本").GetROProperty("text")
2.WinComboBox对象(下拉组合框对象)
(0)属性
WinComboBox("xxx").GetROProperty("items count")
记录下拉组合框中的项目总数
WinComboBox("xxx").GetROProperty("selection")
记录当前选择的选项内容,和text属性记录相同
WinComboBox("xxx").GetROProperty("text")
记录当前选择的选项内容,和selection属性记录相同
WinComboBox("xxx").GetROProperty("all items")
记录所有选项内容
(1)GetItemsCount方法
a.语法:WinComboBox("xxx").GetItemsCount
b.返回值:下拉组合框中的项目总数
等同于 ==== WinComboBox("xxx").GetROProperty("items count")
(2)Select方法
a.语法:WinComboBox("xxx").Select "选项内容"/选项编号
b.注意:选项编号从0开始
(3)GetItem方法
a.语法:WinComboBox("xxx").GetItem 选项编号
b.返回值:该编号的选项内容
c.编号从0开始
GetSelection方法
返回选中行对应的的内容
等同于 ==== WinComboBox("xxx").GetROProperty("selection")
WinComboBox("xxx").GetROProperty("text")
GetContent方法
返回返回下拉框对应的内容
等同于 ==== WinComboBox("xxx").GetROProperty("all items")
练习1:在From选择前后分别获得到达城市的项目数
练习2:自定义检查点,检查在From中随机的选择一个城市后,To的下拉框中不出现From里选择的城市
(4)随机选择一个下拉框的选项内容
a.获得选项总数:GetItemsCount方法,获得items count属性值
b.生成随机数,范围0到(选项总数-1)
c.使用Select方法,选择b随机数的项目
Dim cityCount '起飞城市总数
Dim itemno '起飞城市索引数
Dim tocitCount '到达城总市数
Dim toitemno '到达城市索引数
For i=0 to 5
cityCount=Window("Flight Reservation").WinComboBox("Fly From:").GetItemsCount
itemno=randomnumber(0,cityCount-1)
tocityCount=Window("Flight Reservation").WinComboBox("Fly To:").GetItemsCount
toitemno=randomnumber(0,tocityCount-1)
Window("Flight Reservation").WinComboBox("Fly From:").Select itemno
Window("Flight Reservation").WinComboBox("Fly To:").Select toitemno
msgbox Window("Flight Reservation").WinComboBox("Fly From:").GetContent
Next
3.WinList对象(列表框)
(1)GetItemsCount方法
a.语法:WinList("xxx").GetItemsCount
b.返回值:列表框中的项目总数
(2)Select方法
a.语法:WinList("xxx").Select "选项内容"/选项编号
b.注意:选项编号从0开始
(3)items count属性
记录列表框中的项目总数
selection
当前选中行的内容
(4) 随机选择一个WinList对象中的项目
步骤:
(1)获得列表框中的项目总数,通过两种方法:
a:使用GetItemsCount方法
b:获得items count属性值
(2)生成随机编号,范围0到(项目总数-1)
(3)使用Select方法选择步骤(2)生成的随机编号
4.WinMenu对象(顶部的菜单栏)
(1)注意:不能通过手动添加添加到对象仓库,
也不能通过Object Spy捕获
只能通过录制代码
(2)Select方法
a.
语法1:WinMenu("xx").Select "一级菜单完整名称;二级菜单完整名称..."
注意:名称必须是全称,如:File(F)
语法2:WinMenu("xx").Select "<Item n>;<Item m>;<Item k>..."
注意:编号从1开始(Item的I必须大写)
b.作用:选择某个菜单
(3)CheckItemProperty方法
验证menu中的属性,
Window("Flight Reservation").WinMenu("Menu").CheckItemProperty("File;Fax Order...","enabled",false)
5.WinRadioButton对象(单选按钮)
(1)每个单选按钮是一个独立的对象
(2)Set方法
a.语法:WinRadioButton("xx").Set
b.作用:选中此单选按钮
经济舱:112.2
商务舱:224.4
头等舱:336.6
作业2:PPT中Windows对象的综合练习
对Flights 订票测试需求:
1. 录制订单的新增和根据订单号打开操作(WinMenu编号)。
2. 检查日期和航班起止地输入完成前后“Flight”按钮的有效性。
3. 对票数参数化,要求票数参数化为1到6之间的随机数。
4. ? 对飞机舱位进行随机选择
5. 输出新增订单的订单号,并以此订单号打开订单。
6. 随机选择“出发地”和“到达地”字段,航班列表出现后,随机选择某一航班。
7. 检查某一航班三种舱位(Economic,Business和First)的价格是否正确:First=Economic*3 Business=Economic*2
8. 将运行测试中产生的“出发地”和“到达地”字段值以及三个等级的票价写入数据表中,并在测试结果中显示。
三、Web对象的常用操作方法
选择index时,最好统一使用“#index”
1.WebList对象(下拉组合框)
(1)Select方法
a.语法:WebList("xx").Select "选项内容"/选项编号/"#选项编号"
select "Paris"
select 5
select "#5"
b.作用:从Web下拉框中选择一个项目
c.注意:编号从0开始
(2)items count属性
记录选项的总数
注意:WebList对象没有GetItemsCount方法
(3)value属性或者selection属性
记录当前选项的内容
(4)all items属性
记录所有选项内容,分号分隔各个内容
(5)GetItem方法
a.语法:WebList("xxx").GetItem 选项编号
b.作用:获得某选项编号的选项内容
c.注意:编号从1开始
练习3:Mtours系统随机选择起飞城市和到达城市,订票,
要求:起飞城市和到达城市不能选择相同的城市
提示:Do...Loop
2.WebRadioGroup对象(单选按钮组,一组单选按钮是1个对象)
(1)Select方法
a.语法:WebRadioGroup("xx").Select "选项内容"/"#选项编号"
b.注意:选项内容不一定和显示的项目内容一致
选项编号从0开始
(2)items count属性
记录选项总数
(3)value属性
记录当前选项的内容
(4)all items属性
记录全部选项的内容
(5)selected item index属性
记录选项编号,编号从1开始
(6)随机选择的算法
a.获得items count属性的选项总数
b.生成随机数,范围为0到(总数-1)
c.选择随机数编号的项目,格式如下:Select "#"&randno
3.Webtable对象(表格对象,通过录制是录制不了的)
(1)如何添加WebTable对象到对象仓库
a.打开对象仓库,点击“Add Object to Local”(添加对象到对象仓库)
b.点击WebTable对象的某个项目
c.在Object Selection(对象选择)对话框中,点击WebTable对象,再添加
(2)RowCount方法
a.语法:WebTable("xx").RowCount
b.作用:返回表格的行数
(3)ColumnCount方法
a.语法:WebTable("xx").ColumnCount 行号
注意:行号从1开始
b.作用:返回指定行的列数
(4)GetCellData方法
a.语法:WebTable("xx").GetCellData 行号,列号
b.作用:返回指定行指定列的单元格文本内容
c.注意:当指定的单元格不存在时,报错“无效单元格”
当指定的单元格存在,内容为空时,返回空数据
Browser("Select a Flight: Mercury").Page("Select a Flight: Mercury").WebRadioGroup("outFlight").Select "Blue Skies Airlines$191$723$7:08 pm$"
Set departO=Browser("Select a Flight: Mercury").Page("Select a Flight: Mercury").WebTable("DEPART")
rowC=departO.RowCount
print "总行数:"&rowC
print "---------"
For i=1 to rowC
colC=departO.ColumnCount (i)
For j=1 to colC
print i&"行---"&j&"列---"&departO.GetCellData (i,j)
Next
Next
(5)其它
-ChildItem方法
-ChildItemCount方法
-GetRowWithCellText方法
-ChildItem方法(index从0开始)
a.语法:object.ChildItem(Row,Column,MicClass,Index)
object.ChildItem(2,3,"Link",2)---查2行3列单元格中,索引为2的 所有链接对象
b.作用:获取相应行、列单元格中指定类型,指定编号的对象
c.返回值:对象
-ChildItemCount方法
a.语法:object.ChildItemCount(Row,Column,MicClass)
object.ChildItemCount(2,3,"Link")---查2行3列单元格中,所有链接的个数
b.作用:获取相应行、列单元格中指定类型的对象个数
-GetRowWithCellText方法
a.语法:object.GetRowWithCellText(Text,[Column],[StartFromRow])
msgbox depO.GetRowWithCellText("Pangea Airlines 192",2,2)
會先從第2行,第2列開始找,然後在從第3行第2列找,一直在第2列找,找不到,返回-1行
b.作用:返回表格中出現的第一個匹配字符串值的行號
(6)行数、列数都是从1开始
练习4:打印Depart表格中的每个航班的起飞时间
2721.32
4.通过插入表检查点和表输出值的方式获得表的设计(探测的不太准确)
表检查点:Insert\CheckPoint\Standard CheckPoint,选择对象时,选择WebTable的对象
表输出值:Insert\Output Value\Standard OutputValue,选择对象时,选择WebTable的对象
四:其它技巧
1.控件的随机选择
a.获取选项的总数
GetItemsCount方法 或者
items count 属性
b.获取随机数
RandomNumber(第一个选项的编号,总数/总数-1)
c.选择随机数
2.简化代码的方法
a.将对象赋值给变量(在变量前一定要加 set)
b.With...End With
网友评论