【测试技术-性能测试-实战1】使用Loadrunner自带的系统学习脚本编写和脚本增强。

1、启动Web Tours Server

  • Hp software->start hp web tours server
  • Hp software->hp web tours application

2、脚本录制
2.1、录制前设置

打开Virtual User Generator

创建脚本,协议选择Web - HTTP/HTML,输入脚本名,选择好脚本存放路径,点击create即可创建好一个空白脚本。

设置录制选项,点击record按钮,设置完基本信息后,点击右下角的Recording Options,设置录制选项:

HTTP/HTML Level设置:使用基于HTML-based script录制的脚本更简洁欸,使用基于URL-based script录制的脚本,会将每个html元素都使用web_url函数加载,脚本冗长,不易关联。实际使用时基于浏览器的的应用程序(未使用HTTP安全协议)推荐选择HTML-based script;非浏览器/使用了HTTPS安全协议,推荐使用URL-based script。
编码设置(防止录制出现中文乱码):HTTP Properties -> Advanced,勾选上Support charset(UTF-8)
其他使用默认选项即可
开始录制:录制选项设置完成后,点击Start Recording即可开始录制。

2.2、开始录制
录制完整的登录->查询航班->选择航班->支付->查看结果->退出登录流程

2.2.1、登录
登录之前先插入一个登录事务:tran01_login,然后输入用户/密码(jojo/bean),点击登录:

 登录完成后,结束登录事务:

2.2.2、查找航班

先点击页面上的Flights,进入查找航班界面,然后插入事务:tran02_findFlight,输入航班信息后,点击continue按钮进入下一步

点击按钮后,结束tran02_findFlight事务。

2.2.3、选择航班

插入事务:trans03_selectFlight,选择航班,然后点击continue,进入下一步

结束trans03_selectFlight事务

2.2.4、支付

插入事务:trans04_payment,输入支付信息后,然后点击continue,进入下一步

 结束trans04_payment事务

2.2.5、查看结果

插入事务:trans05_itinerary,点击Itinerary,查看预定结果

 结束trans05_itinerary事务

2.2.6、退出登录

插入事务:trans06_signOff,点击sign Off按钮退出登录:

结束trans06_signOff事务。

至此,整个预定流程完成,点击结束录制按钮,完成录制,生成录制脚本。

完整的录制脚本如下:

