01-LR脚本开发基础

一、数据库性能测试

脚本说明

1.      数据操作脚本准备 Testdb.java

import java.sql.*;

import java.text.SimpleDateFormat;

public class Testdb {

       publicstatic void main(String[] args) {

              // 如果传入的参数不等于2,则给出提示信息"调用:java test_db ip:port recordcnt"

              if (args.length != 2) {

                     System.out.println("调用:java test_db ip:portrecordcnt");

                     return;

              }

              // 根据传入的参数,动态建立连接URL

              String url ="jdbc:oracle:thin:@"+args[0];

              int cnt = Integer.parseInt(args[1]);

 

              // 1 Java 连接 Oralce

              try {

                     //数据库连接初始化操作

                     Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();

                     Connectionconn = DriverManager.getConnection(url, "test",

                                   "administrator");

 

                     //声明起初记录插入时间

                     longtimeBegin;

                     java.util.Dated1 = new java.util.Date();

                     //循环插入记录

                     PreparedStatementpstmt = conn

                                   .prepareStatement("insertinto test_db(ID,time) values (?,?)");

                     Statements = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,

                                   ResultSet.CONCUR_READ_ONLY);

                     timeBegin= d1.getTime();

                     SimpleDateFormatdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                     for(int i = 1; i <= cnt; i++) {

                            pstmt.setInt(1, i);

                            pstmt.setString(2, df.format(newjava.util.Date()));

                            pstmt.executeUpdate();

                     }

                     s.close();

                     conn.close();

                     //诸末尾记录跟初始记录的时间差

                     java.util.Dated2 = new java.util.Date();

                     System.out.println("用时 : " + (d2.getTime() - timeBegin) + " 毫秒");

              } catch (InstantiationException e) {

                     e.printStackTrace();

              } catch (IllegalAccessException e) {

                     e.printStackTrace();

              } catch (ClassNotFoundException e) {

                     System.out.println("找不到ORALCE数据驱动");

                     e.printStackTrace();

              } catch (SQLException e) {

                     e.printStackTrace();

              } catch (Exception e) {

                     e.printStackTrace();

              }

       }

}

 

2.      批处理文件建立 test.bat

@ echo off

if "%JAVA_HOME%" =="" goto error_setting

set CLASSPATH=ojdbc14.jar;Testdb.jar

rem 当前路径 dir "%~dp0"

java -classpath %CLASSPATH% Testdb %1 %2

goto end

:error_setting

echo JDK环境变量未正确设置

goto end

:end

3.      编写LR脚本。

Action()

{

   //调用windows可执行程序

       system("testdb127.0.0.1:1521:orcl 1000");

       return0;

}

 

注意:

Ø  几个脚本并发,集合一定要设置成相同的名称;

Ø  Java程序所依赖的jar包以及批处理文件应放置到脚本所在目录。

二、FTP测试

脚本演示

ftp_logon_ex();

ftp_get_ex();

ftp_put_ex();

 

三、文件下载

脚本演示

web_set_max_html_param_len();

web_get_int_property();

Fwrite();

四、http接口测试

脚本演示web_url()  web_submit_data()

1.      web_custom_request()函数介绍

语法:
Int web_custom_request (const char *RequestName, <List of Attributes>,

 [EXTRARES, <List of Resource Attributes>,] LAST );

返回值
返回LR_PASS(0)代表成功,LR_FAIL(1)代表失败。

参数:
RequestName:步骤的名称,VuGen中树形视图中显示的名称。

List of Attribute:支持的属性有以下几种:

1.     URL:页面地址。

2.     Method :页面的提交方式,POST或GET。

3.     TargetFrame:包含当前链接或资源的frame的名称。参见List of Attributes的同名参数。

4.     EncType:编码类型。

5.     RecContentType:响应头的内容类型。参见List of Attributes的同名参数。

6.     Referer:参见List of Attributes的同名参数。

7.     Body:请求体。参见List of Attributes的同名参数。

8.     RAW BODY:参见List of Attributes的同名参数。

9.     BodyFilePath:作为请求体传送的文件的路径。它不能与下面的属性一起使用:Body,或者其他Body属性或Raw Body属性包括BodyBinary,BodyUnicode, RAW_BODY_START或Binary=1。

