目录

项目的截图

测试的流程

脚本replay报错分析

问题

问题解决

完整代码和注释


项目的截图

商品列表页

response从body中获取内容_loadrunner

购物车页

response从body中获取内容_loadrunner_02

 订单详情页

response从body中获取内容_软件测试_03

我的订单页

response从body中获取内容_response从body中获取内容_04

测试的流程

上面的商城项目是JavaWeb的课程作业,这学期上软件测试的课程需要用来做测试。下面简单介绍一下,录制的测试脚本的主要流程。

  1. 在 "商品列表页" 挑选商品,并点击 "加入购物车" 按钮,将商品添加到购物车。
  2. 挑选商品完毕后,在 "购物车页面" 选择要结算的商品,并点击 "结算" 按钮。
  3. 跳转到 "订单详情页",填写订单信息,并点击 "增加订单" 按钮,生成订单。
  4. 在 "我的订单页面" 点击 "支付" 按钮。

脚本replay报错分析

录制出来脚本,在 "replay" 的时候出现问题。结合后端代码,分析整个流程,定位问题根源。

1、数据库中有一张关键的表 cart_item (用来描述购物车的)

response从body中获取内容_关联_05

  • user_id:用户id(比如说A)
  • pid:商品id(比如说B)
  • num:用户A将多少件商品B放入到自己的购物车
  • cartID:自增长id

2、当用户A将商品B放入到购物车中时,假如用户A的购物车中不存在商品B(cart_item表没有user_id为A,pid为B的记录),则插入一条新记录。假如对应记录,则将对应记录的 num 加 1。

3、用户在购物车页面点击 "结算" 按钮时,会将勾选对应的商品的 cartID (多个)传递到 "订单详情页"。在 "订单详情页" 中要罗列用户【确认】结算的商品(即用户在购物车页面【勾选】的商品),后端拿到 cartID (多个),在 cart_item 表找到对应的记录,并与 product 表进行关联。

4、在 "商品详情页" 点击 "增加订单" 按钮,后端生成订单信息。 

5、支付订单成功,会清空购物车,会将 购物车对应的(多个cartID对应的)记录全部删除。

问题

在重放脚本的时候,将商品加入购物车,会插入往 cart_item 插入新的记录,生成新的自增长主键 cartID。而之后的 "订单详情页","增加订单"操作, "支付"操作,"清空购物车操作" 都【需要】前面生成的 cartID。换言之,就是:前一次请求的结果,作为之后请求的参数

而 loadrunner 录制的脚本的请求参数都是 "定死的",录制的时候是咋样,生成的脚本就是咋样。录制的时候,支付之后就把购物车给清空了(清除了对应的 cart_item 记录)。脚本中的 cartID ,在清空购物车后就不存在了。脚本重放时,将相同的商品加入购物车,此时往 cart_item 表插入了新的记录,此时对应的 cartID 是新生成的。而拿着旧的 cartID (不存在了,已经被删了),进行之后的 "订单详情页","增加订单"操作, "支付"操作显然会失败。

比较难描述清楚,我已经尽我所能去描述清楚问题根源了。可能对于写过这个项目的同学来说,更能有体会。

假如可以明白上面我所表述的情景,是不是对 loadrunner 中的 "关联" 的概念的理解会更加清晰???

response从body中获取内容_关联_06

问题解决

核心思想是:从上一次响应的数据中,提取出出对应的参数,作为下一次请求的参数。

回到上面的情况,在购物车的html页面中,有新生成的 cartID。我们只需要拿到响应体,并匹配出来,并作为后续请求的参数即可。

下面介绍相关的 函数:

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

该函数可以在响应数据中匹配出我们需要的值,放在一个请求前面。

o ParamName: 存放得到的动态内容的参数名称

o 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,表示一直到结尾的整个字串都存入参数。

关于该函数的详细使用,参考以下两篇博客:



针对上述作业问题的解决,如何使用上述函数进行手动关联。请参看下面代码和注释。

完整代码和注释

