多语言展示
当前在线:1489今日阅读:27今日分享:41

性能测试:[1]LoadRunner规范

性能测试LoadRunner规范
工具/原料

loadrunner

方法/步骤
1

1   文档说明1.1       背景及目的编写这篇文档的目的用于规范我们测试部LoadRunner脚本编码风格,使大家能够养成一个好的编程习惯,使得在日常工作中编写的代码可读性更强,“低级错误”更少,更易于维护以及他人学习,并且希望通过这些点点滴滴的努力从而提高我们的产品质量,降低风险。该规范的和C语言相关的部分,基本完全借鉴了林锐博士的高质量C++编程这本书里面的内容。因此建议大家学习一下这本书,是开发和测试都需要学习的一本好书。该规范后面增加了LoadRunner脚本中常用的例子,在实际工作中,基本常用的函数以及写法都已经包含在里面。

2

1.2       注意事项

3

2         脚本编写2.1       命名规则l  【规则2-1-2】命名规则尽量要遵循“言简意赅、望文生义”的八字方针。l  【规则2-1-1】变量名应当直观且可以拼读,可望文知意,不必进行“解码”。变量名最好采用英文单词或其组合,便于记忆和阅读,切忌使用汉语拼音来命名。程序中的英文单词一般不会太复杂,用词应当准确。l  【规则2-1-2】程序中不要出现仅靠大小写区分的相似的变量名。例如:int  x,  X;          // 变量x 与 X 容易混淆l  【规则2-1-3】程序中不要出现完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。l  【规则2-1-4】变量的名字应当使用“名词”或者“形容词+名词”。另外,对于大家常用的、习惯成俗的形容词,可以采用缩写。例如:uint32     value;     //名词uint32     n_val;     //形容词+名词,n是new的缩写l  【规则2-1-5】尽量避免名字中出现数字编号,如val1,val2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。l  【规则2-1-6】全局变量加前缀g_(表示global)修饰,单词之间采用下划线分割。例如:Char   *g_msg_pool;l  【规则2-1-7】函数名尽量采用“模块名+动词+名词”(动宾词组)或者“模块名+名词+动词”的方式命名,尽量做到根据函数名能大概明确函数所完成的功能。例如:bool  comm_hash_create(…)    //模块+名词+动词l  【规则2-1-8】宏常量名必须全部采用大写的字母,单词之间使用下划线分隔。例如:#define DEF_BUF_LEN 150     //宏常量

4

2.2       格式化代码l  【规则2-2-1】脚本应采用缩进风格编写,每层缩进使用一个制表位(TAB),类定义、方法都应顶格书写;l  【规则2-2-1】左花括号要另起一行,不能跟在上一行的行末;l  【规则2-2-2】一个变量定义占一行,一个语句占一行;l  【规则2-2-3】对独立的程序块之间、变量说明之后必须加空行;l  【规则2-2-4】对于较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读;l  【规则2-2-5】循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分;l  【规则2-2-6】在结构成员赋值等情况,等号对齐,最少留一个空格;l  【规则2-2-7】若函数或过程中的参数较长,则要进行适当的划分。l  【规则2-2-8】形参的排序风格:最常使用的参数放在第一位;输入参数列表应放在输出参数列表的左边;将通用的参数放在特殊的参数的左边

5

2.3       Vuserl  【规则2-3-1】脚本越小越好。就像写code一样,不要太长,这样易于维护也易懂。尽量做到一个功能写一个脚本。如果那些功能是连续有序的,必须先做上一个,下一个动作才能进行,就只能放在一起了。l  【规则2-3-2】对于在脚本中常用的函数,需要进行抽取,放到专门的.h中进行定义实现。l  【规则2-3-3】能用到高级协议的,不要使用底层协议。l  【规则2-3-4】通常将登陆业务放到init里面;业务放到action里面;退出放到end里面l  【规则2-3-5】在脚本中,必须自己定义事务,不允许使用默认事务。l  【规则2-3-6】在脚本中,如果有登陆和退出操做,也必须声明事务。l  【规则2-3-7】脚本名称,事务名称、参数名称要做到见名知义。l  【规则2-3-8】对于socket需要明确是长连接还是段连接l  【规则2-3-9】socket编程必须关闭系统的bufferl  【规则2-3-10】对于socket,如果能每次返回的长度确定,那么一定使用data.ws文件中指定特定长度的字符。否则才设置接受超时时间。l  【规则2-3-11】对于操做二进制,不使用字符串操做函数,需要使用内存函数。如memcpy代替strcpy

