LoadRunner 性能测试脚本

1   概述

  脚本录制编写是性能测试的一个重要环节。在性能测试过程中,虚拟用户模拟真实用户使用被测系统,这个"模拟"的过程正是通过性能测试脚本来实现的。因此,编写一个准确无误的脚本对性能测试有至关重要的意义。完成性能测试脚本包括两个步骤:脚本录制和脚本编写,本文重点关注脚本编写。

  2   脚本录制

  2.1.录制方式

  HTTP协议脚本录制可选两种方式:基于HTML和基于URL.选择哪种录制方式的原则如下:基于浏览器的HTTP应用系统选择HTML,基于其他方式的HTTP应用系统选择URL.

  2.2.录制注意点

  取消录制期间自动关联功能;

  如果部分测试脚本出现问题,需要重新录制,可以只录制存在问题的片断脚本,方法是不选中录制启动对话框中的Record the application startup.

  3   脚本编写

  3.1.常用技术

  LoadRunner性能测试脚本编写常用的技术包括参数化,关联,逻辑控制和脚本模块化。

  3.1.1.参数化

  参数化就是将脚本中的常量转化为变量的过程。通过录制生成的脚本所有的数据都是常量,为了达到向服务器发送的数据多样化的目的,需要将一些数据常量转化为变量。

  3.1.2.关联

  关联就是查找动态数据,并把查询到的数据以参数的形式保存起来。在B/S或者C/S系统中,服务器返回给客户端的数据有些是动态改变的,例如客服系统的人工来话流水号和工作流系统的工单流水号。当打开工单生成页面后,工单流水号已经从服务器端获取到了,而在提交工单步骤,需要将该流水号返回给服务器。因此,在提交工单之前,在脚本中必须获得流水号。获得流水号的方法就是关联。

  使用关联功能动态保存的参数跟直接通过参数化生成的参数是一致的。唯一不同的是,通过参数化生成的参数在脚本中可以高亮显示。

  3.1.3.逻辑控制

  业务系统在实际应用中,业务操作步骤间往往存在逻辑。比如,客服3.0工作流系统,业务代表处理工单,如果待办区没有工单等待处理,则先从工单池中提取工单到待办区,然后进行处理,并且需要优先处理超时或即将超时的工单。在工单处理的性能测试脚本中,也必须遵从这种业务逻辑。

  LoadRunner性能测试脚本采用C语言,因此脚本逻辑控制同C语言一致,使用if,switch,while/for/do控制结构。

  3.1.4.脚本模块化

  脚本模块化的目的是:提高脚本可读性、可重用性和脚本生产效率。脚本模块化的本质是抽取函数,一些很通用的函数甚至可以封装为DLL.模块化性能测试脚本的思想跟自动化测试的ActionWord有相似之处。

  例如:客服3.0系统的登录功能,无论是工作流、知识库、公告便签还是培训考试,它们都使用相同的登录页面。我们可以把登录脚本抽取为一个函数csp_login(char *staffno,char * password),需要登录操作时,不需要录制和拷贝脚本,只要调用这个函数就可以了。

  注意:并不是所有的脚本代码块都需要做模块化处理,只有那些稳定不变、并且经常用到的代码块才需要做模块化处理。不做得不偿失的事。

  3.2.典型函数

  LoadRunner中,常用的函数有很多,这里只介绍编写性能测试脚本过程中那些必然用到的函数。本文重点关注这些典型函数的应用场合及注意点,至于函数详细使用说明请参见LoadRunner帮助文档。

  3.2.1.事务相关

  3.2.1.1. lr_start_transaction/lr_end_transaction

  功能:事务开始/结束标记。

  应用场合:需要统计某一段代码块执行所需要的时间,这两个函数需要成对使用。

  举例:工作流系统性能测试中有一个需求,300人在线,提交工单操作平均响应时间在3秒以内,则需要在提交工单请求步骤之前插入lr_start_transaction,提交工单请求步骤之后插入lr_end_transaction.

  注意点:这两个函数只是标记函数,用于标记事务开始/结束,因此可以嵌套使用,即事务中还可以包含子事务。

  3.2.1.2. lr_think_time

  功能:模拟思考时间,即等待时间。

  应用场合:在线用户测试,为了让每一个虚拟用户模拟一个真实用户的行为,即让一个虚拟用户对系统产生的压力跟真实用户相当,就必须使用这个函数。这是因为,用户在使用系统的过程中,从一个操作转换到另一个操作,是需要时间的,这个时间就是思考时间。

  举例:客服3.0工作流系统在线用户测试。对于工单查询操作,输入查询条件后提交查询,从输入查询条件至提交查询的时间间隔就是思考时间。因为LoadRunner无法模拟键盘输入的过程,它只能模拟键盘输入的等待时间,此时需要在提交查询的那个动作前插入lr_think_time函数。

  注意点:在录制脚本中,原子事务内不要包含lr_think_time函数,否则该思考时间将被统计到事务响应时间中,造成结果不准确。另外lr_think_time是否启作用,可通过runtime-seting进行设置。

  注:原子事务指那些不能再分割为更小事务的事务,它经常指一个单一的业务操作,通常表现为一个URL请求。

  3.2.1.3. lr_rendezvous

  功能:在Vuser脚本中设置集合点。

  应用场合:并发测试。

  举例:客服3.0培训考试系统,100人同时打开同一份试卷。则需要在打开试卷的语句前插入lr_rendezvous函数,并在场景中设置集合点策略。

  注意点:非并发测试,例如在测试系统的处理能力时,最好不要设置集合点,因为一旦设置了集合点,将导致一些VUser处于等待状态,在这等待过程中服务器将是空闲的,这将导致不能准确的测试出服务器的真实性能水平。集合点更多用于发现系统的并发问题。

  3.2.2.参数化/关联

  3.2.2.1.lr_save_string/lr_save_int

  功能:将某一字符串/整型保存为参数。

  应用场合:有些变量的值通过C语言生成,之后在测试脚本中要使用这些变量。

  举例:客服3.0业务配置台系统增加业务代表操作,业务代表的工号和姓名使用C语言函数生成。工号和姓名分别保存在staff_no和staff_name变量中,则在脚本中可以使用lr_save_int(staff_no,"staffno"),lr_save_string(staff_name, "stafffname")将工号和姓名参数化。

  注意点:无。

  3.2.2.2.web_reg_save_param

  功能:在服务器返回的文本中查找一个或者多个字符串,并将搜索到的字符串值保存在参数中。

  应用场合:在B/S或者C/S系统中,服务器返回给客户端的数据有些是动态改变的,在脚本的下一个步骤中,需要使用该动态数据。这时,就需要使用关联获得该动态数据。

  举例:客服3.0工作流系统,工单办理每次都从待办区中打开第一条工单,为打开第一条工单,需要获取第一条工单的完整URL(包括URL中的parameter及其值),而每一次进入待办区,第一条工单有可能是不一样的。为获取第一条工单的URL,将打开工单的URL做关联。已知打开待办区操作获得的HTML有如下片断:

  <a #"onclick="javascript:openseviceforprocess(‘/iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200‘,‘false‘);">

  可在打开待办区的操作前插入如下语句:

  web_reg_save_param("tt_url", "LB=javascript:openseviceforprocess(‘","RB=‘,‘false‘)", "Ord=1","IgnoreRedirections=Yes", "Search=Body","RelFrameId=1", LAST );

  运行脚本后,tt_url的值为:

  /iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200

  这个URL就是打开第一条工单的URL,有了URL,便可打开工单。

  注意点:

  (1)LoadRunner工具只能识别文本,在HTTP协议中只能识别HTML文档,因此关联的依据是HTML源码,而不是经过浏览器解析后的可视化文本。这一点很重要。

  (2)关联还能将多个匹配的参数保存在数组中,方法是指定ORD的属性值为ALL,之后通过"{参数名_1}", "{参数名_2}", "{参数名_3}"格式可获得数组元素的值。

  (3)该函数有一个属性NOTFOUND,默认值为ERROR,也就是说,如果找不到要查找的数据,将报出错误,在必要的时候,例如脚本逻辑控制需要,可以将NOTFOUND的属性值设为WARNING,这样LoadRunner将不产生错误。

  3.2.2.3.lr_save_searched_string

  功能:在某一个字符缓冲区中搜索指定的字符串,并将搜到的字符串保存在参数中。

  应用场合:可配合LoadRunner的关联功能,灵活获取服务器端返回的数据。

  举例:客服3.0工作流系统,工单处理每次都从待办区中打开第一条工单,打开工单的URL已经通过关联保存在tt_url参数中,在工单处理提交时,需要使用serviceNo,serviceID,nodeID,dealID,tt_url的值如下:

  /iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200

  可使用以下函数保存serviceNo,serviceID,nodeID,dealID的值。

  //保存serialNo,serviceID,nodeID,dealID参数

  int getTTData(){

  int i = 0;int j=0;

  char *tt_url = lr_eval_string("{tt_url}");

  int len= strlen(tt_url);

  while(tt_url[i]!=‘=‘){i++;} while(tt_url[j]!=‘&‘){j++;}

  lr_save_searched_string(tt_url,len,0,"serialNo",1,j-i-1,"serialNo");

  i++;j++;while(tt_url[i]!=‘=‘){i++;} while(tt_url[j]!=‘&‘){j++;}

  lr_save_searched_string(tt_url,len,0,"serviceID",1,j-i-1,"serviceID");

  i++;j++;while(tt_url[i]!=‘=‘){i++;}  while(tt_url[j]!=‘&‘){j++;}

  lr_save_searched_string(tt_url,len,0,"nodeID",1,j-i-1,"nodeID");

  i++;j++; while(tt_url[i]!=‘=‘){i++;}  while(tt_url[j]!=‘&‘){j++;}

  lr_save_searched_string(tt_url,len,0,"dealID",1,j-i-1,"dealID");

  return 0;

  }

  注意点:无

  3.2.2.4.lr_save_datetime

  功能:将时间保存为参数。

  应用场合:应用系统需要把时间数据提交给服务器端。

  举例:客服3.0工作流系统活动工单查询,默认查询从当天开始的最近三天工单。 则查询的开始时间和结束时间可用lr_save_datetime获取。

  lr_save_datetime("%y-%m-%d00:00", DATE_NOW-2*ONE_DAY, "queryBeginTime");

  lr_save_datetime("%y-%m-%d23:59", DATE_NOW, "queryEndTime");

  注意点:无

  3.2.2.5. web_save_timestamp_param

  功能:将当前时间戳保存为参数。

  应用场合:应用系统需要把时间戳提交给服务器端。

  举例:多媒体坐席客户端,在向MClient提交信息时,需要附带客户端的时间戳,则可以使用该函数获取当前时间戳。

  注意点:与lr_save_datetime不同的是,本函数保存的是时间戳,而lr_save_datetime保存的是日期和时间。

  3.2.2.6.lr_eval_string

  功能:将某一字符串中包含的所有参数替换为真实值,并返回替换后的字符串。

  应用场合:欲查看某一参数的值,可使用该函数。

  举例:客服3.0工作流系统,生成工单时打开工单页面准备工单提交,提交之前想查看已通过关联保存的serialNo参数的值。方法如下:

  lr_output_message(lr_eval_string("TheserialNo is {serialNo}"));

  注意点:如果不存在该参数,将把"{参数名}"当作普通字符串输出。如本例,如果不存在serialNo参数,则输出:The serialNo is {serialNo}.

  3.2.3.验证点

  3.2.3.1.web_reg_find

  功能:在HTML文档中查找指定的字符串。

  应用场合:该函数是检查点函数,在脚本中需要插入检查点的地方使用。

  举例:客服3.0工作流系统,提交工单生成后,需要验证工单是否提交成功。则可根据页面提示"工单生成成功"进行验证。在提交生成工单步骤前插入:

  web_reg_find("Text=工单生成成功",LAST);

  注意点:该函数是注册型参数,需要在请求服务器数据步骤之前插入该函数。与该函数功能类似的函数是web_find,但是web_find只对HTML方式的脚本起作用,对URL方式脚本则不起作用,而且web_find函数效率低下,已被废弃。

  3.2.3.2. web_image_check

  功能:判断某一个图片是否存在HTML页面中。

  应用场合:同web_reg_find函数一样,该函数也是检查点函数,在脚本中需要插入检查点的地方使用。

  举例:客服3.0培训考试系统并发测试,50个人同时打开试卷,为了验证打开试卷成功,根据试卷中的图片public/images/onexam.gif进行验证:

  web_image_check("web_image_check","Src=public/images/onexam.gif",LAST);

  注意点:要使该函数生效,需要在runtime-seting中将打开。与web_reg_find不一样的是,该函数不是注册型函数,因此需要在请求返回步骤之后插入该函数。上文提过,LoadRunner只能识别文本,因此web_image_check函数其本质仍然是文本验证,完全可以用web_reg_find替代,而且强烈推荐使用web_reg_find作为检查点函数。

  3.2.4.日志输出

  3.2.4.1. lr_output_message

  功能:将VUser的消息打印到日志文件和输出窗口中,打印的消息带有脚本行信息。

  应用场合:方便查看运行信息,辅助问题定位。

  举例:客服3.0系统,登录工号已经参数化,调试脚本时将当前的登录工号输出到Replay Log窗口中。代码如下:

  lr_output_message("Thestaffno is %s",lr_eval_string("{staffno}"));

  注意点:与该函数具有类似功能的还有:lr_debug_message,lr_log_message lr_message,lr_error_message它们之间的不同之处这里不作详细介绍,请参见LoadRunner帮助文档。

  3.2.4.2. lr_vuser_status_message

  功能:将VUser的消息输出到场景运行的VUser状态窗口。

  应用场合:将一些关键信息输出到VUser运行状态窗口,方便场景执行时查看。

  举例:在场景运行过程中,出现了错误。根据错误窗口提示,该错误属于VUser ID为2的虚拟用户,为了方便将系统登录用户名与VUser ID对应起来,以方便问题定位。可以使用以下代码:

  lr_vuser_status_message("Thelogin username is %s", lr_eval_string("{username}"));

  场景执行时,可方便查看到VUserID与登录用户名的对应关系,如下图:

  注意点:无

  3.2.5.其它实用函数

  3.2.5.1. lr_get_vuser_ip

  功能:获得VUser的IP地址。

  应用场合:在使用IP欺骗时,为了验证IP欺骗是否成功,可以使用该函数。

  举例:在场景运行过程中,将每一个VUser的IP在VUser运行状态窗口中显示出来。

  char *ip;

  ip = lr_get_vuser_ip();

  if (ip)

  {

  lr_vuser_status_message("The IP addressis %s", ip);

  }

  注意点:为了使IP欺骗成功,使用IP欺骗向导设置好IP后,还要将打开才可。

  3.2.5.2. lr_load_dll

  功能:加载外部DLL.

  应用场合:脚本需要使用外部DLL时,使用该函数加载DLL.

  举例:函数getDateTime(char * time,int seconds,char * resultTime)已封装在timeutil.dll中,getDateTime的功能是根据传入的日期字符串time(如2008-09-24 16:56:24),秒偏移量seconds,计算返回结果日期字符串resultTime,代码如下:

  int hours =atoi(lr_eval_string("hours"));

  char acceptEndTime[20];

  lr_load_dll("/timeutil.dll");

  getDateTime(lr_eval_string("{acceptBeginTime}"),3600*hours,acceptEndTime);

  注意点:该函数为LoadRunner提供了调用外部接口的能力。

  3.3.封装,构建可重用脚本

  3.3.1.简单函数封装

  LoadRunner使用C语言作为脚本,因此只要是合法的C代码都可以在LoadRunner中运行。为了提高脚本可读性和脚本生产效率,有必要将性能测试脚本模块化。

  客服3.0工作流系统,查询工单池是一个很常见的操作。我们可以把查询工单池操作封装为一个queryTTPool函数,函数体如下,在脚本中,将所有的查询工单池操作替换为queryTTPool函数调用,提高了脚本的可读性:

  //查询工单池

  int queryTTPool(char* nodeType){

  lr_save_string(nodeType,"nodeType");

  lr_save_datetime("%Y-%m-%d 00:00",DATE_NOW-2*ONE_DAY, "acceptBeginTime");

  lr_save_datetime("%Y-%m-%d 23:59", DATE_NOW,"acceptEndTime");

  lr_start_transaction("WF_查询工单池工单");

  web_submit_data("IWFController",

  "Action=wf_sysurl}/IWFController",

  "Method=POST",

  "RecContentType=text/html",

  "//f_sysurl}/iwflow/common/UnitQueryDealForm.jsp?pageNo=1",            "Snapshot=t32.inf",

  "Mode=HTML",

  ITEMDATA,

  "Name=ACTIONID","Value=UniteQueryDealAction", ENDITEM,

  "Name=pageNo", "Value=1", ENDITEM,

  "Name=sortType", "Value=", ENDITEM,

  "Name=sortField", "Value=", ENDITEM,

  "Name=reSortFlag", "Value=", ENDITEM,

  "Name=acceptPhone", "Value=", ENDITEM,

  "Name=serialNo", "Value=", ENDITEM,

  "Name=serialFlag", "Value=0", ENDITEM,

  "Name=serviceName", "Value=", ENDITEM,

  "Name=serviceID", "Value=", ENDITEM,

  "Name=acceptBeginTime","Value={acceptBeginTime}", ENDITEM,

  "Name= acceptEndTime ", "Value={acceptEndTime}",ENDITEM,

  "Name=urgentID", "Value=", ENDITEM,

  EXTRARES,

  "Url=/iwflow/image/kms-1_23.gif", ENDITEM,

  "Url=/iwflow/buttons/obtainProcess-2.gif", ENDITEM,

  LAST);

  lr_end_transaction("WF_查询工单池工单",LR_AUTO);

  }

  3.3.2.DLL封装

  使用DLL有很多好处。高度重用的函数制作成DLL,方便脚本调用。将与IVR交互的消息函数封装成DLL后,便可利用LoadRunner测试IVR性能。制作DLL可以选择VC或者MinGW Developer Studio等工具,至于DLL的制作细节,本文不作介绍,请参见相关指导书。

  4   脚本调试

  LoadRunner的VUser Generator本身的调试功能比较弱,只能设置断点,无法单步跟踪。当脚本出现问题时,可以使用lr_debug_message,lr_output_message,lr_eval_string等函数协助定位。

  脚本错误大部分原因都是向服务器发送的数据不对,因此还可以利用HttpAnalyzer工具进行HTTP协议跟踪,通过比较LoadRunner发送的数据和浏览器发送的数据,便能很快定位出问题根源。