10. Resource、ResourceByteLimit、Snapshot、Mode:参见List of Attributes的同名参数。

11. ExtraResBaseDir:参见List of Attributes的同名参数。

12. UserAgent:用户代理,它是一个HTTP头的名字,用来标识应用程序,通常是浏览器,它呈现的是用户和服务器的交互。

例如:头信息“User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)”识别的是Window NT下的IE浏览器6.0。其他的User-Agent的值用来描述其他的浏览器,或者非浏览器程序。通常,一个应用程序中所有的请求都使用相同的用户代 理,录制者作为一个运行时参数来指定(Run-Time Setting—BrowserEmulation—User Agent)。不管怎么说,即使是在一个简单的浏览器进程中,仍有可能会用到直接与服务器交互的非浏览器组件(例如ActiveX控件),通常他们有着不 同于浏览器的用户代理属性。指定“UserAgent”表示这是一个非浏览器的请求。指定的字符串被HTTP头“User-Agent:” 使用,在某些情况下,它同时会影响回放脚本时的行为。例如,不使用浏览器缓存,假设指定的URL属于资源等等。

LoadRunner本身不检查指定的字符串与浏览器本身的值是否相同。

13. Binary:“Binary=1”表示页面请求体中的每一个以file://x/##形式出现的值(在这里“##”代表2个十六进制数字),都会被替换为单字节的十六进制的值。

如果“Binary=0”(默认值),所有的字符序列只是按照字面的值传递。