6

3         场景执行l  【规则3-1】在执行前,建议将所有的脚本放到本地的英文目录下,建议d:\scriptl  【规则3-2】运行时需要关闭系统的日志。l  【规则3-3】运行时根据实际情况设置场景的思考时间l  【规则3-4】运行时去掉每个action作为一个transaction的统计l  【规则3-5】对于HTTP协议测试,正确合理设置缓存策略l  【规则3-6】在执行时每次将执行的结果放到本地的英文目录下,建议d:\resultl  【规则3-7】执行单交易测试最少需要20分钟;执行混合场景测试最少需要30分钟l  【规则3-8】对于测试使用负载均衡策略的系统,需要考虑负载均衡的方案,以便决定是否采用IP欺骗。l  【规则3-9】在整个测试执行过程中,使用excel记录整个执行过程,尤其是在执行过程中新设计的场景。

7

序号内容/场景负责人开始时间结束时间测试结果记录发现问题解决办法备注

8

4         一些经验1、  能用简单方法实现的,别用复杂的实现。尤其是获取loadrunner测试数据模块。2、  关联函数使用web_reg_save_param(“attributeChannelsXml”,“LB=”, “RB=”,LAST);sprintf (tmp, “%s”,lr_eval_string(“{attributeChannelsXml}”));lr_save_string(tmp, “attributeChannelsXml”);3、  HTTP协议检查点a)、检查HTTP应答消息的BODY部分web_reg_find(“Text=Welcome”,  LAST);b)、检查HTTP应答消息的Header部分web_save_header(RESPONSE,”response”);web_url(“John_Willoughby”,“URL=http://Combe_Magna.com/portal/index.asp”,“TargetFrame=_TOP”,LAST);if( strstr(lr_eval_string(“{response}”), “OK”) != NULL )  {//PASS}else{//FAIL}4、  使用hex_print函数,进行二进制报文调试。char* hex_print(void *hexbuf, int bufsize){int i;unsigned char *buf_str;unsigned char *x; unsigned char tmp[1]; buf_str = (unsigned char *)malloc(bufsize * 4 + 1);x = buf_str;memset(x, 0, bufsize*4+1);for(i=0;i

9

5、  格式化输出函数sprintf (tmp, “%s”,lr_eval_string(“{attributeChannelsXml}”));sprintf (buffer, “{m_Channel_%d}”,i_loop+1);sprintf(runlog.sendTime, “%s%c“, ctime(&currTime), ”);sprintf(version, “%02x“,((unsigned char *)recieve_buffer)[2+total_loop]);6、  XML的操做i_address_channel = lr_xml_get_values(“XML={attributeAddressesXml}”,“ValueParam=m_address_channel”,“Query=/addresses/item/channel”,“SelectAll=yes”,LAST); i_address_address = lr_xml_get_values(“XML={attributeAddressesXml}”,“ValueParam=m_address_address”,“Query=/addresses/item/address”,“SelectAll=yes”,LAST);for (i_loop = 0; i_loop < i_address_channel; i_loop++){sprintf(buffer,”{m_address_channel_%d}

{m_address_address_%d}
”,i_loop+1,i_loop+1);strcat(tmp,buffer);}7、  善于使用lr_save_string和lr_eval_string函数lr_save_string(ssic, “SSIC”);lr_eval_string(“SSIC”)8、  内存函数使用buffer = (char *)malloc(content_len * sizeof(char));memset(buffer, 0, content_len);loop = loop + 2;sprintf(x, “%c”, 0xA0);memcpy(buffer + loop, x, 1);loop = loop + 4;sprintf(x, “%c”, 0×05);memcpy(buffer + loop, x, 1);loop = loop + 3;free(buffer)

10

9、  字符串函数使用if (strcmp(lr_eval_string(“{currentWorkMode}”),”3″)!=0) {lr_set_transaction_status(LR_FAIL);lr_end_transaction(“登陆”, LR_AUTO);return 1;} strcat(tmp,buffer); if( strstr(runlog.recvPacket, runlog.Hrst) != NULL ){runlog.Frst = “Pass”;result = TRUE;}else{runlog.Frst = “Fail”;result = FALSE;}(char* ) malloc(sizeof(char)* (strlen(tmpStr)+strlen(ipport) + 1) );10、              文件操做sprintf(filepath, “..\\runlog\\result.txt%c”,”); if ( (fp = fopen(filepath, “at+b”)) == NULL){lr_message(“open logfile failed!\n”);return -1;}sprintf(strbuf,”<%s> %s  %s%c”, strtime, scriptName, result, ”);fprintf(fp, “%s\r\n”, strbuf);free(strbuf);fclose(fp);11、              函数参数传递a)、函数传入参数返回内容char *checkBuf;调用函数:socketSendRecv(socketName, “buf_Add_Buddy”, 1, &checkBuf,1)函数实现:/*****************************************************************函数名称:         socketSendRecv函数功能:         通过一个socket连接 发送并接收数据输入参数:输出参数:状态:编码完成*******************************************************************/BOOL socketSendRecv(char* src_socket, char* buffer, int length, char** pRebuffer,int flag_parse){char *send_buffer_xml;int num_input;char *send_buffer_mcp;int send_len;char *recieve_buffer_mcp;int recsize2;char *recieve_buffer_xml;int recvieve_len;BOOL ret;……paserMcptoXml((unsigned char *)recieve_buffer_mcp,&recieve_buffer_xml,&recvieve_len,recsize2);*pRebuffer = (char* ) malloc(sizeof(char)*strlen(recieve_buffer_xml) + 1);memcpy(*pRebuffer, recieve_buffer_xml, strlen(recieve_buffer_xml));*(*pRebuffer+strlen(recieve_buffer_xml)) = ”;free(recieve_buffer_xml);free(recieve_buffer_mcp);return ret;}b)、函数返回值,返回字符串调用函数:char *str = NULL;str = GetMemory3(100);函数实现:char *GetMemory3(int num){char *p = (char *)malloc(sizeof(char) * num);return p;}12、              网络函数操做TCPlrs_create_socket(“socket”, “TCP”, “LocalHost=0″, “RemoteHost={remoteHost}”, LrsLastArg);lrs_set_send_buffer(“socket”, buffer, content_len);lrs_length_send(“socket”, “buf0″, 0, LrsLastArg); lrs_receive(“socket”, “buf1″, LrsLastArg);lrs_get_last_received_buffer(“socket”, &recbuf, &num_input);UDPlrs_create_socket(“socket”,”UDP”,”LocalHost=0″,”RemoteHost={remoteHost}”,  LrsLastArg);lrs_set_send_buffer(“socket”, buffer, 52);lrs_send(“socket”, “buf0″, LrsLastArg); lrs_receive(“socket”, “buf1″, LrsLastArg);lrs_get_last_received_buffer(“socket”, &recbuf, &num_input); 13、              自定义封装函数char* substr(char* srcstr, char* lstr, char* rstr); //对字符串进行截取int searchstr(char* srcstr, char* lstr, char* rstr, char **pSubstr); //在字符串内所搜指定的字符串int searchstrN(char* srcstr, char* lstr, int len, char **pSubstr);  //在字符串内所搜指定的字符串int splitStringByChar(char *bfword,char sep,char  *bhword,char *source);char * Trim(char  *source); //删除字符串的开始和结束部分的空格BOOL searchstrM(char* srcstr, char* lstr, char* rstr, PSTRLIST* pList); //根据特定字符对字符串进行分割

注意事项

loadrunner规范

推荐信息