发布新日志

  • LR学习点滴记录-socket脚本学习1

    2008-07-21 14:51:07

    网上搜索时看到一篇好的实例,复制下来,保存:

    用LoadRunner编写socket应用的测试脚本

            LoadRunner提供了很好的对socket应用的支持,用户可以通过录制方法完全获得客户端发送和接收的数据,然后在录制的基础上对相应的数据进行参数化和关联等处理。

            但在有些情况下(例如,客户端程序没有windows上的版本),我们就很难通过录制达成生成脚本的目标了。但如果我们能够完全知晓服务端和客户端的交互过程,完全手工编写一个测试脚本也并不是一件特别困难的事情。

           在本文中,我们以一个实际的例子说明如何根据服务端和客户端交互的过程,用LoadRunner自行编写相应的脚本。

            以下是服务端工作线程的代码:
    DWORD WINAPI mythread( LPVOID lpParameter)    //客户线程
    {
        
    struct My my;
        memcpy(
    &my,lpParameter,sizeof(My));    
        printf(
    "One client connect!\n");
        
    char str1[1024];            //接收字符串
        char str2[1024];
                            
        
    int i;
        i
    =recv(my.skt,str1,sizeof(str1),0);    //接收客户请求
        str1[i]=0;

        
    char *filename;
        filename
    =new char[255];
        
    for(int j=2;j<i;j++)            //获得文件名
        {
            filename[j
    -2]=str1[j];
        }
        filename[i
    -2]=0;
       

        
    if (str1[0]=='S')
        {
            printf(
    "The file name : %s\n",filename);
            ofstream 
    out(filename);                //创文件流   
            if (!out)
            {
                printf(
    "cannot open file.\n");        //文件是否正确打开,打开错误则退出
                send(my.skt,"q",1,0);            //向客户发送退出信息
                closesocket(my.skt);            //解除客户连接;
                return 0;
            }
            str2[
    0]='O';                       
            str2[
    1]='K';
            str2[
    2]=0;
            send(my.skt,str2,strlen(str2),
    0);        //回复OK信息

            i
    =recv(my.skt,str1,sizeof(str1),0);        //接收文件长度
            str1[4]=0;
           
            
    int len;
            len
    =str1[0]*1000+str1[1]*100+str1[2]*10+str1[3];
            printf(
    "The File lenght is: %d Byte\n",len);
           
            
    for(int j=0;j<len;j++)
                {
                    
    char str[1];
                    i
    =recv(my.skt,str,sizeof(str),0);//接收文件,按字节接收,接收字符串为2个字节
                    str[i]=0;
                    
    out.put(str[0]);
                }

            
    out.close();                    //关闭文件
            printf("over!One client quit!\n");        //接收文件完毕
            closesocket(my.skt);                //解除此客户连接
            return 0;
        }

        
    if (str1[0]=='R')
        {       
           
            ifstream 
    in(filename);
            
    if (!in)
            {
                printf(
    "cannot open file or file not exist.\n");    //文件是否正确打开,打开错误则退出
                send(my.skt,"q",1,0);                    //向客户发送退出信息
                closesocket(my.skt);                    //解除客户连接;
                return 0;
            }
            
    char ch;
            
    int len=0;
            
    while(in.get(ch))
            {
                len
    ++;                            //get file lenght
            }
            
    in.close();
            str2[
    0]='O';
            str2[
    1]='K';
            str2[
    2]=len/1000;                       
            str2[
    3]=(len%1000)/100;
            str2[
    4]=(len%100)/10;
            str2[
    5]=len%10;
            printf(
    "%s",str2);
            send(my.skt,str2,
    6,0);                        //发OK+文件长度

            
    in.open(filename);
            
    if (!in)
            {
                printf(
    "cannot open file or file not exist.\n");    //文件是否正确打开,打开错误则退出
                send(my.skt,"q",1,0);                    //向客户发送退出信息
                closesocket(my.skt);                    //解除客户连接;
                return 0;
            }

            
    while(in.get(ch))                        //发文件
            {               
                
    char str[1];
                strcpy(str,
    "");
                str[
    0]=ch;
                str[
    1]=0;
                send(my.skt,str,
    1,0);                    //发送一个字符
            }
            
    in.close();
            printf(
    "over,One client quit!\n");                //传输文件完毕
            closesocket(my.skt);                        //解除此客户连接
            return 0;
        }

        printf(
    "Bad command!\n");
        closesocket(my.skt);
        
    return 0;
    }

            从这段代码中可以看到,当客户端和服务端建立连接后,客户端会先向服务端发送一个请求,该请求的第一个字节是大写的“S”或是“R”,分别向服务端写文件或是从服务端读取文件。从第三个字节开始,后面的内容是请求文件的文件名。

            服务端在接收到客户端的请求后,根据请求的类型,如果是“S”,则打开指定的文件,并返回一个字符串“OK”;如果是“R”,则打开指定的文件并向客户端发送“OK”+“文件长度”。

            随后,如果是“S”,则由客户端发送写入的文件长度和文件内容给服务端;如果是“R”,则向客户端发送文件的内容。

            到此我们已经完全明了了客户端和服务端的交互过程,因此,我们可以尝试在LR中建立一个脚本用户模拟客户端行为。

            下面我们以“S”的处理过程为例编写脚本。

            1、打开VUGen应用;
            2、新建脚本,选择“windows sockets”协议,不需录制;
            3、在Action Section中增加以下内容:
        //建立到服务端的连接
        lrs_create_socket("socket1","TCP","RemoteHost=127.0.0.1:8000",LrsLastArg);
       
        
    //发送“S”和文件名
        lrs_send("socket1""buf0", LrsLastArg);
        lrs_receive(
    "socket1""buf1", LrsLastArg);
       
        
    //发送要写入的数据的长度
        lrs_send("socket1""buf2", LrsLastArg);

        
    //发送数据内容
        lrs_send("socket1""buf3", LrsLastArg);
       
        
    //关闭连接
        lrs_close_socket("socket1");
       
            4、这样就成功的描述了整个交互过程,但还没有给出实际要发送的数据。在采用“Windows Sockets”协议的脚本中,实际发送的数据存放在data.ws Section中,因此,打开该Section,直接输入:
    send  buf0 7
        
    "S"
        
    "\x00"
        
    "1.txt"

    recv buf1 
    2
        
    "OK"

    send buf2 
    3
        
    "\x00"
        
    "\x00"
        
    "\x02"
        
    "\x00"

    send buf3 
    20
        
    "12345678901234567890"

            每个发送和接收的数据包在这里都有登记,“send”和“recv”表示数据的方向;“buf0”等表示数据包的描述,和脚本中的内容对应;接下来的一个整数表示数据包的长度;然后是数据包的内容,“\x00”表示16进制的00。

            该脚本描述了客户端向服务端请求写入一个文件1.txt,文件内容为“12345678901234567890”的过程。

           
          
  • LR学习点滴记录-IP Wizard使用

    2008-07-21 14:16:06

    LoadRunner 使用虚拟IP测试流程,设置虚拟IP地址:
     
    1、load Generator机器必须使用固定的IP,不能使用动态IP.确定网络中不冲突的IP地址
     
    2、打开:开始-〉程序-〉loadrunner-〉tools-〉ip wizard.
     
      第一项:增加新IP选择第一项;

       第二项:使用保存的文件增加IP选择

      第三项:释放已经设置的IP。
     
     点“下一步”

    3、此步让输入web server的IP地址,尚不清楚有何意义。不输入,直接点‘下一步’。
     
    4、点击add,增加虚拟ip

       点击remove按钮可以删除选定的虚拟IP.
     
    5、点击add后,在对话框中根据输入的IP的第一个值和数量,自动添加到虚拟IP列表中。

      例如:192.168.67.140  4,则增加的虚拟IP是:192.168.67.140、192.168.67.141、192.168.67.142、192.168.67.143.点ok按钮。点”完成“按钮。
     
      说明:使用Save as…可以将本次增加的IP保存成。ips文件,下次再使用时就可以直接选择此文件了。
     
      点‘OK’按钮即可
     
    6、重新启动计算机(可以重新启动网络连接即可)
     
      注意: 重新启动计算机后,设置的虚拟IP都生效了,此时使用ping会发现都能ping通,并且本机的IP也被改成了第一个虚拟IP地址。确认虚拟IP是否都生效的方法:在运行中输入cmd,在命令窗口录入ipconfig/all,然后就能看到已经生效的所有IP.
     
      使用虚拟IP(以手动方案为例)

      在controller中,选择 Scenario-〉Enable IP Spoofer,此项设置允许使用IP欺骗。按Generators按钮,设置虚拟用户生成器,将虚拟IP地址都添加进去,并连通。连接成功的虚拟用户生成器会在工具栏中显示。
     
    7、测试完成后,需要释放所有的虚拟ip并重新启动计算机。
     
      使用虚拟IP测试完成后 ,打开IP Wizard,释放所有虚拟IP.重新启动计算机。

     

  • LR学习点滴记录-socket录制关联

    2008-07-18 11:04:24

    转:

    今天写一下winsock的关联操作。

    以前看过一个文档。在英文版的讲winsock的,其中讲到关联。大致操作是:

    1,录制。

    2,回放。这里是失败。

    3,data.ws里找需要关联的数据。

    4,F7,打开EBCDIC translation对话框。

    5,查找数据的位置及偏移量。

    6,到脚本中写函数用:lrs_save_param, lrs_save_param_ex, lrs_save_searched_string,这三个函数。

     

    Notes:winsock的关联函数要写到需要关联的代码行的下面。

     

    说明一下这几个函数:

    Lrs_save_param:

    int lrs_save_param ( char *s_desc,char *buf_desc, char *param_name, int offset, int param_len);

    这个函数保存buffer中的数据到一个参数里。这个函数是用来在脚本中做关联的。

    前两个参数是为了指定特定的参数。

    在指定活动的socketbuffer之后,需要指定一个参数来保存数据。指定偏移量来显示buffer中数据的偏移量和数据的长度。

    保存了参数之后,可以在脚本和数据文件使用它,代替所有需要替代的值。替换时要用选项中的定义的符号来引用。

    注意:要从buffer中保存一个编码过的数据到参数中,要用lrs_save_param_ex函数。

    lrs_save_param_ex

    int lrs_save_param_ex ( char *s_desc, char *type, char *buff, int offset, int length, char *encoding, char *param );

    这个函数保存一个buffer或者一个buffer的某一部分到参数中。这个变量指定buffer中某种类型的数据被保存:用户buffer,录制的buffer,或者上一个接收到的buffer.推荐使用在用户数据中。

    [Z1] 

     

     

    下面说不用这么麻烦的操作的,直接点几下就可以了。

     

    1         录制脚本

    这个没什么说的吧。选择协议winsock,这要是也不懂,我建议你去看十遍手册。

    我这里录制到的脚本如下:

           lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=192.168.1.114:5560", LrsLastArg);

           lrs_send("socket0", "buf0", LrsLastArg);

           lrs_receive("socket0", "buf1", LrsLastArg);

           lrs_create_socket("socket1", "TCP", "LocalHost=0", "RemoteHost=192.168.1.114:5560", LrsLastArg);

           lrs_send("socket1", "buf2", LrsLastArg);

           lrs_receive("socket1", "buf3", LrsLastArg);

    相应的data.ws如下:

    ;WSRData 2 1

     

    send buf0 50

           "OPERTYPE(LOGIN)ACCOUNTNAME(admin)PASSWORD(admin)"

     

    recv buf1 155

           "DATALEN{{155}}000000USERID{{90}}USERNAME{{DMS"

           "\xcf\xb5\xcd\xb3"

           "WEB"

           "\xb2\xe9\xd1\xaf\xd5\xca\xbb\xa7"

           "}}USERDESCRIBE{{"

           "\xba\xfe\xd6\xdd\xb5\xe7\xc1\xa6\xbe\xd6"

           "\\DMS"

           "\xcf\xb5\xcd\xb3"

           "WEB"

           "\xb2\xe9\xd1\xaf\xd5\xca\xbb\xa7"

           "}}DEPARTNAME{{"

           "\xce\xb4\xd6\xaa"

           "}}ADMIN{{0}}CLIENTSESSIONID{{2}}"

     

    send buf2 53

           "CLIENTSESSIONID(2)OPERTYPE(INITDEPARTLIST)"

     

    recv buf3 683

           "DATALEN{{683}}000000XMLDATA{{<?xml version=\"1.0\" encoding=\"GB2312\"?>\n"

           "<!DOCTYPE DepartList>\n"

           "<DepartList>\n"

           ………………………………………………………………………………………………

    这里就省略了些数据。反正也看着也晕乎乎的。

    这里说明一下,我这里是用GIS系统,需要sessionID关联的。我这上面的代码很简单,在buf1中有一个sessionID,在buf2send时就用到了它。

    2         回放一下

    在不关联时回放是一定会有问题的。我回放的结果是:

    Virtual User scrīpt started

    Starting action vuser_init.

    Ending action vuser_init.

    Running Vuser...

    Starting iteration 1.

    Starting action Action.

    Action.c(4): lrs_create_socket(socket0, TCP, ...)

    Action.c(6): lrs_send(socket0, buf0)

    Action.c(8): lrs_receive(socket0, buf1)

    Action.c(11): lrs_create_socket(socket1, TCP, ...)

    Action.c(13): lrs_send(socket1, buf2)

    Action.c(15): lrs_receive(socket1, buf3)

    Action.c(15): Mismatch (expected 683 bytes, 42 bytes actually received)

    Action.c(17): lrs_create_socket(socket2, TCP, ...)

    Action.c(19): lrs_send(socket2, buf4)

    Action.c(21): lrs_receive(socket2, buf5)

    Action.c(21): Mismatch (expected 34143 bytes, 42 bytes actually received)

    Action.c(23): lrs_create_socket(socket3, TCP, ...)

    Action.c(25): lrs_send(socket3, buf6)

    Action.c(27): lrs_receive(socket3, buf7)

    Action.c(27): Mismatch (expected 100 bytes, 42 bytes actually received)

    Action.c(29): lrs_create_socket(socket4, TCP, ...)

    Action.c(31): lrs_send(socket4, buf8)

    Action.c(33): lrs_receive(socket4, buf9)

    Action.c(33): Mismatch (expected 134 bytes, 42 bytes actually received)

    Action.c(35): lrs_send(socket4, buf10)

    Action.c(38): lrs_receive(socket4, buf11)

    Action.c(38): Mismatch (expected 17520 bytes, 42 bytes actually received)

    Action.c(41): lrs_create_socket(socket5, TCP, ...)

    Action.c(43): lrs_send(socket5, buf12)

    Action.c(45): lrs_receive(socket5, buf13)

    Ending action Action.

    Ending iteration 1.

    Ending Vuser...

    Starting action vuser_end.

    Ending action vuser_end.

    Vuser Terminated.

    主要来看一下蓝色的部分,因为没有关联,服务器是返回了42字节的数据,但是和录制时的数据是不同的。所以会mismatch。这里可以在LOGMismatch的值打印出来,不过太长了,我就不打印了。^@^

    3         转到树视图做关联

    选择buf1看到数据:

    DATALEN{{155}}000000USERID{{90}}USERNAME{{DMS\xcf\xb5\xcd\xb3WEB\xb2\xe9\xd1\xaf\xd5\xca\xbb\xa7}}USERDESCRIBE{{\xba\xfe\xd6\xdd\xb5\xe7\xc1\xa6\xbe\xd6\\DMS\xcf\xb5\xcd\xb3WEB\xb2\xe9\xd1\xaf\xd5\xca\xbb\xa7}}DEPARTNAME{{\xce\xb4\xd6\xaa}}ADMIN{{0}}CLIENTSESSIONID{{2}}

    选择CLIENTSESSIONID{{2}}中的2.右击后选择:create parameter。在弹出窗口中。看到默认的是用lrs_save_param,这个函数只能关联固定长度的数据。如果是固定的话,到这里点击一下OK,就关联成功了。LR会自动生成语句并且提示检查其他的需要关联的地方。弹出一个窗口提示。

    而我这里的sessionID是动态的值。所以需要选择:extract parameter data using boundaries复选框。这时生成的语句是这样的:

    lrs_save_searched_string( "socket0", LRS_LAST_RECEIVED, "Parameter3", NULL, NULL, -1, 152, 1 );

    左右边界是NULL空的,这里点击left的浏览,弹出选择左边界的窗口,用鼠标选择:SESSIONID{{,点击Done

    再点击right浏览,选择}}

    就确定了左右边界了。

    这里的语句如下:

    lrs_save_searched_string("socket0",LRS_LAST_RECEIVED,"Parameter4","LB/BIN=SESSIONID{{", "RB/BIN=}}", 1, 0, -1);

    一路小跑点OK

    弹出提示是否替换所有符合左右边界的值。

    点击yesLR会自动搜索所有需要关联的地方并替换。

    再转到脚本视图,看到脚本如下:

      lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=192.168.1.114:5560", LrsLastArg);

           lrs_send("socket0", "buf0", LrsLastArg);

           lrs_receive("socket0", "buf1", LrsLastArg);  

       lrs_save_searched_string("socket0", LRS_LAST_RECEIVED, "Parameter1", "LB/BIN=SESSIONID{{", "RB/BIN=}}", 1, 0, -1);

        lr_output_message("小样还抓不到你!你不就是: %s嘛!",lr_eval_string("{Parameter1}"));       lrs_create_socket("socket1", "TCP", "LocalHost=0", "RemoteHost=192.168.1.114:5560", LrsLastArg);

           lrs_send("socket1", "buf2", LrsLastArg);

           lrs_receive("socket1", "buf3", LrsLastArg);

    看蓝色部分。后面一句输出是我加上去的。

    这样就关联成功了。

    4         再次回放

    看到LOG如下:

    Virtual User scrīpt started

    Starting action vuser_init.

    Ending action vuser_init.

    Running Vuser...

    Starting iteration 1.

    Starting action Action.

    Action.c(4): lrs_create_socket(socket0, TCP, ...)

    Action.c(6): lrs_send(socket0, buf0)

    Action.c(8): lrs_receive(socket0, buf1)

    Action.c(10): lrs_save_searched_string(socket0, get_last_received_buffer, Parameter1, LB/BIN=SESSIONID{{, RB/BIN=}}, 1, 0, -1)

    Action.c(12): 小样还抓不到你!你不就是: 8嘛!

    Action.c(14): lrs_create_socket(socket1, TCP, ...)

    Action.c(16): lrs_send(socket1, buf2)

    Action.c(18): lrs_receive(socket1, buf3)

    Action.c(20): lrs_create_socket(socket2, TCP, ...)

    Action.c(22): lrs_send(socket2, buf4)

    Action.c(24): lrs_receive(socket2, buf5)

    Action.c(26): lrs_create_socket(socket3, TCP, ...)

    Action.c(28): lrs_send(socket3, buf6)

    Action.c(30): lrs_receive(socket3, buf7)

    Action.c(32): lrs_create_socket(socket4, TCP, ...)

    Action.c(34): lrs_send(socket4, buf8)

    Action.c(36): lrs_receive(socket4, buf9)

    Action.c(38): lrs_send(socket4, buf10)

    Action.c(41): lrs_receive(socket4, buf11)

    Action.c(44): lrs_create_socket(socket5, TCP, ...)

    Action.c(46): lrs_send(socket5, buf12)

    Action.c(48): lrs_receive(socket5, buf13)

    Ending action Action.

    Ending iteration 1.

    Ending Vuser...

    Starting action vuser_end.

    Ending action vuser_end.

    Vuser Terminated.

    看,输出了:

    Action.c(12): 小样还抓不到你!你不就是: 8嘛!

     

     

     

    完。

     


     [Z1]这里还没写完。还有另一个函数解释。

  • LR学习点滴记录-错误日志查看

    2008-07-17 16:11:14

    1、在LR运行后生成的res文件夹里面。有log文件夹,里面有各个虚拟用户错误运行的记录。可以查看

    2、在analysis中可以通过查看.mdb这个文件来查看运行场景是出现的错误信息。

    用access打开.mdb,之后,选择Error message,最后打开。

    3、通过在.mdb文件中的修改,可以对lr的性能测试结果产生影响

  • LR学习点滴记录-参数设置

    2008-07-17 15:02:15

    转:

    一、关于参数的定义
    在你录制程序运行的过程中,脚本生成器自动生成由函数组成的用户脚本。函数中参数的值就是在录制过程中输入的实际值。
    例如,你录制了一个Web应用程序的脚本。脚本生成器生成了一个声明,该声明搜索名称为“UNIX”的图书的数据库。
    当你用多个虚拟用户和迭代回放脚本时,也许你不想重复使用相同的值“UNIX”。那么,你就可以用参数来取代这个常量。
    结果就是你可以用指定的数据源的数值来取代参数值。数据源可以是一个文件,也可以是内部产生的变量。
    用参数表示用户的脚本有两个优点:
    ① 可以使脚本的长度变短。
    ② 可以使用不同的数值来测试你的脚本。例如,如果你企图搜索不同名称的图书,你仅仅需要写提交函数一次。在回放的过程中,你可以使用不同的参数值,而不只搜索一个特定名称的值。
    参数化包含以下两项任务:
    ① 在脚本中用参数取代常量值。
    ② 设置参数的属性以及数据源。
    参数化仅可以用于一个函数中的参量。你不能用参数表示非函数参数的字符串。
    另外,不是所有的函数都可以参数化的。
    二、参数的创建
    可以指定名称和类型来创建参数。不存在对脚本中参数个数的限制。
    在Web程序的用户脚本中,你可以使用如下过程在基于文本的脚本视图中创建参数。或者,也可以在基于图标的树形视图中创建参数。
    要创建一个参数:
    1、 将光标定位在要参数化的字符上,点击右键。打开弹出菜单。
    2、 在弹出菜单中,选择“Replace with a Parameter”。选择或者创建参数的对话框弹出。
    3、 在“Parameter name”中输入参数的名称,或者选择一个在参数列表中已经存在的参数。
    4、 在“Parameter type”下拉列表中选择参数类型。
    5、 点击“OK”,关闭该对话框。脚本生成器便会用参数中的值来取代脚本中被参数化的字符,参数用一对“{}”括住。
    注意:在参数化CORBA或者General-Java 用户脚本的时候,必须参数化整个字符串,而不是其中的部分。
    另外注意:除了Web或者WAP,缺省的参数括号对于任何脚本都是 “{}”。你可以在“General Options”对话框中的“Parameterization”标签(Tools>General Options)中定义参数括号种类。
    6、 用同样的参数替换字符的其余情况,选中参数,点击右键,弹出菜单。从弹出的菜单中,选择“Replace More Occurrences”。搜索和替换对话框弹出。
    “Find What”中显示了你企图替换的值。“Replace With”中显示了括号中参数的名称。
    选择适当的检验框来匹配整个字符或者大小写。如果要搜索规则的表达式(.,!,?等等),选中“Regular Expression”检验框,然后点击“Replace”或者“Replace All”。
    注意:小心使用“Replace All”,尤其替换数字字符串的时候。脚本生成器将会替换字符出现的所有情况。
    7、 如果想用以前定义过的参数来替换常量字符串的话,选中该字符串,点击右键,然后选择“Use Existing Parameter”,子菜单“Use Existing Parameters”弹出。
    从子菜单“Use Existing Parameters”选择参数,或者用“Select from Parameter List”来打开参数列表对话框。
    注意:如果用以前定义过的参数来替换常量字符串的话,那么,使用“Parameter List”非常方便。同时,还可以查看和修改该参数的属性。
    8、 对于已经用参数替换过的地方,如果想取回原来的值,那么,就在参数上点击右键,然后选择“Restore Original Value”。
    在Web用户脚本的树形视图中创建参数
    在Web用户脚本的树形视图中创建一个参数的步骤
    1、将光标定位在企图参数化的地方,点击右键,从弹出的菜单中选择“Properties”。则相关的属性对话框打开。
    2、点击在要参数化的参量的旁边的“ABC”形状的图标。“Select or Create Parameter”对话框打开。
    3、在“Parameter name”中输入参数的名称,或者从列表中选择一个已经存在的参数。
    4、在“Parameter type”中输入参数的类型。
    5、点击“OK”关闭该对话框。用户脚本生成器会用参数来替换最初的字符串常量,并用一个表格形状的图标替换“ABC”形状的图标。
    6、要恢复参数化以前的值,点击图标,然后从弹出的菜单中选择“Undo Parameter”,则以前的值便会重现。
    三、定义参数的属性
    创建参数完成后,就可以定义其属性了。参数的属性定义就是定义在脚本执行过程中,参数使用的数据源。
    在Web用户脚本中,你既可以在基于文本的脚本视图中定义参数属性,也可以在基于图标的树形视图中定义参数属性。下面的过程将教你如何在基于本文的脚本视图中定义参数属性。
    定义参数属性步骤:
    1、 在参数上点击右键,有菜单弹出。
    2、 在弹出的菜单中,选择“Parameter Properties”。参数属性对话框打开,显示和当前参数类型相关的属性。
    3、 输入参数的属性值。
    4、 点击“Close”关闭参数属性对话框。
    在Web用户脚本的树形视图中定义参数的属性
    1、 将关标定位在参数上,然后点击右键,选择“Properties”。属性对话框打开。
    2、 点击要定义属性的参数旁边的表格形状按钮,点击右键,选择“Parameter Properties”。参数属性对话框打开,和参数类型相关的属性显示出来。
    3、 输入参数的属性。
    4、 点击“Close”关闭参数属性对话框。
    使用参数列表
    使用参数列表可以在任意时刻查看所有的参数,创建新的参数、删除参数,或者修改已经存在参数的属性。
    要使用参数列表:
    1、 点击参数列表按钮或者用“Vuser>Parameter List”。参数列表对话框打开。
    2、 要创建新的参数,点击“New”按钮。新的参数则被添加在参数树中,该参数有一个临时的名字,你可以给它重新命名,然后回车。
    注意:不要将一个参数命名为“unique”,因为这个名称是用户脚本生成器本身的。
    设置参数的类型和属性,点击“OK”,关闭参数列表对话框。
    注意:用户脚本生成器创建新的参数,但是不会自动用该参数在脚本中替换任意选中的字符串。
    3、 要删除已有的参数,那么,要先从参数树中选择该参数,点击“Delete”,然后确认你的行为即可。
    4、 要修改已有参数,那么,要先从参数树中选择该参数,然后编辑参数的类型和属性。
    四、理解参数的类型
    在你定义参数属性的时候,要指定参数值的数据源。你可以指定下列数据源类型的任何一种:
    Internal Data 虚拟用户内部产生的数据。
    Data Files 存在于文件中的数据。可能是已存在的文件或者是用脚本生成器新创建的。
    User-Defined Functions 调用外部DLL函数生成的数据
    Internal Data包括以下几种:
    1. Date/Time
    Date/Time用当前的日期/时间替换参数。要指定一个Date/Time格式,你可以从菜单列表中选择格式,或者指定你自己的格式。这个格式应该和你脚本中录制的Date/Time格式保持一致。
    2. Group Name
    Group Name 用虚拟用户组名称替换参数。在创建scenario的时候,你可以指定虚拟用户组的名称。当从用户脚本生成器运行脚本的时候,虚拟用户组名称总是None。
    3. Load Generator Name
    Load Generator Name用脚本负载生成器的名称替换参数。负载生成器是虚拟用户在运行的计算机。
    4. Iteration Number
    Iteration Number用当前的迭代数目替换参数。
    5. Random Number
    Random Number用一个随机数替换参数。通过指定最大值和最小值来设置随机数的范围。
    6. Unique Number
    Unique Number用一个唯一的数字来替换参数。你可以指定一个起始数字和一个块的大小。
    7. Vuser ID
    Vuser ID用分配给虚拟用户的ID替换参数,ID是由Loadrunner的控制器在scenario运行时生成的。如果你从脚本生成器运行脚本的话,虚拟用户的ID总是-1。
    五、数据文件
    数据文件包含着脚本执行过程中虚拟用户访问的数据。局部和全局文件中都可以存储数据。可以指定现有的ASCII文件、用脚本生成器创建一个新的文件或者引入一个数据库。在参数有很多已知值的时候数据文件非常有用。
    数据文件中的数据是以表的形式存储的。一个文件中可以包含很多参数值。每一列包含一个参数的数据。列之间用分隔符隔开,比如说,用逗号。
    对数据文件设置参数属性
    如果使用文件作为参数的数据源,必须指定以下内容:
    1. 文件的名称和位置
    2. 包含数据的列
    3. 文件格式,包括列的分隔符
    4. 更新方法
    如果参数的类型是“File”,打开参数属性(Parameter Properties)对话框,设置文件属性如下:
    1. 在“File path”中输入文件的位置,或者点击“Browse”指定一个已有文件的位置。缺省情况下,所有新的数据文件名都是“parameter_name.dat”,注意,已有的数据文件的后缀必须是.dat。
    2. 点击“Edit”。记事本打开,里面第一行是参数的名称,第二行是参数的初始值。使用诸如逗号之类的分隔符将列隔开。对于每一新的表行开始一行新的数据。
    注意:在没有启动记事本的情况下如果想添加列,就在参数属性对话框中点击“Add Col”,那么“Add new column”对话框就会弹出。输入新列的名称,点击“OK”。脚本生成器就会添加该列到表中,并显示该列的初始值。
    3. 在“Select Column”部分,指明包含当前参数数据的列。你可以指定列名或者列号。列号是包含你所需要数据的列的索引。列名显示在每列的第一行(row 0)。
    4. 在“Column delimiter”中输入列分隔符,你可以指定逗号、空格符等等。
    5. 在“First data line”中,在脚本执行的时候选择第一行数据使用。列标题是第0行。若从列标题后面的第一行开始的话,那就在“First data line”中输入1。如果没有列标题,就输入0。
    6. 在“Select next row”中输入更新方法,以说明虚拟用户在脚本执行的过程中如何选择表中的数据。方法可以是:连续的、随机的、唯一的、或者与其它参数表的相同行。
    7. 选中“Advance row each iteration”表示虚拟用户在每次迭代都使用新的一行数据而不是所有的迭代都使用相同的数据。
    从文件中更新参数值
    若使用文件中的数值,脚本生成器会要求你指定给参数分配数值给的方法。可用的方法有:
    1. 顺序(Sequential):该方法顺序地给虚拟用户分配参数值。如果正在运行的虚拟用户访问数据表的时候,它会取到下一行中可用的数据。
    2. 随机(Random):该方法在每次迭代的时候会从数据表中取随机数
    3. 使用种子取随机顺序(Use Random Sequence with Seed):如果从Loadrunner的控制器来运行scenario,你可以指定一个种子数值用于随机顺序。每一个种子数值在测试执行的时候代表了一个随机数的顺序。无论你何时使用这个种子数值,在scenario中同样的数据顺序就被分配给虚拟用户。如果在测试执行的时候发现了一个问题并且企图使用同样的随机数序列来重复测试,那么,你就可以启动这个功能(可选项)。
    4. 唯一(Unique):Unique方法分配一个唯一的有顺序的值给每个虚拟用户的参数。
    5. 与以前定义的参数取同一行(Same Line As <parameter>):该方法从和以前定义过的参数中的同样的一行分配数据。你必须指定包含有该数据的列。在下拉列表中会出现定义过的所有参数列表。注意:至少其中的一个参数必须是Sequential、Random或者Unique。
    如果数据表中有三列,三个参数定义在列表中:id1,name1和title1,如下:。
    ID Name Title
    132 Kim Manager
    187 Cassie Engineer
    189 Jane VP
    对于参数id1,你可以指示虚拟用户使用Random方法,而为参数name1和title1就可以指定方法“Same Line as id1”。所以,一旦ID“132”被使用,那么,姓名(Name)“Kim”和职位(Title)“Manager”同时被使用。
    六、从已存在的数据库中导入数据
    Loadrunner允许你利用参数化从已经存在的数据库中导入数据。可以使用下列两种方式之一:
    1. 使用Microsoft Query(要求在系统上先安装MS Query)。
    2. 指定数据库连接字符串和SQL语句。
    用户脚本生成器在从数据库中导入数据的过程中提供了一个向导。在向导中,你指明如何导入数据-通过MS Query创建查询语句或者直接书写SQL语句。在导入数据以后,以.dat为后缀并作为正规的参数文件保存。
    要开始导入数据库中数据的过程,在参数属性对话框中点击“Data Wizard”,则,数据库查询向导弹出。
    要创建新的查询
    1. 选择“Create new query”。如果需要MS Query的帮助,选择“Show me how to use Microsoft Query”,然后点击“Finish”。
    如果你还没有安装Microsoft Query,Loadrunner会提示你这个功能不可用。在进行之前,从Microsoft Office中安装MS Query。
    2. 在Microsoft Query中遵循以下步骤,导入期望的表和列。
    3. 在完成数据的导入后,选择“Exit and return to Virtual User Generator”,然后点击“Finish”。在参数属性对话框中数据库记录以data文件的形式显示出来。
    要在MS Query中编辑并查看数据,选择“View data or edit in Microsoft Query”。若要结束,则选择“File>Exit and return to Virtual User Generator”返回到脚本生成器。
    4. 在“Select Column”部分,指定包含当前参数数据的列可以指定列号或者列名。注意:列标题默认为第0行(row 0)。
    5. 从“Select next row”列表中选择一个更新方法来告诉虚拟用户在脚本指定的过程中如何选择表中的数据。可选项是:Sequential、Random、Unique或者Same Line As。其中每一项的含义文章前面已经讲述,就不再赘述。
    6. 如果选择“Advance row each iteration”,虚拟用户在每次迭代的时候会使用新的一行的数据而不是重复同样的数据。
    要指定数据库连接或者SQL语句
    1. 选择“Specify SQL Statement”,然后点击“Next”。
    2. 点击“Create”指定一个新的连接字符串。选择数据源的窗口弹出。
    3. 选择已有的数据源,或者点击“New”创建一个新的数据源。向导将提示你穿过创建ODBC数据源的过程。在完成后,连接字符串就会在连接字符串框中显示出来。
    4. 在SQL框中,输入或者粘贴SQL语句。
    5. 点击“Finish”继续SQL语句并导入数据。数据库记录将以data文件的形式显示在参数属性框中。
    6. 在“Select Column”部分中,指定包含当前参数数据的列。你可以指定列号或者列名。
    7. 从“Select next row”列表中选择一个更新方法来告诉虚拟用户在脚本指定的过程中如何选择表中的数据。可选项是:Sequential、Random、Unique或者Same Line As。
    8. 如果选择“Advance row each iteration”,虚拟用户在每次迭代的时候会使用新的一行的数据而不是重复同样的数据。 一、关于参数的定义
    在你录制程序运行的过程中,脚本生成器自动生成由函数组成的用户脚本。函数中参数的值就是在录制过程中输入的实际值。
    例如,你录制了一个Web应用程序的脚本。脚本生成器生成了一个声明,该声明搜索名称为“UNIX”的图书的数据库。
    当你用多个虚拟用户和迭代回放脚本时,也许你不想重复使用相同的值“UNIX”。那么,你就可以用参数来取代这个常量。
    结果就是你可以用指定的数据源的数值来取代参数值。数据源可以是一个文件,也可以是内部产生的变量。
    用参数表示用户的脚本有两个优点:
    ① 可以使脚本的长度变短。
    ② 可以使用不同的数值来测试你的脚本。例如,如果你企图搜索不同名称的图书,你仅仅需要写提交函数一次。在回放的过程中,你可以使用不同的参数值,而不只搜索一个特定名称的值。
    参数化包含以下两项任务:
    ① 在脚本中用参数取代常量值。
    ② 设置参数的属性以及数据源。
    参数化仅可以用于一个函数中的参量。你不能用参数表示非函数参数的字符串。
    另外,不是所有的函数都可以参数化的。
    二、参数的创建
    可以指定名称和类型来创建参数。不存在对脚本中参数个数的限制。
    在Web程序的用户脚本中,你可以使用如下过程在基于文本的脚本视图中创建参数。或者,也可以在基于图标的树形视图中创建参数。
    要创建一个参数:
    1、 将光标定位在要参数化的字符上,点击右键。打开弹出菜单。
    2、 在弹出菜单中,选择“Replace with a Parameter”。选择或者创建参数的对话框弹出。
    3、 在“Parameter name”中输入参数的名称,或者选择一个在参数列表中已经存在的参数。
    4、 在“Parameter type”下拉列表中选择参数类型。
    5、 点击“OK”,关闭该对话框。脚本生成器便会用参数中的值来取代脚本中被参数化的字符,参数用一对“{}”括住。
    注意:在参数化CORBA或者General-Java 用户脚本的时候,必须参数化整个字符串,而不是其中的部分。
    另外注意:除了Web或者WAP,缺省的参数括号对于任何脚本都是 “{}”。你可以在“General Options”对话框中的“Parameterization”标签(Tools>General Options)中定义参数括号种类。
    6、 用同样的参数替换字符的其余情况,选中参数,点击右键,弹出菜单。从弹出的菜单中,选择“Replace More Occurrences”。搜索和替换对话框弹出。
    “Find What”中显示了你企图替换的值。“Replace With”中显示了括号中参数的名称。
    选择适当的检验框来匹配整个字符或者大小写。如果要搜索规则的表达式(.,!,?等等),选中“Regular Expression”检验框,然后点击“Replace”或者“Replace All”。
    注意:小心使用“Replace All”,尤其替换数字字符串的时候。脚本生成器将会替换字符出现的所有情况。
    7、 如果想用以前定义过的参数来替换常量字符串的话,选中该字符串,点击右键,然后选择“Use Existing Parameter”,子菜单“Use Existing Parameters”弹出。
    从子菜单“Use Existing Parameters”选择参数,或者用“Select from Parameter List”来打开参数列表对话框。
    注意:如果用以前定义过的参数来替换常量字符串的话,那么,使用“Parameter List”非常方便。同时,还可以查看和修改该参数的属性。
    8、 对于已经用参数替换过的地方,如果想取回原来的值,那么,就在参数上点击右键,然后选择“Restore Original Value”。
    在Web用户脚本的树形视图中创建参数
    在Web用户脚本的树形视图中创建一个参数的步骤
    1、将光标定位在企图参数化的地方,点击右键,从弹出的菜单中选择“Properties”。则相关的属性对话框打开。
    2、点击在要参数化的参量的旁边的“ABC”形状的图标。“Select or Create Parameter”对话框打开。
    3、在“Parameter name”中输入参数的名称,或者从列表中选择一个已经存在的参数。
    4、在“Parameter type”中输入参数的类型。
    5、点击“OK”关闭该对话框。用户脚本生成器会用参数来替换最初的字符串常量,并用一个表格形状的图标替换“ABC”形状的图标。
    6、要恢复参数化以前的值,点击图标,然后从弹出的菜单中选择“Undo Parameter”,则以前的值便会重现。
    三、定义参数的属性
    创建参数完成后,就可以定义其属性了。参数的属性定义就是定义在脚本执行过程中,参数使用的数据源。
    在Web用户脚本中,你既可以在基于文本的脚本视图中定义参数属性,也可以在基于图标的树形视图中定义参数属性。下面的过程将教你如何在基于本文的脚本视图中定义参数属性。
    定义参数属性步骤:
    1、 在参数上点击右键,有菜单弹出。
    2、 在弹出的菜单中,选择“Parameter Properties”。参数属性对话框打开,显示和当前参数类型相关的属性。
    3、 输入参数的属性值。
    4、 点击“Close”关闭参数属性对话框。
    在Web用户脚本的树形视图中定义参数的属性
    1、 将关标定位在参数上,然后点击右键,选择“Properties”。属性对话框打开。
    2、 点击要定义属性的参数旁边的表格形状按钮,点击右键,选择“Parameter Properties”。参数属性对话框打开,和参数类型相关的属性显示出来。
    3、 输入参数的属性。
    4、 点击“Close”关闭参数属性对话框。
    使用参数列表
    使用参数列表可以在任意时刻查看所有的参数,创建新的参数、删除参数,或者修改已经存在参数的属性。
    要使用参数列表:
    1、 点击参数列表按钮或者用“Vuser>Parameter List”。参数列表对话框打开。
    2、 要创建新的参数,点击“New”按钮。新的参数则被添加在参数树中,该参数有一个临时的名字,你可以给它重新命名,然后回车。
    注意:不要将一个参数命名为“unique”,因为这个名称是用户脚本生成器本身的。
    设置参数的类型和属性,点击“OK”,关闭参数列表对话框。
    注意:用户脚本生成器创建新的参数,但是不会自动用该参数在脚本中替换任意选中的字符串。
    3、 要删除已有的参数,那么,要先从参数树中选择该参数,点击“Delete”,然后确认你的行为即可。
    4、 要修改已有参数,那么,要先从参数树中选择该参数,然后编辑参数的类型和属性。
    四、理解参数的类型
    在你定义参数属性的时候,要指定参数值的数据源。你可以指定下列数据源类型的任何一种:
    Internal Data 虚拟用户内部产生的数据。
    Data Files 存在于文件中的数据。可能是已存在的文件或者是用脚本生成器新创建的。
    User-Defined Functions 调用外部DLL函数生成的数据
    Internal Data包括以下几种:
    1. Date/Time
    Date/Time用当前的日期/时间替换参数。要指定一个Date/Time格式,你可以从菜单列表中选择格式,或者指定你自己的格式。这个格式应该和你脚本中录制的Date/Time格式保持一致。
    2. Group Name
    Group Name 用虚拟用户组名称替换参数。在创建scenario的时候,你可以指定虚拟用户组的名称。当从用户脚本生成器运行脚本的时候,虚拟用户组名称总是None。
    3. Load Generator Name
    Load Generator Name用脚本负载生成器的名称替换参数。负载生成器是虚拟用户在运行的计算机。
    4. Iteration Number
    Iteration Number用当前的迭代数目替换参数。
    5. Random Number
    Random Number用一个随机数替换参数。通过指定最大值和最小值来设置随机数的范围。
    6. Unique Number
    Unique Number用一个唯一的数字来替换参数。你可以指定一个起始数字和一个块的大小。
    7. Vuser ID
    Vuser ID用分配给虚拟用户的ID替换参数,ID是由Loadrunner的控制器在scenario运行时生成的。如果你从脚本生成器运行脚本的话,虚拟用户的ID总是-1。
    五、数据文件
    数据文件包含着脚本执行过程中虚拟用户访问的数据。局部和全局文件中都可以存储数据。可以指定现有的ASCII文件、用脚本生成器创建一个新的文件或者引入一个数据库。在参数有很多已知值的时候数据文件非常有用。
    数据文件中的数据是以表的形式存储的。一个文件中可以包含很多参数值。每一列包含一个参数的数据。列之间用分隔符隔开,比如说,用逗号。
    对数据文件设置参数属性
    如果使用文件作为参数的数据源,必须指定以下内容:
    1. 文件的名称和位置
    2. 包含数据的列
    3. 文件格式,包括列的分隔符
    4. 更新方法
    如果参数的类型是“File”,打开参数属性(Parameter Properties)对话框,设置文件属性如下:
    1. 在“File path”中输入文件的位置,或者点击“Browse”指定一个已有文件的位置。缺省情况下,所有新的数据文件名都是“parameter_name.dat”,注意,已有的数据文件的后缀必须是.dat。
    2. 点击“Edit”。记事本打开,里面第一行是参数的名称,第二行是参数的初始值。使用诸如逗号之类的分隔符将列隔开。对于每一新的表行开始一行新的数据。
    注意:在没有启动记事本的情况下如果想添加列,就在参数属性对话框中点击“Add Col”,那么“Add new column”对话框就会弹出。输入新列的名称,点击“OK”。脚本生成器就会添加该列到表中,并显示该列的初始值。
    3. 在“Select Column”部分,指明包含当前参数数据的列。你可以指定列名或者列号。列号是包含你所需要数据的列的索引。列名显示在每列的第一行(row 0)。
    4. 在“Column delimiter”中输入列分隔符,你可以指定逗号、空格符等等。
    5. 在“First data line”中,在脚本执行的时候选择第一行数据使用。列标题是第0行。若从列标题后面的第一行开始的话,那就在“First data line”中输入1。如果没有列标题,就输入0。
    6. 在“Select next row”中输入更新方法,以说明虚拟用户在脚本执行的过程中如何选择表中的数据。方法可以是:连续的、随机的、唯一的、或者与其它参数表的相同行。
    7. 选中“Advance row each iteration”表示虚拟用户在每次迭代都使用新的一行数据而不是所有的迭代都使用相同的数据。
    从文件中更新参数值
    若使用文件中的数值,脚本生成器会要求你指定给参数分配数值给的方法。可用的方法有:
    1. 顺序(Sequential):该方法顺序地给虚拟用户分配参数值。如果正在运行的虚拟用户访问数据表的时候,它会取到下一行中可用的数据。
    2. 随机(Random):该方法在每次迭代的时候会从数据表中取随机数
    3. 使用种子取随机顺序(Use Random Sequence with Seed):如果从Loadrunner的控制器来运行scenario,你可以指定一个种子数值用于随机顺序。每一个种子数值在测试执行的时候代表了一个随机数的顺序。无论你何时使用这个种子数值,在scenario中同样的数据顺序就被分配给虚拟用户。如果在测试执行的时候发现了一个问题并且企图使用同样的随机数序列来重复测试,那么,你就可以启动这个功能(可选项)。
    4. 唯一(Unique):Unique方法分配一个唯一的有顺序的值给每个虚拟用户的参数。
    5. 与以前定义的参数取同一行(Same Line As <parameter>):该方法从和以前定义过的参数中的同样的一行分配数据。你必须指定包含有该数据的列。在下拉列表中会出现定义过的所有参数列表。注意:至少其中的一个参数必须是Sequential、Random或者Unique。
    如果数据表中有三列,三个参数定义在列表中:id1,name1和title1,如下:。
    ID Name Title
    132 Kim Manager
    187 Cassie Engineer
    189 Jane VP
    对于参数id1,你可以指示虚拟用户使用Random方法,而为参数name1和title1就可以指定方法“Same Line as id1”。所以,一旦ID“132”被使用,那么,姓名(Name)“Kim”和职位(Title)“Manager”同时被使用。
    六、从已存在的数据库中导入数据
    Loadrunner允许你利用参数化从已经存在的数据库中导入数据。可以使用下列两种方式之一:
    1. 使用Microsoft Query(要求在系统上先安装MS Query)。
    2. 指定数据库连接字符串和SQL语句。
    用户脚本生成器在从数据库中导入数据的过程中提供了一个向导。在向导中,你指明如何导入数据-通过MS Query创建查询语句或者直接书写SQL语句。在导入数据以后,以.dat为后缀并作为正规的参数文件保存。
    要开始导入数据库中数据的过程,在参数属性对话框中点击“Data Wizard”,则,数据库查询向导弹出。
    要创建新的查询
    1. 选择“Create new query”。如果需要MS Query的帮助,选择“Show me how to use Microsoft Query”,然后点击“Finish”。
    如果你还没有安装Microsoft Query,Loadrunner会提示你这个功能不可用。在进行之前,从Microsoft Office中安装MS Query。
    2. 在Microsoft Query中遵循以下步骤,导入期望的表和列。
    3. 在完成数据的导入后,选择“Exit and return to Virtual User Generator”,然后点击“Finish”。在参数属性对话框中数据库记录以data文件的形式显示出来。
    要在MS Query中编辑并查看数据,选择“View data or edit in Microsoft Query”。若要结束,则选择“File>Exit and return to Virtual User Generator”返回到脚本生成器。
    4. 在“Select Column”部分,指定包含当前参数数据的列可以指定列号或者列名。注意:列标题默认为第0行(row 0)。
    5. 从“Select next row”列表中选择一个更新方法来告诉虚拟用户在脚本指定的过程中如何选择表中的数据。可选项是:Sequential、Random、Unique或者Same Line As。其中每一项的含义文章前面已经讲述,就不再赘述。
    6. 如果选择“Advance row each iteration”,虚拟用户在每次迭代的时候会使用新的一行的数据而不是重复同样的数据。
    要指定数据库连接或者SQL语句
    1. 选择“Specify SQL Statement”,然后点击“Next”。
    2. 点击“Create”指定一个新的连接字符串。选择数据源的窗口弹出。
    3. 选择已有的数据源,或者点击“New”创建一个新的数据源。向导将提示你穿过创建ODBC数据源的过程。在完成后,连接字符串就会在连接字符串框中显示出来。
    4. 在SQL框中,输入或者粘贴SQL语句。
    5. 点击“Finish”继续SQL语句并导入数据。数据库记录将以data文件的形式显示在参数属性框中。
    6. 在“Select Column”部分中,指定包含当前参数数据的列。你可以指定列号或者列名。
    7. 从“Select next row”列表中选择一个更新方法来告诉虚拟用户在脚本指定的过程中如何选择表中的数据。可选项是:Sequential、Random、Unique或者Same Line As。
    8. 如果选择“Advance row each iteration”,虚拟用户在每次迭代的时候会使用新的一行的数据而不是重复同样的数据。

Open Toolbar