http://www.educity.cn/se/525901.html

时间: 2024-10-22 13:47:49

LoadRunner 性能测试脚本的相关文章

品味性能之道&lt;九&gt;:利用Loadrunner编写socket性能测试脚本简述

一.概述 Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力.其中就有此次要讨论的socket套接字操作. 二.socket概述 socket是操作系统中I/O系统的网络延伸部分,它扩展了操作系统的基本I/O到网络通信,使进程和机器之间的通信成为可能.如果想完全地理解socket在Loadrunner中如何工作的,熟悉一些关于它的历史会很有帮助. 当前常用的socket,最早起源于BSD UNIX类的操作系统.在UNIX系统上,比如BSD,把对网络的支持加入操作系统,以一

LoadRunner性能测试样例分析

LR性能测试结果样例分析 测试结果分析 LoadRunner性能测试结果分析是个复杂的过程,通常可以从结果摘要.并发数.平均事务响应时间.每秒点击数.业务成功率.系统资源.网页细分图.Web服务器资源.数据库服务器资源等几个方面分析,如图1- 1所示.性能测试结果分析的一个重要的原则是以性能测试的需求指标为导向.我们回顾一下本次性能测试的目的,正如 所列的指标,本次测试的要求是验证在30分钟内完成2000次用户登录系统,然后进行考勤业务,最后退出,在业务操作过程中页面的响应时间不超过3秒,并且服