需要注意双斜杠的用法。在C编译器中双斜杠被解释为单斜杠。如果不需要零字节,单斜杠可以在Binary不等于1的情况下使用(例如,使用\x20代替file://x20/)。如果需要零字节,那么只能使用file://x00/且设置 “Binary=1”,\x00在逻辑上会被截断。

14. ContentEncoding

指定请求体的使用指定的方式(gzip或者deflate)进行编码(例如,压缩),相应的“Content-Encoding:”HTTP头会和此请求一起发送。这个参数适用于web_custom_request和web_submit_data。

EXTRARES:表明下面的参数将会是List Of ResourceAttributes了。

LAST :结尾的标示符。

 

2.      脚本中错误处理

void lr_continue_on_error ( intvalue );

 常量名称                                         常量值      含义

LR_ON_ERROR_NO_OPTIONS                         0         取消出错继续执行设置

LR_ON_ERROR_CONTINUE                           1          发生错误继续运行脚本

LR_ON_ERROR_SKIP_TO_NEXT_ACTION              2      发生错误跳至下个Action运行

LR_ON_ERROR_SKIP_TO_NEXT_ITERATION            3     发生错误跳至下一迭代来运行

LR_ON_ERROR_END_VUSER                          4         发生错误结束当前用户

    lr_continue_on_error调用后将对其后面所有的语句产生影响。因此,脚本中较常用的是lr_continue_on_error (0)与lr_continue_on_error (1)。这两个语句成对出现,期间包含着需要设置为发生错误停止执行的关键业务脚本。

3.      参数与变量使用

int lr_save_string( const char*param_value, const char *param_name);

变量转换为参数。

char *lr_eval_string( const char *instring);

获取参数。

Strcpy(char * ,char *);

参数转换为变量。

4.      乱码处理

int lr_convert_string_encoding( const char*sourceString, const char *fromEncoding, const char *toEncoding, const char*paramName);

lr_convert_string_encoding("登陆成功",NULL,"UTF-8","temp");

如果这样用得出的结果是

登录成功\x00

而正确的结果应该是

登录成功

为了去掉这个最后的\x00,可以通过下面这个办法去掉
lr_save_string(lr_eval_string("{temp}"),"temp");

当你对一个带有/x00的参数取值时,会自动去除掉,所以只需要再存一次就行了.

 

五、SOCKET协议脚本录制

主要函数:

int lrs_create_socket( char*s_desc, char *type, [ char* LocalHost,] [char* peer,] [char *backlog,] LrsLastArg);

s_desc:要初始化的套接字标识符;

Type:套接字类型,TCP/UDP;

LocalHost:绑定本地端口;

Peer:远程机器端口;

Backlog:请求连接队列的长度,如backlog=25;

LrsLastArg:参数结束标识符。

int lrs_send( char *s_desc,char *buf_desc, [char *target], [char *flags,] LrsLastArg );

int lrs_receive( char*s_desc, char *bufindex, [char *flags], LrsLastArg );

lrs_receive()默认超时时间为10S,通过lrs_set_recv_timeout()和lrs_set_recv_timeout2()制定超时时间

 

参数化:

action:

paraData=<NewParam>;

rs_save_param_ex("socket0","user",lr_eval_string(paraData),0,strlen(lr_eval_string(paraData)),NULL,"data_param");

 //把测试用参数通过函数,传递给 “data_param”,把data_param参数放在Data.ws

data.ws

send  buf0 "<data_param>" 

 

六、调用JAR包

脚本演示

七、调用DLL动态库

脚本演示

第一种:

lr_load_dll("LRDllTest.dll");菜单“File-Add file to script”,把要引用的DLL加进来,Agent的Enable Firewall Agent选项不要勾上。

第二种:mdrv.dat方法

将LRDllTest.dll拷贝到LoadRunner安装路径的Bin目录下。

修改mdrv.dat文件(安装路径的dat目录下),因为选择的是默认的Web协议,所以找到[lrun_api]节点,在后面加上一句: WINNT_DLLS=LRDllTest.dll

八、关联操作

脚本演示

1.      方法一:自动关联

1.Tools-Recording Options。

2.设置完成后录制登陆 - 退出过程。

3.利用LR自带的自动关联进行关联。

2.      方法二:手动关联

1:录制测试脚本,录制二遍

2:使用WinDiff工具找出两次脚本的不同,判断是否需要进行关联(Tools下的 Compare with Vuser进行2个相同操作的脚本对比)

3:确定插入关联的位置

4:在VIEW TREE中使用web_reg_save_param函数手动建立关联

5:将脚本中有用到关联的数据,用参数代替

6:验证关联的正确性

函数原型:

  int web_reg_save_param (const char*ParamName, <List of Attributes>, LAST);

参数说明:

ParamNam:存放动态数据的参数名称

  List of Attributes:其它属性,包含Notfound、LB、RB、RelFrameID、Search、ORD、SaveOffset、Convert、SaveLen。

  ● Notfound:指当找不到要找的动态数据时,怎么处理。

  ● Notfound=error,当找不到动态数据时,发出一个错误信息,为LoadRunner的默认值。

  ● Notfound=warning,当找不到动态数据时,不发出错误信息,只发出警告,脚本会继续执行下去不会中断。

  ● LB:动态数据的左边界字符串,该参数为必选参数,并区分大小写。

  ● RB:动态数据的右边界字符串,该参数为必选参数,并区分大小写。

  ● ORD:指提取第几次出现的左边界的数据,该参数为可选参数,默认值是1。假如值为All,则查找所有符合条件的数据并把这些数据存储在数组中。

   ● Search:搜寻的范围。可以是Headers(只搜寻Headers)、Body(只搜寻Body部分,不搜寻Headers)、 Noresources(只搜寻Body部分,不搜寻Header与Resource)或是All(搜寻全部范围,此为默认值),该参数为可选参数。

  ● RelFrameID:相对于URL而言,欲搜寻的网页的Frame,此属性可以是All或是具体的数字,该参数为可选参数。

  ● SaveOffset:当找到符合的动态数据时,从第几个字符开始才存储到参数中,该参数为可选参数,此属性值不可为负数,其默认值是0.

  ● Convert:可能的值有两种:

  ● HTML_TO_URL:将HTML-encoded数据转成URL-encoded数据格式。

  ● HTML_TO_TEXT:将HTML-encoded数据转成纯文字数据格式。

  ● SaveLen:从Offset开始算起,到指定长度内的字符串,才储存到参数中,该参数为可选参数,默认值为-1,表示储存到结尾整个字符串。

        例子:web_reg_save_param("Test","LB=userSessionValue","LB=>","Ord=1"

              "RelFrameID=1.21","Serch=Body","IgoreRedirections=Yes",LAST);

 

九、LR脚本编写规范

规范说明及模板演示

1.一般约定   

1.1具体脚本规则,必须在具体代码中加注释,以便脚本开发人员阅读和理解脚本。

1.2脚本的存放规则:

测试脚本应该存储在指定的库中,例如一个共享的驱动盘或测试管理工具中。为节省空间,便于复用,测试脚本的文件夹下的: result,res,date 文件夹,后缀名为:.idx  .log .txt 文件都可不必保留。

1.3脚本中 action的命名规则:

录制脚本前有个命名规则非常有必要,否则同一动作会有多个事务,会给数据收集、分析带来不必要的麻烦。

假设某J2EE系统实现开户、销户业务,那么自然会有Login、OpenAccount、DestroyAccount和LoginOut动作。那么录制LR脚本时,脚本中的Action列表应该为:

脚本1:初始化-Login-OpenAccount-LoginOut-结束动作
       脚本2:初始化-Login-DestoryAccount-LoginOut-结束动作
(即只有一个动作不同)这样做其目的是创建场景Scene时,在Login、LoginOut的事务只被记录一次

1.4 变量命名规则

变量的命名的基本原则是使得变量的含义能够从名字中直接理解。可以用多个英文单词拼写而成,每个英文单词的首字母要大写,其中英文单词有缩写的可用缩写;变量的前缀表示该变量的类型;对于作用域跨越10行以上的变量名称不能少于4个字符,除循环变量,累加变量外不得使用I、j、k等名称的变量。变量分为取全局变量和局部变量,对于全局变量以加前缀“g_”来区分。

1.5 常数名规则

       常量所有的字母均为大写。并且单词之间使用下划线”_”隔开。例如:

     USER_LIST_MAX

     NEW_LINE

1.6 函数名命名规则

函数/过程名称应该尽量使用能够表达函数功能的英文名称,函数名称中应该禁止使用如同function1,function2等含义不清的名称。单词间应该使用大小写分隔。全局函数/过程名称以“g_”前缀开始。

2.     代码注释约定

在软件中对每个文件头,自定义函数和变量,重要的处理过程都要有必要的注释。
  2.1 源程序头的注释和规范
  每个文件头插入注释,标明文件的用途和作者,注释如下:(注释尽量用中文)
  //程序名称
  //版权说明
  //版本号:
  //功能:
  //开发人:
  //开发时间:
  //修改者:
  //修改时间
  //修改简要说明
  //其他
  2.2 函数的注释
  每个函数前面注明函数的功能和输入,输出。注释为:
  //名称
  //功能:(说明函数的功能)
  //输入参数:(说明每个输入参数的用途和取值约定)
  //输出参数:(说明每个输出参数的用途和取值约定)
  //返回:(说明返回值,返回值的含义和约定)
  2.3 变量注释
  直接在变量后面注明变量的用途和取值约定,如:
  int status; //记录处理状态,0: 成功,1: 错误
  2.4 类型定义注释
  指类和记录等等定义的注释。在注释中标明定义的用途。
  2.5 区的注释
  同一个类的成员方法要求排列在一起,共同协作而实现同一个功能的函数和过程要求排列在一起。代码通常使用几个函数和过程来实现某一项功能,这时候需要使用区注释将这些具有共同目的的函数和过程标明出来。
  使用整行的”*”作为隔离行,让程序清晰可读。
  一般删除的代码不建议直接删除,最好用“//”注释起来。
  2.6 代码中的注释
  在代码中要求注释的地方有:
  代码中的关键部分;
  在使用特殊算法或者逻辑性较强的代码;
  在修改或删除代码部分,需要加注释;修改/删除人,目的.

3.      格式化代码

程序应采用缩进风格编写,每层缩进使用一个制表位(TAB),类定义、方法都应顶格书写;
  左花括号要另起一行,不能跟在上一行的行末;
  一个变量定义占一行,一个语句占一行;
  对独立的程序块之间、变量说明之后必须加空行;
  对于较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读;
  循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分;
  在结构成员赋值等情况,等号对齐,最少留一个空格;
  若函数或过程中的参数较长,则要进行适当的划分。
  形参的排序风格:
  Ø 最常使用的参数放在第一位;
  Ø 输入参数列表应放在输出参数列表的左边;
  Ø 将通用的参数放在特殊的参数的左边

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值