Action()
{

	//打开WebTours主页
	web_url("index.htm", 
		"URL=http://127.0.0.1:1080/WebTours/index.htm", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=", 
		"Snapshot=t1.inf", 
		"Mode=HTML", 
		LAST);

	lr_think_time(13);

	//登录
    lr_start_transaction("tran01_login");
    
	web_submit_data("login.pl", 
		"Action=http://127.0.0.1:1080/cgi-bin/login.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?in=home", 
		"Snapshot=t4.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=userSession", "Value=133951.489509923ziQAVcQpHtVzzzzHtVDtApHHitf", ENDITEM, 
		"Name=username", "Value=jojo", ENDITEM, 
		"Name=password", "Value=bean", ENDITEM, 
		"Name=JSFormSubmit", "Value=on", ENDITEM, 
		"Name=login.x", "Value=51", ENDITEM, 
		"Name=login.y", "Value=10", ENDITEM, 
		LAST);

	lr_end_transaction("tran01_login",LR_AUTO);

	lr_think_time(13);

	//查询航班
	lr_start_transaction("tran02_findFlight");

	web_submit_data("reservations.pl", 
		"Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl?page=welcome", 
		"Snapshot=t9.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=advanceDiscount", "Value=0", ENDITEM, 
		"Name=depart", "Value=Denver", ENDITEM, 
		"Name=departDate", "Value=05/28/2022", ENDITEM, 
		"Name=arrive", "Value=Frankfurt", ENDITEM, 
		"Name=returnDate", "Value=05/29/2022", ENDITEM, 
		"Name=numPassengers", "Value=1", ENDITEM, 
		"Name=seatPref", "Value=Window", ENDITEM, 
		"Name=seatType", "Value=First", ENDITEM, 
		"Name=.cgifields", "Value=roundtrip", ENDITEM, 
		"Name=.cgifields", "Value=seatType", ENDITEM, 
		"Name=.cgifields", "Value=seatPref", ENDITEM, 
		"Name=findFlights.x", "Value=65", ENDITEM, 
		"Name=findFlights.y", "Value=5", ENDITEM, 
		LAST);

	lr_end_transaction("tran02_findFlight",LR_AUTO);

	lr_think_time(21);

	//选择航班
	lr_start_transaction("trans03_selectFlight");

	web_submit_data("reservations.pl_2", 
		"Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Snapshot=t10.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=outboundFlight", "Value=013;592;05/28/2022", ENDITEM, 
		"Name=numPassengers", "Value=1", ENDITEM, 
		"Name=advanceDiscount", "Value=0", ENDITEM, 
		"Name=seatType", "Value=First", ENDITEM, 
		"Name=seatPref", "Value=Window", ENDITEM, 
		"Name=reserveFlights.x", "Value=52", ENDITEM, 
		"Name=reserveFlights.y", "Value=9", ENDITEM, 
		LAST);	
	
	

	lr_end_transaction("trans03_selectFlight",LR_AUTO);

	lr_think_time(26);

	//支付
	lr_start_transaction("trans04_payment");
	
	web_submit_data("reservations.pl_3", 
		"Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Snapshot=t11.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=firstName", "Value=Jojo", ENDITEM, 
		"Name=lastName", "Value=Bean", ENDITEM, 
		"Name=address1", "Value=123", ENDITEM, 
		"Name=address2", "Value=456", ENDITEM, 
		"Name=pass1", "Value=Jojo Bean", ENDITEM, 
		"Name=creditCard", "Value=123456", ENDITEM, 
		"Name=expDate", "Value=1122", ENDITEM, 
		"Name=saveCC", "Value=on", ENDITEM, 
		"Name=oldCCOption", "Value=on", ENDITEM, 
		"Name=numPassengers", "Value=1", ENDITEM, 
		"Name=seatType", "Value=First", ENDITEM, 
		"Name=seatPref", "Value=Window", ENDITEM, 
		"Name=outboundFlight", "Value=013;592;05/28/2022", ENDITEM, 
		"Name=advanceDiscount", "Value=0", ENDITEM, 
		"Name=returnFlight", "Value=", ENDITEM, 
		"Name=JSFormSubmit", "Value=off", ENDITEM, 
		"Name=.cgifields", "Value=saveCC", ENDITEM, 
		"Name=buyFlights.x", "Value=42", ENDITEM, 
		"Name=buyFlights.y", "Value=10", ENDITEM, 
		LAST);

	lr_end_transaction("trans04_payment",LR_AUTO);

	lr_think_time(16);

	//查询预定结果
	lr_start_transaction("trans05_itinerary");

	web_url("welcome.pl", 
		"URL=http://127.0.0.1:1080/cgi-bin/welcome.pl?page=itinerary", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?page=menu&in=flights", 
		"Snapshot=t12.inf", 
		"Mode=HTML", 
		LAST);

	lr_end_transaction("trans05_itinerary",LR_AUTO);

	lr_think_time(19);

	//退出登录
	lr_start_transaction("trans06_signOff");

	web_url("welcome.pl_3", 
		"URL=http://127.0.0.1:1080/cgi-bin/welcome.pl?signOff=1", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?page=menu&in=itinerary", 
		"Snapshot=t13.inf", 
		"Mode=HTML", 
		LAST);

	lr_end_transaction("trans06_signOff",LR_AUTO);

	return 0;
}

3、脚本回放

点击Replay,回放脚本:

脚本回放成功。

4、脚本增强
4.1、参数关联
作用:将服务器返回给客户端的动态值进行关联。

回放成功后,可以登录WebTours查看预定的记录是否增加了一条,如果增加了,说明脚本没问题,可以成功预定。然而登录后,发现预定的数量并没有增加。所以,需要重新检查脚本。

首先是检查登录是否成功。可以看到登录的web_submit_data方法中,提交的参数有userSession,userSession为动态为动态生成,userSession在第一次请求服务器的时候有服务器返回,所以需要对该参数做参数关联。

要获取userSession有两个方法:

在浏览器中请求页面,F12工具查看返回,在响应报文中查找userSession:

 可以看到nav.pl?in=home请求中,返回报文中包含userSession:

<input type="hidden" name="userSession" value="133944.089590928ziiQHtQpVAiDDDDDtVDDiptQtzf"/>
  • 在Loadrunner中,请求的上一步操作的任一地方,点击右键->Show snapshot,然后在Snapshot中使用Ctrl+F查找该值,同样可以找到:

 

 找到userSession后,即可开始编写关联函数,关联函数为web_reg_save_param(),具体如下:

