品味性能之道<八>:Loadrunner关联技巧与字符处理
2013-12-21 01:02
555 查看
一、概述
Loadrunner作为HP出品的性能测试工具,拥有太多奇妙魔法甜点供予性能测试人员享用,其中吃起来比较有嚼劲的那就是关联了。当然在关联之后我们还需要一些简单的字符处理,用以生成我们所需要的切糕、煎饼果子等。
ps:在此我只会分享手动关联技巧。
二、为什么要关联
通常而言我们的网络应用软件都需要输入账户密码登陆,在用户验证通过登陆以后,服务器如何确认谁是谁呢?
此时一般而言就是SESSIONID了,如下图所示:
![](http://images.cnitblog.com/blog/538961/201312/21005744-aa844998c47a48b481f522c67b065c59.jpg)
Session在 网络应用中称为“会话”,借助它可提供客户端与服务系统之 间必要的交互。因为HTTP协议本身是无状态的,所以经常需要 通过Session来解决服务端和浏览器的保持状态的解决方案。用户 向服务器发送第一个请求时,服务器为其建立一个Session,并为 此Session创建一个标识,用户随后的所有请求都应包括这个标识 号。服务器会校对这个标识号以判断请求属于哪个Session。会话 保持有效,默认状况下,直到浏览器关闭,会话才结束。
Session中存储的内容包括用户信息:昵称、用户ID、登录状 态等。
我们的服务器通过SESSIONID确认了,谁是谁?但是在我们所录制的脚本里面,每次发送的协议包还一直是我们所录制的内容,此时就引发了如下报错信息:
Error -26612: HTTP Status-Code=500 (Internal Server Error) for
当然这项报错信息,除了是因为服务器无法识别用户以外。更为根本的原因在于发送给服务器的协议包,导致了服务器报500错误。
那还有那些原因导致报错呢?
数据新增修改删除,违反唯一索引(未关联页面隐藏的表关键字段)
发送回服务器的字段所用字符集,不能被服务器正确解析
SESSIONID不被服务器认可
以上只是简单的列举了我所经历过的现象,如果有错漏请大家多多指正。
一般我遇到这问题,在毫无头绪的时候我是如此做的:
开启浏览器F12开发人员工具,分析页面request与response
如果还是难以发现其中症结,就从svn下载源码,自己搭建开发环境,回放脚本发送协议,源码中断点排查
当没有源码的情况下,我们还可以考虑反编译war文件,利用Eclipse及其强大的插件,断点排查
三、如何建立关联
建立关联我总结了以下几步:
![](http://images.cnitblog.com/blog/538961/201312/21005837-ceee4e7233104d278a1dc6399641e560.png)
![](file:///C:/Users/sniffer/AppData/Local/YNote/Data/qq989504294F9FB3FF575644ACE96D2EF1/e90c41947a854b2599db5cbd344fb070/clipboard.png)
(1)、明确关联字段
录制结束以后,进入Tree试图,查看Response Body,如下图所示:
![](http://images.cnitblog.com/blog/538961/201312/21005952-e7a3a0b7c5a2456f98d738427d34fdc4.jpg)
![](file:///C:/Users/sniffer/AppData/Local/YNote/Data/qq989504294F9FB3FF575644ACE96D2EF1/c0967246f0b645bfbc62d6e4bdbbf75a/cf60acb5cba64c7abd568cd2d5ead4cf.jpg)
<r id="value":这里的“value”作为服务器确认字段唯一操作ID,它是我们需要关联的字段。
在确定操作ID之后,我们还需要确定哪个值是数据库表里面的主键或者复合主键字段,如下图所示:
![](http://images.cnitblog.com/blog/538961/201312/21010023-c18de9a470794d9aad0af107cddb6fcf.jpg)
![](file:///C:/Users/sniffer/AppData/Local/YNote/Data/qq989504294F9FB3FF575644ACE96D2EF1/9ab4fcc87b9045e19dec5524f7922e4b/7e0366f2e2e14b41b19919b8f913ab21.jpg)
在确定我们的主键为PARTY_ID之后,我们通过查询数据库得知,前五位为”10000“,长度为十四的数字为我们需要关联的另一个字段。(因涉及安全原因数据库查询结果,不能予以展示)
(2)、创建关联函数
创建关于 <r id="value"这一字段的关键,相对而言比较容易确定,它的左边界为:r id=\",右边界为:\” pageIndex。因为页面返回了大量相同规则的id,所以在此我设置Ordinal=ALL。关联函数如下:
web_reg_save_param_ex(
"ParamName=ridList",
"LB= r id=\"",
"RB= \"",
"Ordinal=ALL",
SEARCH_FILTERS,
"Scope=All",
"RequestUrl=**********************", LAST);
创建关于主键字段的关联,相对比较复杂。在此确定它的左边界为:,1000,右边界为:,1。关联函数如下如下:
web_reg_save_param_ex(
"ParamName=party_id",
"LB=,1000",
"RB=,1",
"Ordinal=ALL",
SEARCH_FILTERS,
"Scope=All",
"RequestUrl=**********************",LAST);
(3)、处理关联字段
此前我们在处理<r id="value"的时候,获取了ridList这个数组。通常情况下,通过在数组变量之后添加”_“,以及以1为起点的数据游标,获取相应的数组元素,用以下函数:
lr_eval_string("{ridList_1}");
在此推荐一个LR提供随机获取数组元素的函数:
lr_paramarr_random("ridList");
总所周知Loadrunner是以c语言为基础设计的脚本,我们常常需要对关联函数所生成的字符进行一些简单的操作,在此分享一些c语言字符操作函数及语法知识。
以上代码相关内容不感兴趣的同学,其实可以跳过滴。
下面分享两个我所写的函数,用于获取按一定分隔符分隔的字符串中字符。类似此类字符"23sdf|2323d|jdjj,|||2323|3dd|"
//argv为源字符串,delimiters为切分分隔符,number为所需获取分隔符数
char* strlick(char *argv,const char delimiters ,int number)
{
int i;
int j = 0;
int p = 0;
char buf[64] = {0};
if(number < 1)
{
return "the number can't < 1";
}
for(i = 0;argv[i] != 0;i++)
{
buf[j] = argv[i];
if(argv[i] == delimiters)
{
buf[j] = 0;
if(p == number) return buf;
j = 0;
p++;
continue;
}
j++;
}
return "can't find";
}
//argv为源字符串,delimiters为切分分隔符, number为所需获取分隔符数 ,length为所需截取字符长度
char* strputty(char *argv,const char delimiters ,int number,int length)
{
int count = 0;
char buf[64] = {0};
int i ;
for(i = 0;argv[i] != 0;i++)
{
if(argv[i] == delimiters)
{
if(count == number)
{
strncpy(buf,argv + i +1,length);
return buf;
}
count++;
continue;
}
}
return "can't find";
}
(4)、替换关联字段
就替换关联字段而言,已然没有什么奥妙。不过在此推荐一个小技巧,把被处理关联字段复制起来,然后按快捷键ctrl + h全局替换相应的{value}。
四、总结
Loadrunner应用各种函数不会使,其实官方文档才是最好的资料查找点。它给予了各种详细的应用技巧说明,确实找不到资料的时候,推荐上google。
系列博客:
品味性能之道<一>:性能测试思维与误区
品味性能之道<二>:性能工程师可以具备的专业素养
品味性能之道<三>:方法论
品味性能之道<四>:管理重于技术
品味性能之道<五>:SQL分析工具
品味性能之道<六>:图形化SQL分析工具
品味性能之道<七>:索引基础
品味性能之道<八>:Loadrunner关联技巧与字符处理
品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述
品味性能之道<十>:Oracle Hint
品味性能之道<十一>:JAVA中switch和if性能比较
深入理解Loadrunner中的Browser Emulation
使用Loadrunner对IBM MQ进行性能测试
怎么做性能测试--响应时间
Loadrunner作为HP出品的性能测试工具,拥有太多奇妙魔法甜点供予性能测试人员享用,其中吃起来比较有嚼劲的那就是关联了。当然在关联之后我们还需要一些简单的字符处理,用以生成我们所需要的切糕、煎饼果子等。
ps:在此我只会分享手动关联技巧。
二、为什么要关联
通常而言我们的网络应用软件都需要输入账户密码登陆,在用户验证通过登陆以后,服务器如何确认谁是谁呢?
此时一般而言就是SESSIONID了,如下图所示:
![](http://images.cnitblog.com/blog/538961/201312/21005744-aa844998c47a48b481f522c67b065c59.jpg)
Session在 网络应用中称为“会话”,借助它可提供客户端与服务系统之 间必要的交互。因为HTTP协议本身是无状态的,所以经常需要 通过Session来解决服务端和浏览器的保持状态的解决方案。用户 向服务器发送第一个请求时,服务器为其建立一个Session,并为 此Session创建一个标识,用户随后的所有请求都应包括这个标识 号。服务器会校对这个标识号以判断请求属于哪个Session。会话 保持有效,默认状况下,直到浏览器关闭,会话才结束。
Session中存储的内容包括用户信息:昵称、用户ID、登录状 态等。
我们的服务器通过SESSIONID确认了,谁是谁?但是在我们所录制的脚本里面,每次发送的协议包还一直是我们所录制的内容,此时就引发了如下报错信息:
Error -26612: HTTP Status-Code=500 (Internal Server Error) for
当然这项报错信息,除了是因为服务器无法识别用户以外。更为根本的原因在于发送给服务器的协议包,导致了服务器报500错误。
那还有那些原因导致报错呢?
数据新增修改删除,违反唯一索引(未关联页面隐藏的表关键字段)
发送回服务器的字段所用字符集,不能被服务器正确解析
SESSIONID不被服务器认可
以上只是简单的列举了我所经历过的现象,如果有错漏请大家多多指正。
一般我遇到这问题,在毫无头绪的时候我是如此做的:
开启浏览器F12开发人员工具,分析页面request与response
如果还是难以发现其中症结,就从svn下载源码,自己搭建开发环境,回放脚本发送协议,源码中断点排查
当没有源码的情况下,我们还可以考虑反编译war文件,利用Eclipse及其强大的插件,断点排查
三、如何建立关联
建立关联我总结了以下几步:
![](http://images.cnitblog.com/blog/538961/201312/21005837-ceee4e7233104d278a1dc6399641e560.png)
![](file:///C:/Users/sniffer/AppData/Local/YNote/Data/qq989504294F9FB3FF575644ACE96D2EF1/e90c41947a854b2599db5cbd344fb070/clipboard.png)
(1)、明确关联字段
录制结束以后,进入Tree试图,查看Response Body,如下图所示:
![](http://images.cnitblog.com/blog/538961/201312/21005952-e7a3a0b7c5a2456f98d738427d34fdc4.jpg)
![](file:///C:/Users/sniffer/AppData/Local/YNote/Data/qq989504294F9FB3FF575644ACE96D2EF1/c0967246f0b645bfbc62d6e4bdbbf75a/cf60acb5cba64c7abd568cd2d5ead4cf.jpg)
<r id="value":这里的“value”作为服务器确认字段唯一操作ID,它是我们需要关联的字段。
在确定操作ID之后,我们还需要确定哪个值是数据库表里面的主键或者复合主键字段,如下图所示:
![](http://images.cnitblog.com/blog/538961/201312/21010023-c18de9a470794d9aad0af107cddb6fcf.jpg)
![](file:///C:/Users/sniffer/AppData/Local/YNote/Data/qq989504294F9FB3FF575644ACE96D2EF1/9ab4fcc87b9045e19dec5524f7922e4b/7e0366f2e2e14b41b19919b8f913ab21.jpg)
在确定我们的主键为PARTY_ID之后,我们通过查询数据库得知,前五位为”10000“,长度为十四的数字为我们需要关联的另一个字段。(因涉及安全原因数据库查询结果,不能予以展示)
(2)、创建关联函数
创建关于 <r id="value"这一字段的关键,相对而言比较容易确定,它的左边界为:r id=\",右边界为:\” pageIndex。因为页面返回了大量相同规则的id,所以在此我设置Ordinal=ALL。关联函数如下:
web_reg_save_param_ex(
"ParamName=ridList",
"LB= r id=\"",
"RB= \"",
"Ordinal=ALL",
SEARCH_FILTERS,
"Scope=All",
"RequestUrl=**********************", LAST);
创建关于主键字段的关联,相对比较复杂。在此确定它的左边界为:,1000,右边界为:,1。关联函数如下如下:
web_reg_save_param_ex(
"ParamName=party_id",
"LB=,1000",
"RB=,1",
"Ordinal=ALL",
SEARCH_FILTERS,
"Scope=All",
"RequestUrl=**********************",LAST);
(3)、处理关联字段
此前我们在处理<r id="value"的时候,获取了ridList这个数组。通常情况下,通过在数组变量之后添加”_“,以及以1为起点的数据游标,获取相应的数组元素,用以下函数:
lr_eval_string("{ridList_1}");
在此推荐一个LR提供随机获取数组元素的函数:
lr_paramarr_random("ridList");
总所周知Loadrunner是以c语言为基础设计的脚本,我们常常需要对关联函数所生成的字符进行一些简单的操作,在此分享一些c语言字符操作函数及语法知识。
函数名 | 英文描述 | 乌龙翻译(看不明白,就别看了) |
strset | Fills a string with a specific character. char *strset( char *string1, int character ); string1 The string to which to add the characher. character The character(s) to add. | 一二三四五,来一起变身,凸凸凸凸凸 |
strchr | Returns the pointer to the first occurrence of a character in a string. char *strchr( const char *string, int c ); string The string that is searched. c The character that is searched for in the string. | 买猪肉,从第一块脊骨那儿斩断,只要后面的,多了不要 |
strrchr | Finds the last occurrence of a character in a string. char *strrchr( const char *string, int c ); string The string that is searched. c The character that is searched for in the string. | 又买猪肉,从最后一块脊骨那儿斩断,只买后面的 胃口不好,少吃点,话说最后一块脊骨后面,是啥呢? |
strcpy | Copies one string to another. char *strcpy( char *dest, const char *source ); dest The destination string into which source is copied. source The string that is sopied. | 克隆其实很简单,复制一个字符串到另一个字符串中 |
strncpy | Copies the first n characters of one string to another. char *strncpy( char *dest, const char *source, size_t n ); dest The destination string to which n characters are copied. source The source string from which n characters are copied. n The number of characters copied. | 买了一头猪,看中了大前蹄前面一节儿,切好了装我兜里,包括大前蹄哟 |
strdup | Duplicates a string. char *strdup( const char *string ); string The string that is duplicated. | 复制一个字符串 |
strlen | Returns the length of a string. size_t strlen( const char *string ); string The string whose is returned. | “鞭长莫及” |
strwr | Converts a string to lower case. char *strlwr( char *string ); string The string whose characters are converted to lower case. | 好吧,中文可没小写版,别乱用哟 |
strupr | Converts a string to upper case. char *strupr( char *string ); string The string whose characters are converted to upper case. | 好吧,中文可没大写版,别乱用哟 |
strcmp | Compares two strings to determine the alphabetic order. int strcmp( const char *string1, const char *string2 ); string1 The frist string that is compared. string2 The second string that is compared. | 大小写敏感 |
stricmp | Performs a case-insensitive comparison of two strings. int stricmp( const char *string1, const char *string2 ); string1 The firest string for comparison. string2 The second string for comparison. | 大小写不敏感 |
strncmp | Compares the first n characters of two strings. int strncmp( const char *string1, const char *string2, size_t n ); string1 The firest string for comparison. string2 The second string for comparison. n The number of characters in each string that are compared. | 大小写敏感 |
strnicmp | Performs a case-insensitive comparison of n strings. int strnicmp( const char *string1, const char *string2, size_t num); string1 The firest string for comparison. string2 The second string for comparison. num The number of characters to compare. | 大小写不敏感 |
strcat | Concatenates two strings. char *strcat( char *to, const char *from ); to The string at the end of which the from string is concatenated. from The string concatenated to the end of the to string. | String"B"接到String"2"后面,化生String"2B" |
strncat | Concatenates n characters from one string to another. char *strncat( char *to_string, const char *from_string, size_t n ); to_string The string to which n charachters are concatenated. from_string The string from whice n charachters are concatenated. n The number of characters to be concatenated. | String"BBBB"接到String"2"后面,只接一位,化生String"2B" |
strstr | Returns the first occurrence of one string in another. char *strstr( const char *string1, const char *string2 ); string1 The string that is searched. string2 The string that is searched for in the first string. | 查找一个字符串 |
strtok | Returns a token from a string delimited by specified characters. char *strtok( char *string, const char *delimiters ); string The string to scan. delimiters The string consisting of the character or characters that delimit tokens in the first string. | 老板,来一整根龙骨,按每个骨节切开,依着原来的顺序打包给我 |
strspn | Returns the length of the leading characters in a string that are contained in a specified string. size_t *strspn( const char *string, const char *skipset ); string Null -terminated string to be scanned. skipset Null -terminated string containing character set. | strspn返回string起始部分匹配skipset 中任意字符串的字符数 |
下面分享两个我所写的函数,用于获取按一定分隔符分隔的字符串中字符。类似此类字符"23sdf|2323d|jdjj,|||2323|3dd|"
//argv为源字符串,delimiters为切分分隔符,number为所需获取分隔符数
char* strlick(char *argv,const char delimiters ,int number)
{
int i;
int j = 0;
int p = 0;
char buf[64] = {0};
if(number < 1)
{
return "the number can't < 1";
}
for(i = 0;argv[i] != 0;i++)
{
buf[j] = argv[i];
if(argv[i] == delimiters)
{
buf[j] = 0;
if(p == number) return buf;
j = 0;
p++;
continue;
}
j++;
}
return "can't find";
}
//argv为源字符串,delimiters为切分分隔符, number为所需获取分隔符数 ,length为所需截取字符长度
char* strputty(char *argv,const char delimiters ,int number,int length)
{
int count = 0;
char buf[64] = {0};
int i ;
for(i = 0;argv[i] != 0;i++)
{
if(argv[i] == delimiters)
{
if(count == number)
{
strncpy(buf,argv + i +1,length);
return buf;
}
count++;
continue;
}
}
return "can't find";
}
(4)、替换关联字段
就替换关联字段而言,已然没有什么奥妙。不过在此推荐一个小技巧,把被处理关联字段复制起来,然后按快捷键ctrl + h全局替换相应的{value}。
四、总结
Loadrunner应用各种函数不会使,其实官方文档才是最好的资料查找点。它给予了各种详细的应用技巧说明,确实找不到资料的时候,推荐上google。
系列博客:
品味性能之道<一>:性能测试思维与误区
品味性能之道<二>:性能工程师可以具备的专业素养
品味性能之道<三>:方法论
品味性能之道<四>:管理重于技术
品味性能之道<五>:SQL分析工具
品味性能之道<六>:图形化SQL分析工具
品味性能之道<七>:索引基础
品味性能之道<八>:Loadrunner关联技巧与字符处理
品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述
品味性能之道<十>:Oracle Hint
品味性能之道<十一>:JAVA中switch和if性能比较
深入理解Loadrunner中的Browser Emulation
使用Loadrunner对IBM MQ进行性能测试
怎么做性能测试--响应时间
相关文章推荐
- 品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述
- 品味性能之道<十>:Oracle Hint
- C++中cout/cin对于空指针、字符指针的处理,及输入>>、 输出<<操作符的重载
- Android最佳性能实践——布局优化技巧之<include>、<merge>标签及仅在需要时才加载布局的:ViewStub
- 品味性能之道<二>:性能工程师可以具备的专业素养
- 品味性能之道<四>:管理重于技术
- C标准库学习之<ctype.h> ——字符处理
- 品味性能之道<十一>:JAVA中switch和if性能比较
- Post传值时间特殊字符处理比如 "<p></p>"当作参数传递到后台
- 品味性能之道<三>:方法论
- Android StrictMode 处理ANR 性能优化<14>
- 本内容中发现无效字符。处理资源 'file:///C:/Users/XDJ/Desktop/1111/press.xml' 时出错。第 5 行,位置: 11 <author>ƽ
- 【技巧篇】解决悬浮的<header>、<footer>遮挡内容的处理技巧
- 【技巧篇】解决悬浮的<header>、<footer>遮挡内容的处理技巧
- 使用<a>标签调用struts2的action、传递动态参数、以及参数中出现加号等特殊字符的处理方法
- 处理内容有&特殊字符thinkphp返回xml无法解析的问题<![CDATA[xxx]]>
- 常用头文件-字符处理-<cctype>
- 【技巧篇】解决悬浮的<header>、<footer>遮挡内容的处理技巧(转)
- 任何时候都适用的20个C++技巧 <9-11> 性能的提升
- 简单的C程序<二>:字符间空格处理