LoadRunner 7 脚本开发和常用函数

开发性能测试脚本原则.简单 正确 高效 在lr中,脚本运行是解释执行的.所以在运行时,需要先编译. 局部变量和全局变量 1.在init.action.end中定义的变量就是局部变量 2.在globals.h中定义的变量是全局变量 3.什么时候定义全局变量 ? 整个过程中固定不变的,例如URL地址.KEY.其他 int a=100;//这个a是文件级别的.除了globals.h 都可访问 Action() { int a =10; int b =6; //在lr要使用变量,必须放在最上面. pri

LoadRunner同一个脚本运行两次结果相差很大的原因

如果同一个脚本运行两次结果相差特别大.后一次的响应时间比前一次的响应时间慢了特别多,而期间开发又未修改过程序排查问题: 1.查看下linux内存利用情况 free -m 是查看内存情况 (通常可用内存占10%是可接受范围内) 如果可用内存很小的话 :一种可能是程序有问题 :另一种可能是磁盘空间不足了 当磁盘空间不足就会去写内存 2.可以先看下第二种情况成立否 : 命令 tf -m 查看磁盘空间情况结果看到磁盘空间为0了 3.查看哪个进程占用了这么多 ,最好通过log日志进行分析.在运行性能测试脚

LoadRunner性能测试基础知识问答