//设置userSession参数关联
web_reg_save_param("userSession",							//参数名
                   "LB=name=\"userSession\" value=\"",		//左边界:参数值的左边字符,如果带有双引号,需要用\进行转义
                   "RB=\"/>",								//右边界:参数值的右边字符,根据左右边界可以唯一确定参数值
                   LAST);	

注意关联需要写到操作函数的上面,关联函数编写完成后,需要替换脚本中的参数值,将登录时的提交参数替换如下:

web_submit_data("login.pl", 
                "Action=http://127.0.0.1:1080/cgi-bin/login.pl", 
                "Method=POST", 
                "RecContentType=text/html", 
                "Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?in=home", 
                "Snapshot=t42.inf", 
                "Mode=HTML", 
                ITEMDATA, 
                "Name=userSession", "Value={userSession}", ENDITEM, 		//参数关联,参数名需要用{}括起来
                "Name=username", "Value=jojo", ENDITEM, 
                "Name=password", "Value=bean", ENDITEM, 
                "Name=JSFormSubmit", "Value=on", ENDITEM, 
                "Name=login.x", "Value=42", ENDITEM, 
                "Name=login.y", "Value=12", ENDITEM, 
                LAST);

关联完成后,重新回放,然后登录网站检查,可以看到Itinerary中订单多了一个记录,每回放一次都会多一条,说明关联成功,脚本可以正常完成登录了。

4.2、参数化
在该脚本中,所有参数均是固定的,比如订票操作,每次都是订的Denver->Frankfurt,如果想要每次预定都使用不同的出发/到达城市对,则需要进行对响应的数据进行参数化,具体操作参考:https://blog.csdn.net/weixin_42115131/article/details/124965795

设置好的脚本如下:
 

web_submit_data("reservations.pl", 
                "Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
                "Method=POST", 
                "RecContentType=text/html", 
                "Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl?page=welcome", 
                "Snapshot=t47.inf", 
                "Mode=HTML", 
                ITEMDATA, 
                "Name=advanceDiscount", "Value=0", ENDITEM, 
                "Name=depart", "Value={depart}", ENDITEM, 					//出发城市参数化
                "Name=departDate", "Value=05/27/2022", ENDITEM, 
                "Name=arrive", "Value={arrive}", ENDITEM, 					//到达城市参数化
                "Name=returnDate", "Value=05/28/2022", ENDITEM, 
                "Name=numPassengers", "Value=1", ENDITEM, 
                "Name=seatPref", "Value=Window", ENDITEM, 
                "Name=seatType", "Value=Business", ENDITEM, 
                "Name=.cgifields", "Value=roundtrip", ENDITEM, 
                "Name=.cgifields", "Value=seatType", ENDITEM, 
                "Name=.cgifields", "Value=seatPref", ENDITEM, 
                "Name=findFlights.x", "Value=63", ENDITEM, 
                "Name=findFlights.y", "Value=8", ENDITEM, 
                LAST);

参数值在Parameters中可以进行设置。

参数设置时,Select next row框选取Unique和Sequential有如下区别,以10个虚拟用户迭代10次为例:

当选择Sequential时,可以看到,同一个每个虚拟用户取值相同,下一次迭代取第二个参数,第6次迭代参数已取完,重新循环取第一个值:

 当选择Unique时,表示每个虚拟用户取唯一的一个值,每次迭代每个虚拟用户都会取不同参数值,由于只设置了5个虚拟用户,所以后5个虚拟用户未取到值:

 替换参数后,重新运行脚本,在runtime setting中将迭代设置为5次,完成后登录网站查看是否生成了5个不同城市对的订单

可以看出,生成的5个记录全是Denver/Frankfurt。参数化并未生效。

再次检查脚本,发现查询航班完成后的选择航班提交的数据,outboundFlight为013;592;05/28/2022,即不论查询结果是什么,每次选择的航班都是013号,592$,该值为查询航班时由服务器返回的值,所以,还需要对该值做参数关联,关联方法同userSession:
 

web_reg_save_param("outboundFlight",
                   "LB=name=\"outboundFlight\" value=\"",
                   "RB=\">",
                   "Ord=2",					//相同的左右边界共有4个,取第二个
                   LAST);

关联之后,把后面脚本中出现该参数的地方都用关联的参数替换掉,然后重新执行脚本,检查结果:

可以看到,成功预定了5张不同出发到达城市对的票。

4.3、检查点设置
订票成功后,页面上会返回字符串”Thank you for booking through Web Tours.“,这儿介绍两种设置检查点的方法:

