一、前言
本文主要针对http接口GET和POST三种不同的请求类型来编写脚本。
(1)application/x-www-form-urlencoded 键值对
(2)application/json Json串
(3)multipart/form-data 表单
二、创建脚本-http
1.通用部分
1.Create/Edit Script
2.New Script
3.Web(HTTP/HTML)
4.光标定位于右侧脚本面板,点击菜单Insert -> New step
5.选择Submit Data -> web_submit_data (根绝接口请求类型选择)
6.填入接口相关信息,点击确定生成接口调用内容,然后在修改完善脚本。
2.POST:application/x-www-form-urlencoded脚本
1.选择Submit Data -> web_submit_data,填入接口信息
2.生成脚本如下,点击运行,根据输出信息判断调用成功。
3.完善脚本
光标停留在要插入函数的位置,在INSERT菜单中,选择new step,在列表中选择或查找要插入的函数,根据提示填写必要的参数;
①添加事务
{ // 定义事务 /* 通常将一个服务定义为一个事务。这样在性能测试后事务相应时间就能看做一个服务的相应时间 事务开始函数 */ lr_start_transaction("login"); web_submit_data("login", "Action=http://127.0.0.1:8087/hms/login.do", "Method=POST", "TargetFrame=", "Referer=", ITEMDATA, "Name=username", "Value=nqsq", ENDITEM, "Name=password", "Value=a", ENDITEM, LAST); // 事务结束函数 lr_end_transaction("login", LR_AUTO); return 0; }
②注册获取返回参数并打印
执行后打印的内容,其中中文出现乱码:
"0" {"jgbm":"310120101010001","jgmc":"濂夎搐鍖哄崡妗ラ晣绀惧尯鍗敓鏈嶅姟涓績","rybm":"437","ryxm":"鍗楁ˉ绀惧尯","xb":"2","zcjgdm":"42504942400","zcrydm":"006"} HTTP/1.1 200 Set-Cookie: JSESSIONID=1A540D4683A6BAD6D01ABA087E99B531; Path=/hms; HttpOnly Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT Access-Control-Max-Age: 86400 Access-Control-Allow-Headers: Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token Access-Control-Allow-Credentials: true XDomainRequestAllowed: 1 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 28 Nov 2018 14:31:15 GMT {"status":"0","data":{"jgbm":"310120101010001","jgmc":"濂夎搐鍖哄崡妗ラ晣绀惧尯鍗敓鏈嶅姟涓績","rybm":"437","ryxm":"鍗楁ˉ绀惧尯","xb":"2","zcjgdm":"42504942400","zcrydm":"006"},"msg":"鐧诲綍鎴愬姛锛?}
③设置检查点(注册断言)
以下代码放在web_submit_data前面
/* 注册断言: Text=断言内容 */ /* 该方法会判断请求响应的内容是否包含status,如果不包含则会报错 */ web_reg_find("Text=status", LAST);
④处理Replay log中输出中文乱码问题
// 将data值从utf-8转为gb2312格式保存在dataStr变量中,并打印 lr_convert_string_encoding(lr_eval_string("{data}"),"utf-8","gb2312","dataStr"); lr_output_message(lr_eval_string("{dataStr}"));
⑤完整内容:
Action() { // 定义事务 /* 通常将一个服务定义为一个事务。这样在性能测试后事务相应时间就能看做一个服务的相应时间 事务开始函数 */ lr_start_transaction("login"); /* 注册获取返回参数,该方法可以配合打印返回数据,检测数据内容 */ web_reg_save_param("status", "LB=\"status\":", "RB=,\"data\":", LAST); // 根据左边界值【"data":】和右边界值【,"msg":】搜索响应结果json串中data的值 web_reg_save_param("data", "LB=\"data\":", "RB=,\"msg\":", LAST); // 不指定边界值,保存所有内容 /* web_reg_save_param("result", "LB=", "RB=", LAST); */ /* 注册断言: Text=断言内容 */ /* 该方法会判断请求响应的内容是否包含status,如果不包含则会报错 */ web_reg_find("Text=status", LAST); /* 向后面的web请求函数增加请求头 */ /* 如果web请求方法中已经设置了相同的头,则优先使用web请求方法中的头, 例如web请求方法中的EncType参数,对应请求投中的Content-Type。 由于下面的方法已经设置了EncType参数,所以这里的设置并没有什么X用 */ /* 表单直接使用方法自带参数,键值对和json建议使用该方法 */ /* web_add_header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); */ /* 主要针对form表单和键值对两种格式的web请求 */ web_submit_data("login", "Action=http://127.0.0.1:8087/hms/login.do", "Method=POST", /* 该方法支持常见的两种请求数据格式 */ /* (1)"EncType=multipart/form-data"。form表单提交数据 */ /* (1)"EncType=application/x-www-form-urlencoded"。默认使用键值对提交数据 */ //"EncType=", "TargetFrame=", "Referer=", ITEMDATA, "Name=username", "Value=nqsq", ENDITEM, "Name=password", "Value=a", ENDITEM, LAST); /* 打印相应结果 */ /* lr_eval_string("{result}") 使用loadrunner引用外部函数, 只有这样才能取出上面web_reg_save_param方法的返回值 */ lr_log_message(lr_eval_string("{status}")); lr_log_message(lr_eval_string("{data}")); // 查看搜索的所有内容 // lr_log_message(lr_eval_string("{result}")); // 将data值从utf-8转为gb2312格式保存在dataStr变量中,并打印 lr_convert_string_encoding(lr_eval_string("{data}"),"utf-8","gb2312","dataStr"); lr_output_message(lr_eval_string("{dataStr}")); // 事务结束函数 lr_end_transaction("login", LR_AUTO); return 0; }
3.POST:application/json脚本
Action() { lr_think_time(1); lr_start_transaction("发卡交易"); web_reg_save_param( "Result", "LB=H_ret_code\": \"", "RB=\"", LAST); web_custom_request("web_custom_request", "URL=http://81.1.53.23:9324", //81.1.53.23 81.1.159.14 "Method=POST", "EncType=application/json", "Resource=0", "Body={mac}{\"boxnum\":\"card1\",\"cust_flag\":\"0\",\"phone\":\"18087962361\",\"worktype\":\"0\",\"nation\":\"156\",\"idbirth\":\"1990-11-07\",\"idlosdate\":\"20170823\",\"card_productcode\":\"1201110010\",\"card_pwd\":\"78B93A6C9DB59FADD762A62F26F48C99\",\"idtype\":\"0\",\"idno\":\"130429199011070018\",\"cust_addr\":\"河北省邯郸市永年县临洺关镇西大街西马道 46号\",\"workname\":\"IMS.ZNWD_002.zpk\",\"M_CustomerNo\":\"11\",\"M_PackageType\":\"JSON\",\"M_ServicerNo\":\"IBP\",\"M_ServiceCode\":\"ibp.tsf.t003.01\",\"M_MesgSndDate\":\"20170316\",\"M_MesgSndTime\":\"183917\",\"M_MesgId\":\"05ed61f7-f27e-438f-bf21-288f63646647\",\"M_MesgPriority\":\"3\",\"M_Direction\":\"1\",\"M_CallMethod\":\"1\",\"channelcode\":\"SS050200\",\"menu_code\":\"B0001\",\"menu_name\":\"个人开卡1\",\"MacKeyName\":\"IMS.ZNWD_002.zak\",\"devicetype\":\"11\",\"channeldate\":\"20170316\",\"channeltime\":\"183917\",\"channelserno\":\"20170316183917370\",\"device_num\":\"1\",\"deviceno\":\"1\",\"device_oid\":\"563ec9b1831eb623c9bcab33e15ad1db\",\"brno\":\"{jgh}\",\"teller\":\"{usercode}\",\"tellerno\":\"050017\",\"accountNo\":\"6231810010599000258\",\"custName\":\"高攀\",\"custinfo_type\":\"0\",\"custinfo_num\":\"130429199011070018\",\"id\":\"130429199011070018\",\"sex\":\"1\",\"auth_teller\":\"050017\",\"opencardtype\":\"1\"}", "Referer=", LAST); if(strcmp(lr_eval_string("{Result}"),"000000")==0) { lr_end_transaction("发卡交易", LR_PASS); } else { lr_end_transaction("发卡交易", LR_FAIL); lr_error_message("======Result:%s=====", lr_eval_string("{Result}")); lr_error_message("======mac:%s=====", lr_eval_string("{mac}")); } return 0; }
4.POST:multipart/form-data脚本
Action() { lr_think_time(1); lr_start_transaction("个人不绑卡开户"); web_reg_save_param("Result", "LB=message\":\"", "RB=\"", LAST); web_submit_data("web_submit_data", "Action=http://17.8.22.58:18401/openapi/perTwoeleAuthOpenAcct", "Method=POST", "EncType=application/x-www-form-urlencoded", "TargetFrame=", "Referer=", "Mode=HTML", ITEMDATA, "Name=version", "Value=1.0", ENDITEM, "Name=appCode", "Value=ggb", ENDITEM, "Name=channelSerialNo", "Value={NewParam}", ENDITEM, "Name=timestamp","Value=time(&t)",ENDITEM, "Name=payload","Value={\"customerName\":\"{NewParam_4}\",\"idNo\":\"{NewParam_3}{NewParam_6}{NewParam_9}\",\"phone\":\"{NewParam_5}\",\"idType\":\"A\",\"isBearing\":\"2\",\"mapArr\":\"Wyc2MicsICczNCcsICcxMDQnLCAnNTMnLCAnNTInLCAnMTExJywgJzYwJywgJzczJywgJzY2JywgJzk3JywgJzY1JywgJzc3JywgJzc0JywgJzY4JywgJzM2JywgJzgxJywgJzg5JywgJzQxJywgJzM4JywgJzcyJywgJzExOScsICcxMDcnLCAnOTknLCAnMTAxJywgJzY3JywgJzEwMicsICczNScsICc1MCcsICcxMDknLCAnMTIyJywgJzg4JywgJzEyNicsICc0MCcsICc4NicsICc4MCcsICc5MCcsICc3OScsICc4MycsICc5NCcsICc0NycsICcxMTAnLCAnNDInLCAnNDgnLCAnMTAwJywgJzU2JywgJzQ0JywgJzc1JywgJzMzJywgJzg1JywgJzEwOCcsICc0NicsICc1NCcsICc5NScsICc2OScsICcxMjAnLCAnMzknLCAnNjQnLCAnNDUnLCAnMTEyJywgJzEyNCcsICcxMTcnLCAnNjEnLCAnMTE4JywgJzExNScsICcxMTQnLCAnNDknLCAnNjMnLCAnNzgnLCAnMTA2JywgJzExNicsICc3MCcsICc5NicsICc5MicsICc5MycsICc5MScsICcxMjMnLCAnODInLCAnNzYnLCAnMTA1JywgJzUxJywgJzQzJywgJzEyMScsICcxMjUnLCAnOTgnLCAnMTAzJywgJzU5JywgJzM3JywgJzcxJywgJzg3JywgJzExMycsICc4NCcsICc1NScsICc1OCcsICc1Nydd\",\"merchantId\":\"00001\",\"randomKey\":\"q8AF/uBJIYWwNnomR2oHt/HIgSq28X2c\",\"remark\":\"张建伟测试开户\",\"transPass\":\"FTifAvSzcGoI7bV31ISlILtSlHKi2d5lunN6SY2iqY0C/fDTPueEqRJ59v5DIMoj7hob6HSEZ7ECzAOXMRHOEHROEdhPe5rMYJQ+iEo1ETs/Jf9fq6Ng5YiYfan2JNpAYWsort/N4l8dGVPa64lEpJLY8f31Wu881GooRCJmmqEbwblXW8QIjqYJ8UMp/04kVRjAeI9YM8Ky3ItMcAUHGFlKji7B03n28XAnBvJXYmQzVmFNRS+rocUhyKNL4LZjcVkYTAu3M7wYRttQFn116g==\"}", ENDITEM, LAST); lr_convert_string_encoding(lr_eval_string("{Result}"),"UTF-8",NULL,"utf8_result"); if(strcmp(lr_eval_string("{Result}"),"ok")==0){ lr_end_transaction("个人不绑卡开户",LR_PASS); } else{ lr_end_transaction("个人不绑卡开户",LR_FAIL); lr_error_message("======Result:%s=====",lr_eval_string("{utf8_result}")); } return 0; }
5.GET脚本
web_custom_request("JYKS01", "URL=http://{url}/nethisService.do?action=nethisCommonBusiness&businessCode={businessCode}&businessInfo={businessInfo}", "Method=GET", "TargetFrame=", "Resource=0", // 指示URL是否属于资源 "Referer=", LAST);
参数businessInfo需要传utf-8编码后的参数值。
如何传编码前的参数值并且设置编码格式待研究。
三、函数详解
1.lr_start_transaction/lr_end_transaction事务组合
lr_start_transaction为事物开始函数,lr_end_transaction为事物结束函数,并负责记录事物的运行时间。 语法格式如下: int lr_start_transaction (const char * transaction_name); int lr_end_transaction (const char * transaction_name,int status); transacton为事物名称。 status为事物的结束状态:共有LR_PASS(通过)、LR_FAIL(失败)、LR_AUTO(自动)、 LR_STOP(暂停)。可以在事物结束前通过lr_set_transaction_status进行修改。 如果在lr_end_transaction中没有指定结束事物状态是LR_AUTO,而是明确制定为LR_PASS、LR_FAIL、 LR_STOP其中的一种,则事物将以最后制定状态来结束。 需要注意,事物开始后需要通过相同的名称以函数lr_end_transaction结束。
2.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。属性值不分大小写
基本信息:
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",则边界大小写都匹配(不加,也就是默认是大小写敏感的);在边界之后指定“/BIN”,即RB/BIN、RB/BIN,则表示为二进制数据 ;
例如:web_reg_save_param("IsRight","LB/ic=cache-control: private\r\n\r\n","RB/ic=|",LAST);
4、属性值不区分大小写,如”Search=all”
附:
一、什么是关联
关联(correlation):脚本回放过程中,客户端发出请求,通过关联函数所定义的左右边界值(也就是关联规则),在服务器所响应的内容中查找,得到相应的值,已变量的形式替换录制时的静态值,从而向服务器发出正确的请求,这种动态获得服务器响应内容的方法被称作关联。也是把脚本中某些写死的数据,转变成动态的数据。
什么内容需要关联:当脚本中的数据每次回放都发生变化时,并且这个动态数据在后面的请求中需要发送给服务器,那么这个内容需要通过关联来询问服务器,获得该数据的变化结果。例如:
1.登录字符串。带有会话 ID 或时间戳等动态数据的登录字符串。
2.日期/时间戳。使用日期或时间戳或者其他用户凭据的任意字符串。
3.常见前缀。后跟字符串的常见前缀,如 SessionID 或 CustomerID
二、手工关联
web_reg_save_param 函数一般用于LR中进行手工关联,运行脚本时,web_reg_save_param 函数将扫描所访问的后续 HTML 页。如果指定左边界和/ 或右边界, VuGen 将搜索这些边界之间的文本。VuGen 找到文本后,会将其分配给某个参数。
举个例子说明吧:
比如说对源码中的<input type="hidden" id="orderId" name="orderId" value="f28958249e141e62312d855ce73252d3"/>的orderId的值进行关联,那么我们可以这样写:
web_reg_save_param("orderId", "LB=name=\"orderId\" value=\"", "RB=\"", LAST);
这个就是要在整个HTML文件中找,左边界是:name="orderId" value=" 右边界是:"
的中间文本的值,找到后赋给orderId。
资料:
https://blog.csdn.net/jiang1986829/article/details/47113613
https://blog.csdn.net/brbrbrbrbrbr/article/details/52404552
3.web_reg_find-检查点函数
LR检查点
设置检查点的目的不只是为了验证我们的脚本没有错误,而更重要的是一个规范问题,如何使得测试结果更具有说服力,因此建议所有的测试脚本中都添加检查点设置。
一、设置检查点的方法
1.将脚本切换到树结构,在page view页面上找到你要check的文本内容, 并执行鼠标右键,选择Add a text check.
2.将脚本切换回代码界面,在光标闪烁的上行,手动添加如下的代码
web_reg_find("Text/IC=Payment Details", "SaveCount=para_count", LAST);
这里是要运行的页面脚本
if (atoi(lr_eval_string("{para_count}"))>0) //验证是否找到了页面上的要检查的字符串 lr_output_message("Pass!"); else lr_output_message("Failed!");
注意:
l “Payment Details” 为你要检查的文本;
l 脚本执行到此处,不管页面上是否存在你要检查的字符串,脚本都不会报错,而是执行下去。
l 此段代码将找到的你要检查的字符串的个数,存为一个参数。 然后在页面代码的后面,通过检查这个参数的值是否大于0,来判断是否找到了你所要检查的字符串。
l 这里的测试结果均以200状态码返回,其失败的结果将在分析报告中进行分类标识。
//atoi()函数的作用是将一个ASCII字符串转换为整型
//lr_eval_string()函数作用是取得参数值,将字符串变量中的参数值替换为当前的参数值并将这个字符串返回
资料:
https://www.cnblogs.com/lci05/p/3647698.html
四、问题处理
1.replaylog中的中文乱码
解决这个问题必须认识到一个事实就是,loadrunner和测试服务器交换数据使用的是utf8格式,但是展现在replaylog中是使用gb2312格式, 而且在脚本中如何使用web_reg_find的时候也是使用的是gb2312格式,所以知道这个原理后,事情就好办多了。
1.获取测试服务器提供的utf8格式的文字并且转换成gb2312格式展现出来
web_reg_save_param_ex( "ParamName=aa", "LB=ProductName", "RB=ProductBriefName", "NotFound=warning", SEARCH_FILTERS, LAST) ; web_url("web_url", "URL=http://124.238.214.65:70/Scripts/Home/HomeHotProduct.js", "TargetFrame=", "Resource=0", "Referer=", LAST); lr_convert_string_encoding(lr_eval_string("{aa}"),"utf-8","gb2312","str"); lr_output_message(lr_eval_string("{str}"));
2.本地的gb2312的中文经过转换成utf8发给测试服务器
lr_convert_string_encoding(lr_eval_string("智能手机"),"gb2312","utf-8","a1"); web_reg_save_param_ex( "ParamName=aa", "LB={a1}", "RB=", "NotFound=error", SEARCH_FILTERS, LAST); web_url("IndexCategoryProductJson.js", "URL=http://124.238.214.65:70/Scripts/Home/IndexCategoryProductJson.js", "Resource=1", "RecContentType=application/x-javascript", "Referer=http://124.238.214.65:8081/", "Snapshot=t24.inf", LAST);
————————————————
版权声明:本文为CSDN博主「angel1magic」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/angel1magic/article/details/84591985