发布新日志

  • 转帖:Loadrunner中对中文进行UTF-8转码的探索

    2011-10-18 15:00:36

    本文来自于fox的日志:http://testingtop.com/space.php?uid=7&do=blog&id=225

    这是一个HTTP接口测试中经常会碰到的问题,目前的服务器采用的都是UTF-8编码方式,而我们的客户机Windows系统一般默认采用的编码方式是GBK,这正是我们采用录制方式的时候会发现许多中文乱码的原因。

    Loadrunner录制的时候可以通过在Virtual User Gen的Tools->Recoding Options -> Advanced -> Support charset -> UTF-8的设置规避(其实也只是部分规避),下面我们讨论在手写测试脚本时如何解决UTF-8转码的问题。

    实践一:在脚本中直接采用中文明文进行请求

      web_custom_request("web_custom_request",
      "URL=http://172.16.4.191/list?id=环球影院",
      "Method=GET",
      "TargetFrame=",
      "Resource=0",
      "Referer=",
      "Body=",
      LAST);
    结果:服务端返回404错误,找不到相应的资源id,明显服务端不能正确响应非UTF8编码方式的请求。

    实践二:

    为解决这个问题,最关键的是要把本地GBK编码的汉字转换成UTF-8编码格式的信息,为此我们引进loadrunner自带的编码函数lr_convert_string_encoding

    lr_convert_string_encoding

    Converts a string to a different encoding.

    C Language

    intlr_convert_string_encoding( const char *sourceString, const char *fromEncoding, const char *toEncoding, const char *paramName);

    Example       See Also

    sourceString
    The string to convert
    fromEncoding
    The encoding of the sourceString
    toEncoding
    The encoding to convert of the string saved in parameterparamName
    paramName
    The name of the parameter in which the destination string will be saved

    lr_convert_string_encodingconverts a string encoding between the following encodings: System locale, Unicode, and UTF-8.The function saves the result string, including its terminating NULL, in the parameterparamName.

    lr_convert_string_encodingis added manually to a script. when needed. It is not recorded.

    Possible values for 'fromEncoding' and 'toEncoding' :

    Constant
    Value
    LR_ENC_SYSTEM_LOCALE
    NULL
    LR_ENC_UTF8
    "utf-8"
    LR_ENC_UNICODE
    "ucs-2"
     
     
    根据函数说明,我们编写测试脚本如下
     lr_convert_string_encoding( "环球影院",
      LR_ENC_SYSTEM_LOCALE,
      LR_ENC_UTF8,
      "str" );
     web_custom_request("web_custom_request",
      "URL=http://172.16.4.191/list?id={str}",
      "Method=GET",
      "TargetFrame=",
      "Resource=0",
      "Referer=",
      "EncType=text/xml;charset=UTF-8",
      "Body=",
      LAST);
     
    使用lr_convert_string_encoding函数,将中文转换成UTF-8编码以后,作为参数传递给请求,并发送。
    测试结果:仍然返回404错误,查看loadrunner日志信息“环球影院”已经正确转换成UTF8编码方式,那为什么还是请求失败呢?
    再次查看日志如下
    Action.c(7): t=825ms: 223-byte request headers for "http://172.16.4.191/list?id=鐜悆褰遍櫌" (RelFrameId=1)
    Action.c(7):     GET /list?id=鐜悆褰遍櫌\x00 HTTP/1.1\r\n
    Action.c(7):     Content-Type: text/xml;charset=UTF-8\r\n
    Action.c(7):     User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows)\r\n
    Action.c(7):     Accept-Encoding: gzip, deflate\r\n
    Action.c(7):     Accept: */*\r\n
    Action.c(7):     Connection: Keep-Alive\r\n
    Action.c(7):     Host: 172.16.4.191\r\n
    Action.c(7):     \r\n
    发现在请求地址“/list?id=鐜悆褰遍櫌”后面还带了一个\x00,这正是lr_convert_string_encoding函数说明中标红的说明:The function saves the result string, including its terminating NULL, in the parameterparamName.
    也就是说,我转换成UTF-8之后,如果直接作为变量传到代码之中的话,在最后的字符串之中,会多出来一个“NULL”,C语言中NULL是一个字符串的结束,而正是这个null字节的存在导致了服务端识别id出错。
     
    实践三:
     char tmp[50];
     lr_convert_string_encoding( "环球影院",
      LR_ENC_SYSTEM_LOCALE,
      LR_ENC_UTF8,
      "str" );  
     strcpy(tmp,lr_eval_string("{str}"));
    lr_log_message("str is %s",tmp);
     lr_save_string(tmp,"sorvalue");
     web_custom_request("web_custom_request",
      "URL=http://172.16.4.191/list?id={sorvalue}",
      "Method=GET",
      "TargetFrame=",
      "Resource=0",
      "Referer=",
      "Body=",
      LAST);
    通过lr_eval_string函数取参数值时会自动去掉\x00,测试结果正常,正确返回HTTP响应内容。
  • 转帖:Loadrunner中web_reg_save_param函数使用详解

    2010-10-22 16:05:46

    Loadrunner中web_reg_save_param函数使用详解

    * 应用范围

    在使用Loadrunner进行性能测试时,经常遇到一种情况,需要通过web页面修改某事务的状态。于是需要首先读出当前的事务的状态,再进行修改,此时便可以使用到web_reg_save_param了。可以通过它先将事务的状态读出写入一个自定义的变量中,根据变量的值来决定下一步的动作。

    * 简要说明

    语法:

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

    参数说明:

    * ParamName: 存放得到的动态内容的参数名称
    * list of Attributes: 其它属性,包括:Notfound, LB, RB, RelFrameID, Search, ORD, SaveOffset, Convert, SaveLen。属性值不分大小写
    o Notfound: 当在返回信息中找不到要找的内容时应该怎么处理
    o Notfound=error: 当在返回信息中找不到要找的内容时,发出一个错误讯息。这是缺省值。
    o Notfound=warning: 当在返回信息中找不到要找的内容时,只发出警告,脚本也会继续执行下去不会中断。
    o LB( Left Boundary ) : 返回信息的左边界字串。该属性必须有,并且区分大小写。
    o RB( Right Boundary ): 返回信息的右边界字串。该属性必须有,并且区分大小写。
    o RelFrameID: 相对于URL而言,欲查找的网页的Frame。此属性质可以是All或是数字,该属性可有可无。
    o Search : 返回信息的查找范围。可以是Headers,Body,Noresource,All(缺省)。该属性质可有可无。
    o ORD : 说明第几次出现的左边界子串的匹配项才是需要的内容。该属性可有可无,缺省值是1。如为All,则将所有找到的内容储存起来。
    o SaveOffset : 当找到匹配项后,从第几个字元开始存储到参数中。该属性不能为负数,缺省值为0。
    o SaveLen :当找到匹配项后,偏移量之后的几个字元存储到参数中。缺省值是-1,表示一直到结尾的整个字串都存入参数。
    o Convert : 可取的值有以下两种:

    HTML_TO_URL : 将 HTML-encoded 资料转成 URL-encoded 资料格式

    HTML_TO_TEXT : 将 HTML-encoded 资料转成纯文字资料格式

    * 实例讲解

    目的:取得页面中的商品状态,如果状态是正常态就改为注销态,否则改为正常态。

    录制脚本使用的是URL based script

    将返回的数据记录到日志

    * 直接手工访问页面,检查URL

    该页面上点击右键,选择属性

    看到URL,对照录制下的脚本中有:
    web_url("modifyOfferingStatePage.do",
    "URL={url}/web/businessAccept/order/modifyOfferingStatePage.do?offeringId=
    282172&offeringSpecId=1&offeringSpecName=普通宽带(ADSL/LAN)&customerName=
    {clientname}&nodeId=260000&pos1=定购管理&pos2=修改商品状态",

    "Resource=0",
    "RecContentType=text/html",
    "Referer={url}/web/businessAccept/order/orderMenu.do",
    "Snapshot=t23.inf",
    "Mode=HTTP",
    LAST);
    于是在这段代码前添加注册函数:
    web_reg_save_param("oldstate",
    "LB/IC=原有商品状态:</td>",
    "RB/IC=</td>",
    "Search=body",
    "Ord=1",
    "RelFrameId=1",
    "SaveOffset=57",
    "SaveLen=4",
    LAST);
    web_url("modifyOfferingStatePage.do",
    "URL={url}/web/businessAccept/order/modifyOfferingStatePage.do?offeringId=
    282172&offeringSpecId=1&offeringSpecName=
    普通宽带(ADSL/LAN)&customerName={clientname}&nodeId=
    260000&pos1=定购管理&pos2=修改商品状态",

    "Resource=0",
    "RecContentType=text/html",
    "Referer={url}/web/businessAccept/order/orderMenu.do",
    "Snapshot=t23.inf",
    "Mode=HTTP",
    LAST);

     函数的一些使用技巧:
            1、web_reg_save_param必须在获取返回值的操作前面注册,在获取返回值的操作后面使用
            2、保存参数最大不能超过256字节,如果超过256字节请使用int web_set_max_html_param_len (const char *length )函数扩大参数保存范围
            例如:web_set_max_html_param_len ("1024"); //扩大参数最大保存范围为1024字节
            3、LB和RB后面跟着"/ic",则边界大小写都匹配(不加,也就是默认是大小写敏感的)
            例如:web_reg_save_param("IsRight","LB/ic=cache-control: private\r\n\r\n","RB/ic=|",LAST);

  • 转帖:LoadRunner里如何实现连接几个很长的字符串呢?

    2010-10-22 16:03:35

    char str[1024];
    char *str1="slJnVtsMOdItZ5dTdNJrturuyhrthKjnyUQb7ni85p76ntizLkQk";
    char *str2=":<?xml version="1.0" encoding="utf-8"?><antiphishing><appinfo><appname>dgdg</appname></appinfo><phishs><phish><url><![CDATA[http://www.baidu.com/abc.html]]></url><action>gjgj</action><sync>ghjg</sync><extraattr keyname="ghj" value="uytyu"/><extraattr keyname="app_name" value="vesfee"/></phish></phishs></antiphishing>
    ";
    char *str3="slJnVtsMOdItZ5dTdNJrturuyhrthKjnyUQb7ni85p76ntizLkQk";

    strcpy(Str,Str1) ;
    strcat(Str,Str2);
    strcat(Str,Str3);


    lr_output_message("%s",str1);

  • 转帖:url 模式录制脚本web_concurrent_start和web_concurrent_end是起到什么作用呀

    2010-10-22 16:00:16

    Zee:

    很多地方都没有把这个东西解释清楚。其实比较容易理解的。就是并发组这个概念把人说晕了。

    简单的说:
    这两个函数是在URL中标记一个页面请求的,注意:这里我说的是页面(page),并不是请求。
    在LR请求一个页面里,由于使用URL的方式录制,会把一个页面中的元素分成几个web函数做处理。所以,LR中实现了web_concurrent_start和web_concurrent_end。实现的作用是:
    从web_concurrent_start开始标记,当脚本运行到web_concurrent_start时,后续的脚本都不会立即被执行,直到web_concurrent_end出现。才把这中间的所有的脚本一起执行。
    所谓并发组也是指把这一组函数一起执行起来。

    如果你用 lr_start_transaction和 lr_end_transaction来替换,脚本完全可以跑通。中间的脚本是从上到下执行的,而不是一起执行的。
    其他的没有作用。

  • 转帖:loadrunner录制下载文件

    2010-10-22 15:57:06

    本文关键字

    loadrunner录制下载文件,文件如何保存,如何获得服务器返回的文件名,保存文件时如何随机生成文件名

            在录制脚本的过程中,我们把下载文件的请求单独放到一个action中,我们先简单的分析一下录制下载文件的脚本,在脚本中只能看到这样一个下载的请求:
    web_url("download.php",
              "URL=http://211.147.208.141/cn/resources/download.php?id=386",
              "Resource=1",
              "RecContentType=application/force-download",
              "Referer=",
              LAST);

    对于如何保存到本地,loadrunner是无法记录的,执行脚本时客户端发出这个请求,服务器端响应后,loadrunner接收到了服务器响应的文件内容(我们可以在日志中看到文件的内容,不过是乱码),既然loadrunner可以接收到文件内容,那么我们完全可以使用关联函数来获得该内容,在通过C语言的文件函数把获得的内容写在本地。

            那现在遇到这样一个问题,使用关联函数如何定义获得服务器响应内容的左右边界呢?因为我们把这个请求写在了一个单独的action中,所以在这里我们只要把服务器响应的所有内容均获取下来写到本地,也就完成了下载文件的保存。

            下面看代码: 
    Action()
            {
                int flen;        //定义一个整型变量保存获得文件的大小
                long filedes;    //保存文件句柄
                char file[256]="\0";  //保存文件路径及文件名


                web_set_max_html_param_len("2000000");//设置页面接收最大的字节数,该设置应大于下载文件的大小

             web_concurrent_start(NULL);

     

    //使用关联函数获取下载文件的内容,在这里不定义左右边界,获得服务器响应的所有内容          

    web_reg_save_param("filecontent",
              "LB=",
              "RB=",
              "Search=BODY",
              LAST);

    web_reg_save_param("file",
              "LB=filename=\"",
              "RB=\"",
              "Search=all",
              LAST);

         //使用关联函数在服务器响应的头文件中获取下载文件名

              web_url("download.php",
              "URL=http://211.147.208.141/cn/resources/download.php?id=386",
              "Resource=1",
              "RecContentType=application/force-download",
              "Referer=",
              LAST);

            //发出下载请求

              web_concurrent_end(NULL);


             strcat(file,"c:\\");    //将“c:\\”这个路径保存到file中
             strcat(file,lr_eval_string("{file}"));//将获得的文件名拼接在file这个变量字符串之后


            flen = web_get_int_property(HTTP_INFO_DOWNLOAD_SIZE); //获得文件大小

                if(flen > 0)
                {
                 if((filedes = fopen(file, "wb")) == NULL)
                 {
                  lr_output_message("Open File Failed!", lr_eval_string("{filecontent}"));
                  return -1;
                 }
                 fwrite( lr_eval_string("{filecontent}"),flen,1,filedes );
                 fclose( filedes );
            }

             return 0;
            }


            好了,运行这段脚本完成文件下载并写到本地的操作

            如果我们需要重复保存这个文件到本地,如何解决重名问题呢,下面这段代码可以随机生成文件名

                 char file[256]="\0";
                char * chNumber

                chNumber=lr_eval_string("{Random}");  //生成随机数

                strcat(file,"c:\\test");
                strcat(file,chNumber);
                strcat(file,".rar");

            此时file中保存着一个随机生成的文件名,然后使用文件函数以该文件名保存文件

  • 转帖:Loadrunner中参数和变量的使用

    2010-10-22 15:26:06

    //字符串复制
    strcpy(str,"Hello ") ;

    //字符串连接
    strcat(str,"World !");
    lr_message("str: %s",str);

    //变量转为参数,将变量str的值存到参数Param中
    lr_save_string(str,"Param");

    //参数复制
    lr_save_string(lr_eval_string("{Param}"),"Param_1");

    //参数转为变量
    strcpy(str1,lr_eval_string("{Param_1}"));
    lr_message("str1: %s",str1);

    //参数名称格式化输出到变量中
    sprintf(str2,"{Param_%d}",1);
    lr_message("str2: %s",lr_eval_string(str2));

    在web系统中 参数一般通过web_reg_save_param获取

    语法:

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

    参数说明:

    • ParamName: 存放得到的动态内容的参数名称
    • list of Attributes: 其它属性,包括:Notfound, LB, RB, RelFrameID, Search, ORD, SaveOffset, Convert, SaveLen。属性值不分大小写
      • Notfound: 当在返回信息中找不到要找的内容时应该怎么处理
      • Notfound=error: 当在返回信息中找不到要找的内容时,发出一个错误讯息。这是缺省值。
      • Notfound=warning: 当在返回信息中找不到要找的内容时,只发出警告,脚本也会继续执行下去不会中断。
      • LB( Left Boundary ) : 返回信息的左边界字串。该属性必须有,并且区分大小写。
      • RB( Right Boundary ): 返回信息的右边界字串。该属性必须有,并且区分大小写。
      • RelFrameID: 相对于URL而言,欲查找的网页的Frame。此属性质可以是All或是数字,该属性可有可无。
      • Search : 返回信息的查找范围。可以是Headers,Body,Noresource,All(缺省)。该属性质可有可无。
      • ORD : 说明第几次出现的左边界子串的匹配项才是需要的内容。该属性可有可无,缺省值是1。如为All,则将所有找到的内容储存起来。
      • SaveOffset : 当找到匹配项后,从第几个字元开始存储到参数中。该属性不能为负数,缺省值为0。
      • SaveLen :当找到匹配项后,偏移量之后的几个字元存储到参数中。缺省值是-1,表示一直到结尾的整个字串都存入参数。
      • Convert : 可取的值有以下两种:

    HTML_TO_URL : 将 HTML-encoded 资料转成 URL-encoded 资料格式

    HTML_TO_TEXT : 将 HTML-encoded 资料转成纯文字资料格式

    注:可以将ORD设置成ALL看看效果,然后充分挖掘

    付:

    字符串处理主要是对字符串操作和比较。

    函数名 介绍
    strcat 连接两个字符串
    strchr 返回字符串第一次出现后的所有字符
    strcmp 区分大小写字母比较 
    strcpy 复制一个字符串到另一个 
    strdup 复制字符串
    stricmp 不区分大小写字母比较
    strlen 返回字符串长度
    strlwr 转化字符串为小写字母
    strncat 一个字符串连接另一个字符串到第n个的字符 
    strncmp 比较两个字符串从第一到n个字符
    strncpy 复制一个字符串从第一到n个字符到另一个字符串 
    strnicmp 比较两个字符串的n个字符 
    strrchr 返回字符最后出现后的所有字符
    strset 为字符串填充特殊字符
    strspn 返回字符串中包含特殊字符的个数 
    strstr 返回一个字符串在另一个中第一出现的位置数 
    strtok 返回特殊标记分割的字符 
    strupr 转化字符串为大小字母

  • 安装HP LoadRunner 9.1碰到的问题

    2010-07-01 10:13:10


    在一个新的XP系统中装HP LoadRunner 9.10,点击安装后提示“Setup has determined that a previous installation has not completed.
    You should restart the system in order to complete this process.”

    重启电脑后问题还存在,用网上下的deletelicense.exe和优化大师清处注册表信息也不行。 后来从网上找到一种可以解决的方法,那就是:

    1. 打开临时文件夹,开始—>运行—>输入%temp%
    2. 找到“Prereq_Mgr.HP_LoadRunner_9.10.log”文件,这个文件记录着不能安装的原因。

    我的这个日志文件记录如下:
    [04/23/09 12:58:31] INFO: (IsRebootRequired) The registry value [PendingFileRenameOperations] exists under [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager] and cannot be ignored

    3、删除注册表项(如果要操作注册表,最好要把注册表备份好,防止误操作)
    把注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager下的项PendingFileRenameOperations删除。

    再安装HP LoadRunner 9.10就可以正常安装了!

Open Toolbar