4.3.1、web_reg_find()函数
参考:https://blog.csdn.net/weixin_42115131/article/details/124965795

4.3.2、保存&对比
原理和参数关联一致,先将服务器返回的参数保存下来:
 

<small><B>Thank you for booking through Web Tours.</B></small>
web_reg_save_param("response",
                   "LB=<small><B>",
                   "RB=</B></small>",
                   LAST);

在payment之后,对服务器返回值和预期值做对比:

//检查支付是否成功
if(strstr(lr_eval_string("{payment_result}"), "Thank you for booking through Web Tours.")!=NULL){
    //strstr(str1, str2)为c语言函数,如果str2为str1子串,则返回字串出现的位置;不是则返回NULL
    //lr_eval_string()函数作用为返回脚本中的一个参数当前的值,格式为:lr_eval_string("{参数名}");
    lr_end_transaction("trans04_payment",LR_PASS);
    //事务有3种结束状态,LR_AUTO为自动结束,不判断成功失败;LR_FAIL为以失败的状态结束;LR_PASS为以成功的状态结束	   	
    lr_output_message("Success! depart is %s, arrive is %s.", lr_eval_string("{depart}"), lr_eval_string("{arrive}"));
    //lr_output_message为打印函数
}else{
    lr_end_transaction("trans04_payment",LR_PASS);
    lr_output_message("FAIL!!!!!!");
}

加入检查点后,重新运行,结果如下:

Action.c(149): Success! depart is Portland, arrive is Denver.
Action.c(149): Success! depart is San Francisco, arrive is Frankfurt.
Action.c(149): Success! depart is Seattle, arrive is London.
Action.c(149): Success! depart is Sydney, arrive is Los Angeles.
Action.c(149): Success! depart is Zurich, arrive is Paris.

至此,脚本调试完成,可以将脚本加载到controller中设置场景执行。完整脚本如下:

