第一大问题:Loadrunner乱码一击必杀

  之前有介绍一些简单的针对Loadrunner脚本或者调试输出内容中乱码的一些设置,但是并没能完全解决一些小伙伴的问题,因为那些设置实在能力有限,还是有很多做不到的事情。但是没关系,知道君还有更厉害的招数分享给大家,简单实在,堪称必杀技,请各路高手前来挑战。

  首先我们来看看有哪些内容是配置无法解决的,这里通过对3个Loadrunner使用率最高的HTTP请求函数来解释(web_url,web_submit_data,web_custom_request),其他一些关联、检查等函数大部分都是直接可以通过配置来解决的。

  • web_url

  关键参数: URL(配置无效)

  当然谁在URL里写中文本身就是一个问题,不同浏览器处理中文的处理和编码都不同,但总有人喜欢那么干……任何关于编码的配置都对URL中的中文无效,一切都会以系统默认编码处理,也就是ANSI(GBK)

  • web_submit_data

  关键参数1:Action(配置无效)

  该参数实际就是URL,只是参数名称不同于常规

  关键参数2:ITEMDATA中的各项value(配置有效)

  • web_custom_request

  关键参数1:URL(配置无效)

  与上面URL参数情况相同,配置对中文无效,都只会作为GBK处理

  关键参数2:Body(含其他模式的Body,配置同样无效)

  • 参数化文件的编码(配置无效)


  看了以上的情况后,发现配置实际对很多情况并没有作用,那么我们就开始出招了,招招导致“乱码兄”小命不保。

 方法一:常规通用招数

  利用Loadrunner提供的转换函数

  (lr_convert_string_encoding)进行处理,GBK转换UTF-8参考代码:

  lr_convert_string_encoding("我是代码","GBK","UTF-8","outparam");

  由于转换过程中会多出一个 \0 的结束字符,也就是outparam转换后变成了”我是代码\0”,所以还需要特别进行处理:

  lr_save_string(lr_eval_string("{outparam}"),"newparam");

  将outparam重新save转存到另一个newparam的参数中,当然也可以保存在原来的outparam参数中进行覆盖,这样才能保证整个转换过程没有纰漏,一些系统对\0比较敏感的时候还可能出现未知的问题。

例一:将报文从中文处给分割成两部分。

char str_Body[4096]; //组装xml
char str_Body1[4096]; //组装xml
char tmp[10]="";
lr_convert_string_encoding("李风华",LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8, "str");
strcpy(tmp,lr_eval_string("{str}"));//目的是去掉转码后的字符串后面\x00。
                    注:lr_save_string(lr_eval_string("{outparam}"),"newparam");也是为了去掉后面的\0结束符,但是具体谁更有效还不太清楚