Q1:什么是负载测试?什么是性能测试? A1:负载测试是通过逐步增加系统负载,测试系统性能的变化,并最终确定在满足性能指标的情况下,系统所能承受的最大负载量的测试,例如,访问一个页面的响应时间规定不超过1秒,负载测试就是测试在响应时间为1秒时,系统所能承受的最大并发访问用户的数量. 性能测试:指在一定的约束条件下(指定的软件.硬件.网络环境等),确定系统所能承受的最大负载压力. Q2.性能测试包含了哪些测试(至少举出3种) A2:性能测试包含负载测试.压力测试.大数据量测试.疲劳强度测试等. Q

性能测试脚本开发(LR.NET控件)

版权声明:本文为兄弟连IT教育原创文章,未经博主允许不得转载. 性能测试过程中,最耗费经历的就是编写性能测试脚本的过程,在大部分的测试工具中都是采用录制的方式,通过录制产生脚本,然后根据需要进行修改,以及参数化.有些时候为了能够完成某一个功能的脚本,需要将录制下来的脚本进行"大手术",给编写脚本的人带来了很大的麻烦. 这篇文章向大家介绍了一种新的方式产生脚本,对于 ISV (独立软件开发商)和一些有 代码的测试厂商带来了很大的方便,特别是一些 C/S 结构的产品采用此种方式更加有效.文