Action()
{
	int count;
	int i;
	char param[10][20];
	char cartIds[1024];

	lr_think_time(9);

	// 商品列表页
	web_url("prodlist", 
		"URL=http://localhost:8081/EasyMall/prodlist", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/index", 
		"Snapshot=t3.inf", 
		"Mode=HTML", 
		EXTRARES, 
		"Url=css/prodList.css", ENDITEM, 
		"Url=upload/5/2/3/4/7/8/d/c/1838eaa6-6459-420f-b8e2-6ea9f43c4b5e_dfd259ab-bcc7-43f6-a9d5-62872ff5671e.jpg", ENDITEM, 
		"Url=css/pageHelper.css", ENDITEM, 
		"Url=js/pageHelper.js", ENDITEM, 
		"Url=js/jquery-1.4.2.js", ENDITEM, 
		"Url=upload/5/e/d/5/4/5/e/b/5f0d34dc-157f-49ba-ad39-1b28927ba6ae_1005714.jpg", ENDITEM, 
		"Url=img/prodlist/search_03.jpg", ENDITEM, 
		"Url=img/core_bg.png", ENDITEM, 
		LAST);

	lr_start_transaction("add_to_cart_transaction");

	// 将商品加入购物车
	web_url("addCart", 
		"URL=http://localhost:8081/EasyMall/cart/addCart?pid=09f47493-214d-44bc-927d-6ce0bf89a057&buyNum=1", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/prodlist", 
		"Snapshot=t4.inf", 
		"Mode=HTML", 
		EXTRARES, 
		"Url=../css/cart.css", "Referer=http://localhost:8081/EasyMall/cart/showcart", ENDITEM, 
		LAST);

	// 回到商品列表页
	web_url("prodlist_2", 
		"URL=http://localhost:8081/EasyMall/prodlist", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/cart/showcart", 
		"Snapshot=t5.inf", 
		"Mode=HTML", 
		LAST);

	// 第2页
	web_url("prodlist_3", 
		"URL=http://localhost:8081/EasyMall/prodlist?page=2", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/prodlist", 
		"Snapshot=t6.inf", 
		"Mode=HTML", 
		EXTRARES, 
		"Url=upload/7/c/b/f/7/d/2/9/5e229aef-063f-4d0d-91df-2d4aa7167670_6f84843a-1d1e-49c7-b4ce-c035d7790171.jpg", "Referer=http://localhost:8081/EasyMall/prodlist?page=2", ENDITEM, 
		"Url=upload/4/d/2/a/2/3/1/8/b3c3fc7a-222c-49be-9491-f466553d2284_386718.jpg", "Referer=http://localhost:8081/EasyMall/prodlist?page=2", ENDITEM, 
		LAST);

	web_set_max_html_param_len( "262144"); // 默认最大长度为256
//	web_reg_save_param( "ResponseBody" , "LB=" , "RB=" , "Search=Body", LAST);
	web_reg_save_param("cart_ids",
                     "LB=class=\"prodC\" id=\"",
                     "RB=\"/>",
                     "ORD=ALL",
                     "Search=Body",LAST);
	
	//web_save_header( REQUEST , "RequestHeader"); // REQUEST为内置变量,保存请求的头信息,需在发送URL请求前注册使用
	//web_save_header( RESPONSE , "ResponseHeader"); // RESPONSE保存响应的头信息
	
	// 将商品加入购物车
	web_url("addCart_2", 
		"URL=http://localhost:8081/EasyMall/cart/addCart?pid=103e5414-0da2-4fba-b92f-0ba876e08939&buyNum=1", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/prodlist?page=2", 
		"Snapshot=t7.inf", 
		"Mode=HTML", 
		LAST);
	
	// ------------------------------------------------------------------------------------
	//lr_output_message( "# 请求头信息: \n %s" , lr_eval_string( "{RequestHeader}"));
	//lr_output_message( "# 响应头信息: \n %s" , lr_eval_string( "{ResponseHeader}"));
	
	// 为了提取 cartIds
	lr_output_message( "# 响应内容体: \n %s" , lr_eval_string( "{cart_ids}"));
    count = atoi(lr_eval_string("{cart_ids_count}"));
	lr_output_message("购物车中的商品数量:%d", count); // 2
	strcpy(cartIds, "");
	for(i = 1; i <= count; i++) {
       sprintf(param[i], "{cart_ids_%d}", i);//参数名称存到数组中
       lr_output_message(lr_eval_string(param[i]));
       strcat(cartIds, lr_eval_string(param[i]));
       if (i < count) {
       		strcat(cartIds, ",");
       }
    }
	lr_output_message(cartIds);
	lr_save_string(cartIds, "cartIds"); // 保存变量才可以通过{}引用
	// ------------------------------------------------------------------------------------
    
	lr_end_transaction("add_to_cart_transaction",LR_AUTO);

	lr_think_time(7);

	lr_start_transaction("produce_order_transaction");

	// debug
//	web_save_header( REQUEST , "RequestHeader");
//	lr_output_message( "# 请求头信息: \n %s" , lr_eval_string( "{RequestHeader}"));
	// 点击生成订单按钮
	web_submit_data("order_add", 
		"Action=http://localhost:8081/EasyMall/order/order_add", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/cart/showcart", 
		"Snapshot=t8.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=cartIds", "Value={cartIds}", ENDITEM, 
		LAST);
	
	
	// 订单详情页
	web_url("order_add_2", 
		"URL=http://localhost:8081/EasyMall/order/order_add?cartIds={cartIds}", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/cart/showcart", 
		"Snapshot=t9.inf", 
		"Mode=HTML", 
		EXTRARES, 
		"Url=../css/addOrder.css", "Referer=http://localhost:8081/EasyMall/order/order_add?cartIds={cartIds}", ENDITEM, 
		LAST);

	lr_end_transaction("produce_order_transaction",LR_AUTO);

	lr_start_transaction("submit_order_transaction");
	
	// 为了提取订单号
	web_reg_save_param("order_id",
                     "LB=EasyMall/order/payorder?id=",
                     "RB=src=\"/EasyMall/img/orderList/zx.jpg",
                     "SaveLen=36",
                     "Search=Body",LAST);
	// 提交订单
	web_submit_data("addOrder", 
		"Action=http://localhost:8081/EasyMall/order/addOrder", 
		"Method=POST", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/order/order_add?cartIds={cartIds}", 
		"Snapshot=t10.inf", 
		"Mode=HTML", 
		ITEMDATA, 
		"Name=receiverinfo", "Value=广东省佛山市南海区狮山镇狮山大学城华南师范大学南海校区(菜鸟驿站)", ENDITEM, 
		"Name=", "Value=1", ENDITEM, 
		"Name=cartIds", "Value={cartIds}", ENDITEM, 
		"Name=", "Value=增加订单", ENDITEM, 
		EXTRARES, 
		"Url=../css/orderList.css", "Referer=http://localhost:8081/EasyMall/order/showorder", ENDITEM, 
		"Url=../img/orderList/zx.jpg", "Referer=http://localhost:8081/EasyMall/order/showorder", ENDITEM, 
		"Url=../img/orderList/sc.jpg", "Referer=http://localhost:8081/EasyMall/order/showorder", ENDITEM, 
		LAST);
	
	lr_output_message( "# order_id:%s" , lr_eval_string( "{order_id}"));
	

	lr_end_transaction("submit_order_transaction",LR_AUTO);
	
	lr_start_transaction("pay_transaction");

	// 支付订单
	web_url("payorder", 
		"URL=http://localhost:8081/EasyMall/order/payorder?id={order_id}", 
		"Resource=0", 
		"RecContentType=text/html", 
		"Referer=http://localhost:8081/EasyMall/order/showorder", 
		"Snapshot=t11.inf", 
		"Mode=HTML", 
		LAST);

	lr_end_transaction("pay_transaction",LR_AUTO);

	return 0;
}