lr_error_message("%s",tmp); sprintf(str_Body,"%s", lr_eval_string( //以下是报文内容,开发人员提供报文规 "body=<Transaction>" "<Transaction_Header>" "<transaction_time>042326</transaction_time>" "<transaction_sn>2017011100000068</transaction_sn>" "<rel_name>" ));//把报文从中截断 sprintf(str_Body1,"%s", lr_eval_string( "</rel_name> " "<rel_cert_type/> " "<rel_cert_no/> " "<other_desc/> " "<cert_org_nat/> " "<cert_org_area/> " )); strcat(str_Body,tmp);//将报文重新拼接。 将tmp 加到str_Body后面 strcat(str_Body,str_Body1); lr_output_message("%s",lr_eval_string(str_Body)); lr_start_transaction("对私客户基本信息查询"); web_reg_save_param("retCode", "LB=<status>", "RB=</status>", /*"NotFound=WARNING"*//*"Serach=ALL",*/ LAST); web_custom_request("login", "URL=http://172.16.223.88:8085", "Method=POST", "Resource=0", "RecContentType=txt/xml", "Referer=", "Mode=HTTP", /*"Body=str_Body"*/ lr_eval_string(str_Body), LAST);

例二:将转码后的字符串,继续转换成一个参数化对象

char str_Body[4096]; //组装xml
char tmp[10]="";
lr_convert_string_encoding(lr_eval_string("{NewParam}"),LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8, "str");
strcpy(tmp,lr_eval_string("{str}"));//目的是去掉转码后的字符串后面\x00
lr_save_string(lr_eval_string(tmp),"param"); //把tmp值保存到param里面,对变量进行参数化。
lr_error_message("%s",tmp);
sprintf(str_Body,"%s", lr_eval_string(
  //以下是报文内容,开发人员提供报文规范

    "body=<Transaction>"
"<Transaction_Header>"
"<transaction_time>042326</transaction_time>"
    "<transaction_sn>{ID}{TIME}</transaction_sn>"
    "<transaction_id>B110</transaction_id>"
    "<requester_id>01101</requester_id>"
    "<transaction_inst>0001</transaction_inst>"
                "<rel_name>{param}</rel_name> " //直接参数化param
                "<rel_cert_type/> "
                "<rel_cert_no/> "
    ));    

lr_error_message("%s",lr_eval_string(str_Body));
  web_reg_save_param("retCode",
    "LB=<status>",
    "RB=</status>",
  /*"NotFound=WARNING"*//*"Serach=ALL",*/
    LAST);

    lr_start_transaction("对私客户关系个人信息创建与维护");
 
    web_custom_request("login",
    "URL=http://172.16.223.88:8085",
    "Method=POST",
    "Resource=0",
    "RecContentType=application/json",
    "Referer=",
    "Mode=HTTP",
    /*"Body=str_Body"*/
    lr_eval_string(str_Body) ,
                       LAST);

 方法二:针对参数文件的转换

  LoadRunner的参数化文件,都是统一使用系统默认编码(GBK),如果内容中含有中文,那么默认参数化到脚本的中文就是GBK编码。所以就需要每次获取时进行代码转换,这对于一些参数化策略多少会受到一些影响,如果使用下面这招,就可以避免每次转码带来的问题,

  假设你的数据文件名称为data.dat,你可以在LoadRunner还没有添加该参数文件前,使用文本编辑器(如:UE),打开data.dat,直接将数据文件另存为UTF-8的编码并对原来的文件进行覆盖,再回去重新添加参数文件,虽然此时参数表中显示上都成乱码,但实际使用时的效果惊人,可直接发送UTF-8编码的中文数据,简单方便,唯一的缺点是只能在脚本外部进行编辑。

方法三:直接发送16进制编码数据,无视任何编码

  假设需要在web_custom_request的body中发送一串json,内容为{"test":123,"name":"名称"} ,json的格式中,中文只能是UTF-8,而如果不是UTF-8编码,情况好点只是乱码,情况差点,可能连带json解析器都会一起报错。

  那么上面的内容我们可以发送什么来代替呢?揭晓答案:

  {"test":123,"name":"\xE5\x90\x8D\xE7\xA7\xB0"}

  至于中间如何转换的过程,可以参考编码码表,或者通过UTF-8编码获取中文的Hex值,再或者,你会发现实际上这和Urlencode的结果很像。

第二大问题:“%”在c语言中的逃逸 

char * c="efe%fefe";
lr_log_message(c);  //输出:efe0.000000efe
lr_log_message("%s\n",c); //输出:efe%fefe      一定要这样输出,避免字符串中,有"%"号导致,出现字符逃逸,就是"%"消失了。

这就是因为c代码中,“%”的逃逸的问题,但是这只是体现在打印输出的时候,并不会影响判断c的长度,也不影响c字符串的相等的判断等。

第三大问题:c语言字符串的连接,不能使用+

char * c="efe%fefe";
char *d="gegeg";
char e[2500];
方式一:
sprintf(e,"%s%s",c,d); //注意此处不能使用snprintf 会出现%的字符逃逸。同时snprintf也有好处,就是不会出现内存分配不足,内存浪费等问题。
lr_log_message("%s\n",c); //一定要这样输出,避免字符串中。
lr_log_message(c)  因c里面有"%"号,会出现字符逃逸,就是"%"消失了。得到的结果将会是:efeefe

方式二:
strcat(e,c);
strcat(e,d);

 注:字符串拼接后,可能需要考虑删除字符串后面的结束符。

第四大问题:并发时,请求发送到最后,不能立即断开。

当采用netstat命令时,看到很多socket处于“wait”状态;

当建立连接时出现“No buffer space available”错误信息。

以后发送到最后,请求不能立即断开,也可以使用该方法。

解决办法:引入web_set_sockets_option()方法。

第五大问题:参数化,在java vuser中,需要加引号

正确使用方式:  lr.log_message("开始时间:::"+"<NewParam>");  

第六大问题:web_reg_save_param_ex()导致的内存泄漏问题

在大的并发下,持续运行一段时间后,发现负载机的内存越来越少,有可能就是该函数导致的。因该函数会将测试脚本信息缓存,从而导致mmdrv.exe(LoadRunner进程)的内存一直上升。

所以建议:继续使用老方法web_reg_save_param。在迫不得已的情况下,再使用。

    web_reg_save_param("result",
        "LB=11",
        "RB=11",
        "NotFound=WARNING",  //找不到不会报错
        "IgnoreRedirections=Yes",//会根据返回的所有的log日志中去查找,而不会只查找第一个返回的log
        LAST);

 

 

 

 

posted on 2017-09-11 16:49  进_进  阅读(185)  评论(0)    收藏  举报