LoadRunner性能测试巧匠训练营

<LoadRunner性能测试巧匠训练营>基本信息作者: 赵强 邹伟伟 任健勇 丛书名: 实战出版社:机械工业出版社ISBN:9787111487005上架时间:2015-1-7出版日期:2015 年1月开本:16开版次:1-1   编辑推荐软件性能测试领域具有突破性创新意义的重要著作,三位资深软件测试专家多年一线工作经验结晶,业内多位测试专家联袂推荐.基于LoadRunner.Apache ab和JMeter等性能测试工具,以真实项目为依托,全面深入讲解了软件性能测试.安全测试.性能调优的流

小强新书《LoadRunner性能测试巧匠训练营》正式预售

china pub预售地址(可以下单支付):http://product.china-pub.com/3770901 京东预售地址:www.jd.com进入后搜索 loadrunner性能测试巧匠训练营 即可  本书特色       从技术层面来讲,性能测试的复杂性是不言而喻的,目前性能测试一直处于一个只能发现问题而无法定位并给出解决方案的状态,本书正是为了改变现状而诞生的.       从内容层面来讲,目前很少有此类以全程项目实战和调优为主的性能测试类书籍,实战类型书籍向来是比较受欢迎的书籍,

LR实现http协议性能测试脚本

1.  GET方式的HTTP请求性能测试脚本 Action() { web_set_max_html_param_len("10000"); web_reg_save_param("retCode", "LB=retCode\":\"", "RB=\"", "NotFound=WARNING", LAST); lr_start_transaction("test&qu