品味性能之道:Loadrunner关联技巧与字符处理

时间:2022-09-14 12:30:04

一、概述
       Loadrunner作为HP出品的性能测试工具,拥有太多奇妙魔法甜点供予性能测试人员享用,其中吃起来比较有嚼劲的那就是关联了。当然在关联之后我们还需要一些简单的字符处理,用以生成我们所需要的切糕、煎饼果子等。

       ps:在此我只会分享手动关联技巧。

 
二、为什么要关联
       通常而言我们的网络应用软件都需要输入账户密码登陆,在用户验证通过登陆以后,服务器如何确认谁是谁呢?
       此时一般而言就是SESSIONID了,如下图所示:
品味性能之道:Loadrunner关联技巧与字符处理
 
         

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及其强大的插件,断点排查

 
三、如何建立关联
       建立关联我总结了以下几步:

品味性能之道:Loadrunner关联技巧与字符处理 

品味性能之道:Loadrunner关联技巧与字符处理
      (1)、明确关联字段
      录制结束以后,进入Tree试图,查看Response Body,如下图所示:

品味性能之道:Loadrunner关联技巧与字符处理 

品味性能之道:Loadrunner关联技巧与字符处理

      <r id="value":这里的“value”作为服务器确认字段唯一操作ID,它是我们需要关联的字段。

 
      在确定操作ID之后,我们还需要确定哪个值是数据库表里面的主键或者复合主键字段,如下图所示:

品味性能之道:Loadrunner关联技巧与字符处理 

品味性能之道:Loadrunner关联技巧与字符处理
      在确定我们的主键为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.
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 );
string The string that is searched.
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 ); 
dest The destination string to which n characters are copied.
source The source string from which n characters are copied.
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 );
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  );
to_string The string to which  n charachters are concatenated.
from_string The string from whice  n charachters are concatenated.
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。