Action()
{

	//设置userSession参数关联
	web_reg_save_param("userSession",			//参数名
		"LB=name=\"userSession\" value=\"",		//左边界:参数值的左边字符,如果带有双引号,需要用\进行转义
		"RB=\"/>",								//右边界:参数值的右边字符,根据左右边界可以唯一确定参数值
		LAST);		
	
	//打开WebTours主页
	web_url("index.htm", 
		"URL=http://127.0.0.1:1080/WebTours/index.htm", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=", 
		"Snapshot=t1.inf", 
		"Mode=HTML", 
		LAST);

	lr_think_time(13);

	//登录
	lr_start_transaction("tran01_login");
	
	web_submit_data("login.pl", 
		"Action=http://127.0.0.1:1080/cgi-bin/login.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?in=home", 
		"Snapshot=t4.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=userSession", "Value={userSession}", ENDITEM, 
		"Name=username", "Value=jojo", ENDITEM, 
		"Name=password", "Value=bean", ENDITEM, 
		"Name=JSFormSubmit", "Value=on", ENDITEM, 
		"Name=login.x", "Value=51", ENDITEM, 
		"Name=login.y", "Value=10", ENDITEM, 
		LAST);

	lr_end_transaction("tran01_login",LR_AUTO);

	lr_think_time(13);

	//查询航班
	lr_start_transaction("tran02_findFlight");
	
	//设置outboundFlight关联函数
	web_reg_save_param("outboundFlight",
       "LB=name=\"outboundFlight\" value=\"",
       "RB=\">",
       "Ord=2",					//相同的左右边界共有4个,取第二个
       LAST);	

	web_submit_data("reservations.pl", 
		"Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl?page=welcome", 
		"Snapshot=t9.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=advanceDiscount", "Value=0", ENDITEM, 
		"Name=depart", "Value={depart}", ENDITEM, 
		"Name=departDate", "Value=05/28/2022", ENDITEM, 
		"Name=arrive", "Value={arrive}", ENDITEM, 
		"Name=returnDate", "Value=05/29/2022", ENDITEM, 
		"Name=numPassengers", "Value=1", ENDITEM, 
		"Name=seatPref", "Value=Window", ENDITEM, 
		"Name=seatType", "Value=First", ENDITEM, 
		"Name=.cgifields", "Value=roundtrip", ENDITEM, 
		"Name=.cgifields", "Value=seatType", ENDITEM, 
		"Name=.cgifields", "Value=seatPref", ENDITEM, 
		"Name=findFlights.x", "Value=65", ENDITEM, 
		"Name=findFlights.y", "Value=5", ENDITEM, 
		LAST);

	lr_end_transaction("tran02_findFlight",LR_AUTO);

	lr_think_time(21);

	//选择航班
	lr_start_transaction("trans03_selectFlight");

	web_submit_data("reservations.pl_2", 
		"Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Snapshot=t10.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=outboundFlight", "Value={outboundFlight}", ENDITEM, 
		"Name=numPassengers", "Value=1", ENDITEM, 
		"Name=advanceDiscount", "Value=0", ENDITEM, 
		"Name=seatType", "Value=First", ENDITEM, 
		"Name=seatPref", "Value=Window", ENDITEM, 
		"Name=reserveFlights.x", "Value=52", ENDITEM, 
		"Name=reserveFlights.y", "Value=9", ENDITEM, 
		LAST);	

	lr_end_transaction("trans03_selectFlight",LR_AUTO);

	lr_think_time(26);

	//支付
	lr_start_transaction("trans04_payment");
	
    //保存返回的参数,做事务状态检查
	web_reg_save_param("payment_result",
       "LB=<small><B>",
       "RB=</B></small>",
       LAST);
	
	web_submit_data("reservations.pl_3", 
		"Action=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/reservations.pl", 
		"Snapshot=t11.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=firstName", "Value=Jojo", ENDITEM, 
		"Name=lastName", "Value=Bean", ENDITEM, 
		"Name=address1", "Value=123", ENDITEM, 
		"Name=address2", "Value=456", ENDITEM, 
		"Name=pass1", "Value=Jojo Bean", ENDITEM, 
		"Name=creditCard", "Value=123456", ENDITEM, 
		"Name=expDate", "Value=1122", ENDITEM, 
		"Name=saveCC", "Value=on", ENDITEM, 
		"Name=oldCCOption", "Value=on", ENDITEM, 
		"Name=numPassengers", "Value=1", ENDITEM, 
		"Name=seatType", "Value=First", ENDITEM, 
		"Name=seatPref", "Value=Window", ENDITEM, 
		"Name=outboundFlight", "Value={outboundFlight}", ENDITEM, 
		"Name=advanceDiscount", "Value=0", ENDITEM, 
		"Name=returnFlight", "Value=", ENDITEM, 
		"Name=JSFormSubmit", "Value=off", ENDITEM, 
		"Name=.cgifields", "Value=saveCC", ENDITEM, 
		"Name=buyFlights.x", "Value=42", ENDITEM, 
		"Name=buyFlights.y", "Value=10", ENDITEM, 
		LAST);
	
	//检查支付是否成功
	if(strstr(lr_eval_string("{payment_result}"), "Thank you for booking through Web Tours.")!=NULL){
	   	//strstr(str1, str2)为c语言函数,如果str2为str1子串,则返回字串出现的位置;不是则返回NULL
	   	//lr_eval_string()函数作用为返回脚本中的一个参数当前的值,格式为:lr_eval_string("{参数名}");
	   	lr_end_transaction("trans04_payment",LR_PASS);
		//事务有3种结束状态,LR_AUTO为自动结束,不判断成功失败;LR_FAIL为以失败的状态结束;LR_PASS为以成功的状态结束	   	
		lr_output_message("Success! depart is %s, arrive is %s.", lr_eval_string("{depart}"), lr_eval_string("{arrive}"));
		//lr_output_message为打印函数
	}else{
	   	lr_end_transaction("trans04_payment",LR_PASS);
	   	lr_output_message("FAIL!!!!!!");
	}


	lr_think_time(16);

	//查询预定结果
	lr_start_transaction("trans05_itinerary");

	web_url("welcome.pl", 
		"URL=http://127.0.0.1:1080/cgi-bin/welcome.pl?page=itinerary", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?page=menu&in=flights", 
		"Snapshot=t12.inf", 
		"Mode=HTML", 
		LAST);

	lr_end_transaction("trans05_itinerary",LR_AUTO);

	lr_think_time(19);

	//退出登录
	lr_start_transaction("trans06_signOff");

	web_url("welcome.pl_3", 
		"URL=http://127.0.0.1:1080/cgi-bin/welcome.pl?signOff=1", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?page=menu&in=itinerary", 
		"Snapshot=t13.inf", 
		"Mode=HTML", 
		LAST);

	lr_end_transaction("trans06_signOff",LR_AUTO);

	return 0;
}


 

猜你喜欢

转载自blog.csdn.net/lzz718719/article/details/130715173