Loadrunner系统知识(非常好)

更新时间:2024-02-03 15:09:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

LoadRunner内部结构

1, 被测系统是由驱动进程mdrv.exe(多线程驱动的进程)和r3vuser.exe来产生压力的,其中r3vuser.exe仿真应用程序的客户端,如IE浏览器。它执行了三个主要的操作:

Kli> cpp (C 语言pre-processor)

1)cci (C语言编译器),建立ci文件,然后使用被测系统的协议相关的驱动来执行。

通过在Windows批处理脚本中启动Mdrv.exe来默默地启动运行。

Mdrv能自动停止加载Vuser,因为他们与Vuser和Windows负载生成器上的CPU使用监视器之间互相通信。

在Windows机器上,对于每一个基于Java的Vuser都有一个独立的JVM。 2, 虚拟用户通过在负载生成器客户端机器上使用agent(3900

magentproc.exe)作为服务或者进程来按照组(在指定的负载生成器上运行相同脚本的虚拟用户的集合)启动虚拟用户。

3, 每一个拥有代理的机器维护一个在.qtp文件中的执行日志。

4, 当日志被启用后,代理同样会在结果文件中为每一个虚拟用户(由虚拟

用户组分开)建立一系列日志文件。

5, 在执行过程中,这些文件可以通过在Controller机器上的view >

Show Output窗口中显示。

6, 在预先设置延时上,Controller上运行的Scheduler指导代理(通过

Windows 54345端口,或者Unix上的动态端口)去初始化场景会话.Controller(wlrun.exe)在请求中发送一份场景的拷贝.

7, 代理是由每一个负载生成器上的Remote Agent Dispatcher进程(以

前叫Remote Command Launcher(RCL))启动的.

8, 每一个根据场景(.lrs)定义文件中设置的代理来决定哪一个虚拟用户组

和脚本需要在主机上运行.

## 这就是说Controller可以从DOS的批处理文件(.batch)中启动. REM Start Controller:

SET M_ROOT=C:\\Program Files\\Mercury Interactive\\LoadRunner\\bin cd %M_ROOT%

wlrun.exe -TestPath D:\\Dev\\Dev1.lrs -port 8080 -Run -DontClose ? 包含的-Run 参数与手动的点”开始场景”自动运行是一样的. 这不是一个很好的方法,因为你可能需要决定从以前的运行中收集文件或者想改变输出文件夹.

? 这是假设系统环境变量PATH已经被更新了,包括LoadRunner的安装. 9, Controller通过使用 Windows 操作系统文件夹里的参数值来启动.因为

LoadRunner被设计成在一个机器上一次只能运行一个Controller实例,所以需要使用Windows文件夹.

## 为了在几个应用之间快速的切换, 在Controller工作之后保存

LoadRunner的ini文件, 然后使用记事本来制作一个批处理文件. 在执行

1

wlrun之前拷贝应用程序的指定版本的ini文件. 下面是一个应用程序文件拷贝的例子:

copy %WinDir%/wlrun7-XXX.ini %WinDir%/wlrun7.ini copy %WinDir%/wlrun7-XXX.dft %WinDir%/wlrun7.dft 需要修改一些默认值:

? 在wlrun7.ini文件的output区域,

MaxNumberOfOutputMessages=from 10000 to 100000, 这就限制了存储在数据库中的输出信息的数目.

? MaxOutputUIRowsToShow限制了在Controller的输出窗口中显示的信息/错误行总数.

? 在LoadRunner程序文件的 dat\\protocols 文件夹下的

QTWeb.lrp文件的[Vugen]部分, 添加一个MaxThreadPerProcess=5来限制由每个负载生成器mdrv.exe进程管理的线程数.

? 存储在wlrun5.ini 和wlrun7.dft文件中的DefaultScenarioDir, DefaultscrīptDir, DefaultResultDir,[Recent File List]几个数据的值会在每次Controller改变的时候更新。

10, 在Vu scrīpts中定义的每个虚拟用户进行的操作是用LoadRunner

的VuGen.exe生成的. 当这个程序启动后, 它在windows文件夹下存储了comparamui.INI文件来保存[LastTablesUsed]下面文件的历史,并且保存由Insert > New Parameter > Dates 菜单指定的[ParamDialogDates].

VuGen在Windows文件夹下存储和检索vugen.ini文件.当使用JAVA的时候,需要添加一些其他的调试选项: [DynaDlg] JavaLevel=3

当在VuGen 8.1中使用8.0的脚本, 往Vugen.ini中加入信息: [Editor]

OLDEDITOR = 1

VuGen在LR文件夹template/qtwebdefault.cfg里和脚本文件里打开. Vu scrīpts可以使用脚本外部的参数文件来获得的变量值进行编码. 更多关于VuGen的信息请看脚本编写的章节.

11. 运行过程中,执行结果存储到一个结果文件夹中.

我喜欢在场景执行中把结果设置成自动产生结果.这样,LoadRunner会在每次启动一个场景之后自动产生一个子增的结果名. 例如,结果名称Res1会自动增长到Res12或有时候是R es11-1.

错误被写到output.mdb微软的Access数据库中。

12. 在每一个结果文件夹中, 程序自动创建Log文件夹来包含每个组的日志文件. 运行之后,在Controller中查看日志文件,点 , .然后在组中点右键,选择 “Show Vuser Log”

13. 场景运行的时候, 监视器在本地维护每个主机的计数器.

14. 运行完成之后, \进程处理.eve和.lrr结果文件, 并且在结果文件夹下创建一个临时的.mdb数据库.

在处理大数据量的结果时, 为了防止错误发生,使用MSDE. ……

2

15.分析模块(8,320K analysisu.exe)使用mdb数据库中的数据来产生分析图表和报告.

16. 每一次场景运行后的结果文件results_name.lrr,也叫分析文档文件,由分析程序来读取并且显示百分位图表.

Loadrunner系列学习--Loadrunner架构(1)

一:Loadrunner结构概述

Loadrunner通过使用虚拟用户代替真实用户操作客户端软件来工作的,例如使用IE对IIS或者Apache Web服务器发送HTTP请求.

多个虚拟用户客户端的请求是有负载生成器(Load Generator)产生的,目的是对不同类型的被测服务器产生负载.

这些负载生成器代理(load generator agent )是由Mercury's的控制器(Controller)来控制启动或停止的.

控制器根据由编译的脚本引起的场景(Scenarios)和相关的运行时设置(Run-time Settings)来控制负载测试的运行.

这些脚本是由虚拟用户脚本生成器(Virtual user scrīpt Generator)也叫VUGen生成的.它是通过截获网络应用程序的客户端和服务器之间的网络通信包而产生的C语言脚本,这些脚本可以被虚拟用户执行.

对于Java客户端,VuGen通过客户端的JVM的钩子技术来捕获请求. 在运行时,每个机器的状态由控制器监控.

运行结束后,控制器把监视日志和右负载生成器产生的日志结合起来给分析器(Analysis)使用.分析器能够把这些日志生成结果报表和Microsoft Word格式的图表,水晶报表或HTML格式页.

每一个由分析器生成的HTML报表页包括一个到结果的超链接,这些结果文件可以用Microsoft Excel打开来进行其他的分析.

运行时产生的错误都被存储在一个数据库中,该数据库可以用Microsoft Access打开. 虚拟用户:

3

不象WINRUNNER那样只能模拟一个客户端用户,LOADRUNNER能够模拟成千上万的虚拟用户.

负载生成器由VnGen脚本控制.这些脚本是使用跟被测客户端一样的协议产生的非GUI的API函数.但是WINRUNNER是使用GUI用 户来模拟被测客户端的键盘输入,鼠标点击和其他用户接口的操作,而且只能运行一个GUI用户.而

LOADRUNNER终端服务管理器 (LoadRunner Terminal Services Manager)管理使用终端服务代理来管理远程机器并且能登陆到客户端终端服务的会话. 运行的时候,线程类型的虚拟用户共享一个公用的内存池.所以线程方式可以使每个负载生成器支持更多的虚拟用户.

所有负载生成器上的虚拟用户的状态是从\开始的,然后在运行完脚本的init部分后变为\虚拟用户的\有通过或者失败的结束状态.当负载生成器负载过重时虚拟用户自动的\

监控标准的Web(HTTP)服务器(Apache, IIS, and Netscape)不需要额外的license.

为了能够监控使用SOAP和XML的Web Services,需要一个独立的 license,并且虚拟用户需要Web Services插件.该插件被Feature Pack(FP1)安装.

产品版本:略 应用程序组件需求

V8.0 Img KB File Size n/a 应用程序 - 程序进程名称 V9 LRLauncherApp.exe 15,840 16,288 Virtual User GeneratorVuGen.exe Controller with On-Line Monitors wlrun.exe 23,980 12,436 2,334,769 61,312 13,076 5,681,215 3,336 3,236 65,536 Load Generator Agent magentproc.exe magentservice.exe 3,496 mdrv.exe Analysis Tuning Console Analysisui.exe protune.exe - 64,460 13,132 6,058,496 - 3,403,833 4

控制台程序:

perl5.8.0.exe Interpreter regtlb.exe sed.exe wdiff.exe 20,535 registers the batch automation type library 30,720 GNU sed (gsed) version 2.05 Compares text files 55,296 197,632 使用WINDOWS远程桌面连接

为了使WINDOWS远程桌面连接会话在测试时不会超时,每个机器的终端服务应该如下配置:

1.开始-->程序(或者控制面板),管理工具下选择终端服务配置. 2.打开树型的连接文件夹 3.右击RDP-Tcp,选择属性. 4,点会话标签页.

5,确保选中\

6.设置空闲会话限制为最大2天来代替默认的2个小时. 7,点应用. 8.OK

注意:确保上面的做法没有影响到公司的安全策略.

注意:终端用户只能允许两个活动的连接.断开会话的时候使用开始-->退出,而不要点远程桌面的\关闭. LR的安装和配置:略

应用程序文件的位置:(省略部分介绍)

可以使用环境变量来快速获得LR的安装路径,如环境变量为\你可以使用 cd %lr81%

WINDOWS文件夹下的文件:

5

1.路径存储在wlrun.ini文件中的[ProductEnv]下作为M_ROOT.该文件在C:\\WINNT (或 C:\\Windows)

2.C:\\WINNT (或 C:\\Windows)下同样存有安装时的Maintenance Number (MPN),存在mercury.ini 文件中. 其他省略.

好了,今天先翻译到这里了,该吃中午饭了,哈哈,下期会翻译LOADRUNNER的内部结构.

Loadrunner学习---脚本编写(1)

VuGen脚本文件的开发过程

1。定义测试项目的目标,环境,脚本,测试数据,硬件等。脚本应该符合编码规范或编码习惯。

2。创建一个版本文件夹来保存被测应用程序相关的各种不同资源,例如截获的.png/.gif图形文件,录制过程保存的html文件,录制中的所有html源文件和VuGen的录制日志。

3。列出(在表里)每一个手动操作业务过程需要的实际步骤 1)截取每一个屏幕图像(screen image )。

2)为每一个屏幕(screen)分配一个唯一的事务名称。

3)为处理的每一个步骤使用的技术组件(URL或者方法和函数)做注释。 4。创建一个版本文件夹。

注:我不喜欢使用默认位置,我喜欢把所有脚本相关的文件放到一个相同的文件夹中。不幸的是,这意味着如果我在不同的测试间互相交换录制,那我每次都得记住修改默认的设置。

注:当录制一个新的脚本时,我喜欢选择多协议而不是单个协议。。。 5。根据你的业务处理列表上指定的用户使用步骤和screen的顺序来使用VuGen录制程序,产生一系列脚本代码。在“开始录制”对话框中 * 使用COM/DCOM 协议时,选择“Win32应用程序“

6

* 使用Web(HTTP/HTML)时,选择“Internet Application“ 6。根据改进脚本方法和脚本语言规则来修改脚本。 改进脚本的方法:

1)为每一个GUI的screen添加事务语句来获得事务时间。 2)添加显示数据来帮助调试。

3)添加验证点来验证是否期望的文本或者图片在每个脚本执行后显示。 4)通过插入新参数和动态获得整个文件的方式对硬编码的URL,用户id,用户密码和其他的变量数据进行参数化。这样脚本中的参数就可以被动态的替换,以此来模拟运行时不同数据的使用。

5)添加重试逻辑(retry logic)来处理不可见的错误。 6)添加随机函数发生器变化脚本来模拟真实的负载。

7)添加if/else逻辑来检查结果,或者来进行合适的操作,或者来在合适的时候退出脚本。

8)在一个screen中添加语句来捕获需要在其他命令中使用的数据。当使用Microsoft .NET的web form技术的时候,需要避免习惯性的“脚本超时“错误。

9)添加语句来调用外部库函数,以便保存和检索在内存Virtual Table Server中的数据。 10)处理XML.

11)添加语句来模仿客户端的Javascrīpt问题。 12)添加语句来管理超时。

13)从事务计时器中计算和减去无效的时间。 14)输出日志。 15)添加集合点。 16)添加时间(Timing)。 脚本语言规则:

7

把cookie代码标注出来(因为脚本运行的时候他们被再次执行)。 7。通过在VuGen中运行来调试和调整脚本(单个用户),同时运行时设置的日志能够显示如下信息:

辨别和解决脚本编辑错误。 决定timing.

设置初始运行设置的场景。

8。在控制器中使用full test Runtime Settings来运行脚本。 脚本录制和产生:

建立一个新脚本的第一步是选择一个单协议或多协议。 * 一些协议可能在多协议模式下不能用。 * 只有在多协议的GUI下你才能重新排列action

在使用Java协议之前,确保你在环境变量的路径下有JDK,否则你可能会遇到这个错误:

Error: Failed to find javac.exe Java Compiler in Path and JDK installation folder in registry. [MsgId: MERR-22981]

Error: Failed to get JRE version. Check that your PATH environment variable contains \\bin directory. [MsgId: MERR-22986] 当选择Java协议的时候:

* 只有选择了“RMI Java”才能录制。

* 如果选择“Java user”,“开始录制”图标或菜单是灰色的。 当你打开一个新的脚本时,默认的脚本名称为“noname1”。下一个新的脚本名称为“noname2”,以此类推。

注:有顺序的录制多个动作(而不是录制一个动作,然后停止开始另一个动作)。这样能使你识别出在你脚本中需要关联的序列码(在例如PeopleSoft的程序中)。 注:每次修改脚本后,脚本都需要重新编译。 Java:略

脚本文件的调用:

8

VuGen是默认在你双击.usr后缀文件的时候被调用。

在这个文件里,Javascrīpt被指定为“Type=General-Js”。 为了避免重新编译,我使用命令行的变量和值得组合这样的批处理文件来调用控制器。例如:

REM LoadRun from LoadRunner 8.0 default installation location: SET LR80=C:\\Program Files\\Mercury Interactive\\Mercury LoadRunner\\bin cd %LR80%

wlrun.exe -TestRun c:\\Temp\\Scenario1.lrs -port 8080 脚本文件Action

主机上的代理发送的到服务器的请求是由虚拟用户生成器创建的(VuGen.exe)action的回放实现的。 Loadrunner创建的脚本有三部分:

* vuser_init 来初始化 Vuser。执行在这部分的虚拟用户的状态是\ * Action 用来重复多次迭代 执行到这部分的虚拟用户的状态是\

* vuser_end 推出虚拟用户。 执行到这部分的虚拟用户的状态是\如果你的脚本只需要执行一次,你仍然需要把这些脚本写到Action部分,因为在其他部分(vuser_init 和vuser_end)有些命令是不合法的或者会忽略掉。 VuGen允许脚本包含多个action。所以我为每一个screen创建一个新的action。 注:如果你想使用不同的用户登陆,就不要把登陆操作放到vuser_init中,而是放到action部分。

VuGen根据选择脚本选择协议的不同来添加不用的引用到“.h”头文件。 C的.h头文件

对于Web(HTTP/HTML)协议, 创建globals.h,包含内容:

9

#ifndef _GLOBALS_H #define _GLOBALS_H

//-------------------------- // Include Files #include \#include \

#include \ // recorded for web_custom_request functions. //-------------------------- // Global Variables

#endif // _GLOBALS_H 对于COM/DCOM协议:略 C脚本语言的格式:

LoadRunner使用的没有进行微软扩展的ANSI C语法。任意最小的action代码块如下:

#include as_web.h // from LoadRunner's include folder. Action1() { /* comment block */ // comment line

return 0; }

C脚本编译/类库

当VuGen编译脚本时,产生一个\文件,这个文件包含了所有action的代码和包含文件。这就是为什么会有语法错误“not writing pre_cci.ci”的原因。

控制器编译这些.ci文件为机器目标码。

VuGen在每一个脚本文件中自动创建一个lib文件夹,这个文件夹中包含了combined_lib.c文件。该文件包含了所有引用文件。

#include \ 来定义 UNIX或者Windows的函数。 #include \ LoadRunner'的模版文件夹的其中一个。

10

#include \ #include \ #include \

警告:当你使用类库中的函数却没有正确包含该类库的时候,你会收到一条错误信息:

Error -- Unresolved symbol C类库

LoadRunner 使用 1994 GNU C Pre-Processoroptions 和 1995 LCC-win32 Retargetable C Compiler/Linker from the Free Software Foundation via Chris Fraser of AT&T and Dave Hanson of Princeton. 附加的函数定义在

ANSI C library中。

外部的没有返回整型数的C函数需要在脚本的开头进行显式声明。例如,string函数中的 string tokenizer:

extern char* strtok(char *token, const char *delimiter); Java语法:略

loadrunner学习系列---脚本编写(2)

VUser_Init部分

这里是Vuser_init部分的一些例子: 操作系统的User ID

下面显示了使用advapi32.dll的GetUserNameA函数获得的操作系统的用户ID char sUserID[1024]; // Maximum possible UserID length. long lUserIDSize = sizeof(sUserID)-1; int rc; rc=lr_load_dll(\ if( rc != 0 ){ lr_error_message(\Aborted for rc=%d\ lr_abort(); }else{ GetUserNameA(sUserID, &lUserIDSize);

11

lr_message(\ }

所有的变量声明需要一块放到最上方。在vuser_init 部分创建的本地C变量(如 int或char)对其他部分的脚本是不可见的。所以使用lr_save_string函数来创建对所有脚本可用的全局参数。例子:

char *itoa ( int value, char *str, int radix ); vuser_init(){ int x = 10; char buffer[10]; lr_save_string( itoa( x, buffer, 10) , \ lr_message ( \return 0; }

运行时设置的附加属性(Additional Attribute)

8.0版本引进了一个非常有价值的特性:在运行时设置中指定属性,这个属性可以对不同的虚拟用户组设置不同的值。

下面的代码是从运行时设置的附加属性中读取名为“usertype”的参数。然后使用参数值来对应的设置全局的\变量。

int thinktime1=0; vuser_init() {

LPCSTR strUsertype; // Define *str.

strUsertype = lr_get_attrib_string(\if (strUsertype==NULL){

12

lr_output_message(\Attribute usertype not specified. Cannot continue.\lr_abort();

}else{

lr_message(%usertype=\\\

if( strcmp( strUsertype,\== 0 ){ thinktime1=2; } else

if( strcmp( strUsertype,\0 ){ thinktime1=4; } else

if( strcmp( strUsertype,\else{

lr_error_message(\Aborting run.\lr_abort();

}

}

return 0;

}

Time Structure Fix(不知道怎么翻译,呵呵,“时间结构的解决“?) 根据知识库34195的文章,默认当前时间戳的毫秒部分不被更新,除非ftime使用的时间结构被重新定义:

typedef long time_t; struct _timeb { time_t time;

unsigned short millitm; short timezone; short dstflag; };

struct _timeb t;

_tzset(); \\\\ 使用ftime设置变量 _ftime( &t );

lr_message( \控制信息的显示:

在运行时,当脚本的事务失败后继续,你怎么知道哪个用户失败了? 在每个失败的事务之后,发出一个能够唯一确定该用户的信息。 Loadrunner提供了一些函数来在运行时显示信息:

? // 往输出日志上发送消息,这个消息前边会带有action 的名称和行数 lr_output_message(\

13

例子:

?Actions.c (4): an output message ? // 往输出日志和虚拟用户日志上发消息: ? lr_message(\

+\

);

把\放到另一行,这样可以容易的在命令上添加或者删除代码项。 在UNIX/Linux机器上,使用 \来添加一个换行。 在Windows 机器上,使用\来添加一个换行。 // 往输出日志上发送不带action名称和行数的信息 lr_log_message(\\\t\\\t\

// 只给控制器上的虚拟用户状态区域发送信息(当在VuGen中运行时,只是简单的显示):

lr_vuser_status_message(\

// 给LoadRunner控制器或者Tuning模块的控制台输出窗口显示一个红色高亮度显示的-17999 信息。

lr_error_message(\an error message\

使用lr_error_message将会使日志信息堆栈在每个新的action开始时被自动清空。如果选择了\当错误发生时才发送消息\这些信息仍然被创建在\日志信息堆栈\里, 但是被压缩了(没有显示),直到监测到一个错误。

LoadRunner学习---脚本编写(4)(比较重要)

2007-12-13 23:45:39 / 个人分类:性能测试

今天接着来翻译http://www.wilsonmar.com/中关于LoadRunner脚本编写部分,下面该翻译脚本编写中一些比较重要的部分了。 Web用户Action

在VuGen中,脚本产生的默认模式是基于HTML的--“描述用户的动作的脚本”直接与用户的动作是对应的:

14

* web_url是浏览器地址栏的URL.

* web_link是点击在和之间的文本超链接。 * web_image是点击HTML的

* web_submit_form 是在前面操作的上下文中的GET或PUT表单上点“提交”--可能前面的操作被VuGen在基于HTML模式下录制下来了。 * web_submit_data 是在GET或PUT表单上点“提交”,而没有带前面操作的上下文--可能是在基于URL模式下录制,或者是基于HTML模式,并且选择了“A scrīpt containing explicit URLs only”选项。

不用HTML产生的资源是.gif和.jpg图片。资源属性的列表只能当对这些资源的路直选项设置成“Record within the current scrīpt step”时被插入。这也是默认的设置。

如果你在“Tools > Internet Procotol > Recording”中选择“a scrīpt containing explicit URLs only”,这将会产生URL-based的脚本录制,只使用web_url和web_submit_data函数,将不会使用 web_link 和 web_image函数,或包含在 applets, XML, ActiveX或javascrīpt中的非HTML元素。 在进行下一页录制之前(如点击链接或者图标),暂停录制,把该页屏幕的标题拷贝下来粘贴到注释中。录制完成之后,这将会在后面的给事务命名上用到。 在每一个页面显示之后,暂停录制,把决定是否是期望页的文本拷贝下来,粘贴到注释中。录制完成之后,这将会用到文本验证检查点的脚本编写中。 录制中产生的各种信息都保存在RecordingLog.txt文件中,删除它不会对脚本的回放产生影响。 额外录制的Action脚本

录制脚本的时候,当浏览器没有安装SSL根证书的时候,会捕获的下面这些代码行。这个信息意思是“这个证书不能被信任证书验证”。 web_url(\

\dr/en/authrootseq.txt\ \

\ \ LAST);

15

web_url(\

\dr/en/authrootstl.cab\ \

\ \ LAST);

录制脚本的时候,但浏览器遇到Macromedia flash组件的时候,会产生下面的代码行:

web_url(\

\/version_en_win_ax.xml\ \

\ \

\ \ LAST);

如果你安装有Google Toolbar,即使你没有访问Google,也会录制上发到Google的请求。

脚本语言规则:

在LoadRunner中,大小写是敏感的,甚至在被检验的值中。所以上面的脚本会因为大写字母的原因,不会识别“Welcome”的。所以Steve Cheney 建议使用“ic”忽略大小写的文字标志:

web_reg_find(\Text/ic=Welcome\LAST);

括号里的参数包含了LAST 是为了指定最后的一个参数。这样做是很方便的,因为上面的例子漏掉了一个指定期望是“found”还是“notfound”的属性。默认是“found”,所有我经常忽略它。

另一个文本标志是“/BIN”用来指定是二进制的字符集。例如,查找“Adams”: web_reg_find(\LAST);

注意两个反斜杠,一个是转义字符,代表是使用了一个符号。如果错误的只使用一个反斜杠,LR会认为它是一个空的终止。

下面的例子脚本是在UTF8服务器上支持获得newquoteuid为UTF-16编码。因为LoadRunner中,UTF16编码的“Red”用ASCII是 R\\x00e\\x00d\\x00 这样的,所以需要把它保存到buffer中。

lr_eval_string_ext(\ strlen(\ &Buf, &BufLen, 0, 0, -1);

对字符数组变量NewBuf使用lr_save_var函数来去掉额外的填充(x00): for (i=0; i if (Buf[i]!=0) NewBuf[NewBufLen++]=Buf[i]; lr_save_var(NewBuf, NewBufLen-1, 0, \ 注:lr_save_var 需要四个参数(不需要使用LAST) 1.param_value 参数值

16

2 value_len 参数的长度。

3 options 参数的选项,一般为0 4。param_name 参数名称

LoadRunner 7.8不支持正则表达式,但是有他自己的通配符: 为了使任何[0-9] 的数字在指定的数字位置,使用/DIG做标志:

web_reg_save_param(\/DIG=Serial XXX-###-ZZZZ\ 有三种使用^做通配符的方法:

* 忽略大小写,并且允许在指定的字符位置使用任意字符: web_reg_find(\IC=^ercury\ * 允许任何小写字符[a-z] 在指定位置:

web_reg_find(\LC=^ercury\ * 允许任何大写字符[A-Z]在指定的字符位置:

web_reg_find(\UC=^ercury\ 把一个字符串变成大写:strupr() 错误信息:

请添加一些其他的错误信息来帮助其他人:

Could not resolve address of host ... [MsgId: MERR-27798] 如果网络不能用或者域没有注册的话,显示一个404的DNS错误 Contents unexpectedly not in cache. [MsgId: MERR-26549] 当一个文件为空时会显示该错误。在空文件中添加空格来满足LoadRunner的错误检查。BTW,因为当创建的iframe没有文件时,IE会产生一个错误,这样就指定了一个空文件。 事务时间脚本编写:

我更喜欢给一个action命名事务,而不是一个结果页面。

lr_start_transaction(\ ...

lr_end_transaction(\ ...

lr_start_transaction(\ ...

lr_end_transaction(\

lr_start_transaction(\

lr_start_sub_transaction(\ web_url( ...

lr_end_sub_transaction(\

17

lr_start_sub_transaction(\ web_submit_form( ...

lr_end_sub_transaction(\ lr_start_sub_transaction(\ web_url( ...

lr_end_sub_transaction(\

lr_end_transaction(\

我喜欢在一个层次结构中使用0填充的事务名称,这样来确保控制器能够正确的给事务排序。

我对不同类型的action上的事务名称上加不同的关键字 Contact Link = Click \ ? Contact Icon = Click \ ? Regis. Sub = Page Submit ? OK = Pop-up dismiss with OK

?

事务名可以是变量,但是它只能被VuGen作为字符串来编译,不能在控制器的接口中显示。无论如何,他们会显示在分析结果文件中。

对于web脚本,LR自动创建和决定事务的的持续时间,但是C语言脚本可以使用这些函数:

使用lr_start_transaction_instance函数来显式获得指定事务实例的句柄,事务名称在函数lr_user_data_point_instance或lr_user_data_point_instance_ex中使用。

使用 lr_start_sub_transaction在一个事务中来操作思考时间和消耗的时间。

LoadRunner关联通用函数的学习

Loadrunner脚本中进行关联的时候,用到了一些函数,作用是把字符串保存到参数中,并且在需要的时候检索出来.C Vusers中用到的函数有: lr_eval_string 所有出现参数的地方用它的当前值来代替.

lr_save_string 把null-terminated字符串保存到参数中.其

中,null-terminated的意思,我从网上查了下是:\以空字符为结束标志的字符 串\也就是以\结束的字符串,其中的0是ASCII码的0,是不能用显示字符表示出来的,只有用转义字符表示了.

18

lr_save_var 把变长字符串保存到参数中. 下面再来看下每个函数的具体解释(参考帮助): lr_eval_string: C Language

char * lr_eval_string (const char * instring ); 返回内嵌参数赋值后的字符串。 instring: 需要赋值的字符串。

lr_eval_string函数返回任何内嵌参数赋值后的输入字符串。如果字符串变量只包含一个参数,函数返回参数的当前值。 内嵌参数必须在括号中。

注:lr_eval_string是内部地分配内存。在每一次迭代之后会释放。如果你在循环中给参数赋值,不要使用lr_eval_string保存内存。你需要使用lr_eval_string_ext,并且在每个循环迭代中使用lr_eval_string_ext_free释放内存。

这里我再补充一下:lr_eval_string_ext 在关联的数据是二进制数据,例如,数据包含嵌入的NULL字符时是非常有用的。

例子:下面的例子使用lr_eval_string来代替参数row_cnt的当前值。使用lr_output_message把这个值输出到输出窗口。

lrd_stmt(Csr1, \/*Ora V7*/, 0);

lrd_bind_col(Csr1, 1, &COUNT_D1, 0, 0); lrd_exec(Csr1, 0, 0, 0, 0, 0);

lrd_save_col(Csr1, 1, 1, 0, \lrd_fetch(Csr1, 1, 1, 0, PrintRow2, 0); lr_output_message(\,

lr_eval_string(\lr_save_string:

19

C Language

int lr_save_string (const char *param_value, const char *param_name); param_value:给参数赋值的值,参数值 param_name:参数名称

lr_save_string函数把指定的以空结束的字符串赋值给参数。这个函数在关联查询的时候非常有用。需要使用lr_eval_string来确定参数的值。 例子:

在下面的例子中,lr_save_string给参数emp_id赋值为777。然后这个参数被用在另一个查询中。

lrd_stmt(Csr1, \lrd_bind_col(Csr1,1,&ID_D1,...); lrd_exec(Csr1, ...); lrd_fetch(Csr1, 1, ...);

ID_D1 0 777 lr_save_string(\

lrd_stmt(Csr1,\lrd_exec(Csr1, 0, 0, 0, 0, 0); lr_save_var C Language

int lr_save_var (const char * param_value, unsigned long const value_len, unsigned long const options, const char * param_name); param_value:参数值 value_len:值的字节长度 options:参数选项,一般为0。

20

param_name:参数名称。

lr_save_var函数把指定的变长字符串赋值给参数。这个函数在关联查询的时候非常有用。需要使用lr_eval_string来确定参数的值。 例子:

在下面的例子中, lr_save_var 用来限制参数的长度。 Action() {

#define MAX_NAME_LEN 4 // 创建参数, InName

lr_save_string(\// 把 \的前四个字节保存到 \ lr_save_var( lr_eval_string(\ MAX_NAME_LEN, 0, \ return 0; } Output:

Action.c(8): Notify: Saving Parameter \Action.c(10): Notify: Saving Parameter \

LoadRunner例子:检查点为参数的一个例子

检查点是LoadRunner的一个功能,用来验证业务功能的正确性。如果检查的内容是变化的,脚本该如何写呢?

问题提出:LoadRunner订票网站例子中,创建一个虚拟用户脚本,在登陆完成之后,设立一个检查点,来检查“welcome, xxx”。其中xxx为登陆的用户名称。

21

解决方法:

1)使用web_find() 做检查点 Action() {

//连接字符串,把welcome和用户名组合成一个字符串

char teststring[1024]=\

strcat( teststring,lr_eval_string(\lr_output_message(\lr_save_string( teststring,\

// [WCSPARAM WCSParam_Diff1 43

97279.0909680032fAADHQDpctVzzzzHDAAccpHfQtf]

//Parameter {WCSParam_Diff1} created by Correlation Studio //关联操作

web_reg_save_param(\ \ \ \

\ \

\ LAST);

web_url(\

\ \ \

\ \

\ \ LAST);

lr_think_time(11);

lr_start_transaction(\test\\\

22

web_submit_data(\

\ \

\

\

\ \ \ ITEMDATA,

\ \\ENDITEM, 名

\ \ \ \ LAST); //检查点 web_find(\ \ LAST);

lr_end_transaction(\

return 0; }

2)使用web_reg_find()做检查点 Action() {

//字符串操作,生成要检查的字符串变量 char teststring[1024]=\ strcat( teststring,

lr_eval_string(\ lr_output_message(\ lr_save_string( teststring,\

23

//参数化用户 //关联

// [WCSPARAM WCSParam_Diff1 43

97279.0909680032fAADHQDpctVzzzzHDAAccpHfQtf] Parameter {WCSParam_Diff1} created by Correlation Studio web_reg_save_param(\ \ \ \

\ \

\ LAST);

web_url(\

\ \ \

\ \

\ \ LAST);

lr_think_time(11);

lr_start_transaction(\

//检查点

web_reg_find(\ \ LAST);

web_submit_data(\

\ \

\

\

\ \ \ ITEMDATA,

\

\ //参数化登陆名称 \ \

24

\\LAST);

lr_end_transaction(\

return 0; }

LoadRunner中字符串的操作

LoadRunner中常用的字符串操作函数有:

strcpy(destination_string, source_string);

strcat(string_that_gets_appended, string_that_is_appended); atoi(string_to_convert_to_int); //returns the integer value

itoa(integer_to_conver_to_string, destination_string, base); // base is 10 strcmp(string1, string2); // returns 0 if both strings are equal 对各函数的定义:

strcpy( ):拷贝一个字符串到另一个字符串中.

strcat( ):添加一个字符串到另一个字符串的末尾。 strcmp( ):比较两个字符串,如果相等返回0。 atoi():转换一个ASCII字符串为一个整型。 itoa():根据给定的进制,转换一个整型数据为ASCII字符串 下面的例子使用了上面这些函数:

Actions() {

char MyString1[20] = \ char MyString2[20] = \

char MyString3[20] = \ char Cstring[10] = \ int Cint;

// MyString1 is empty //

lr_output_message(\

// copy \ //

strcpy(MyString1,\

25

// Now MyString1 contains \ //

lr_output_message(\

// Copy MyString3 into MyString2 //

lr_output_message(\ strcpy(MyString2,MyString3);

lr_output_message(\

// Catenate MyString2 to MyString1 //

strcat(MyString1,MyString2);

lr_output_message(\

// Cstring is converted to integer Cint //

lr_output_message(\ Cint = atoi(Cstring);

lr_output_message(\

// Cint is converted to string Cint = 100;

itoa(Cint,Cstring,10);

lr_output_message(\

return 0; }

LoadRunner编程之文件的操作

这篇文章主要写下LoadRunner下如何进行文件的操作。 1,文件的声明

LoadRunner不支持FILE数据类型,所以在LoadRunner中用int来声明一个文件:

int MyFile;

2,文件的打开

fopen():返回一个FILE数据类型的指针.因为LoadRunner不支持FILE数据类型,所以返回值需要转化成int型. int MyFile;

MyFile=(int)fopen(\

26

fopen()函数的第一个参数是创建文件的路径.第二个参数指定了创建文件的模式.下面是常用的几种模式:

“w” - 写, 当需要往文件中写的时候. 如果文件存在,就覆盖该文件,如果文件不存在,根据第一个参数来创建新文件.

“r” – 读, 需要从文件中读的时候. 这个文件必须已经存在. “a” – 附加, 当往文件末尾添加数据时用到. “rw” – 读和写.

第一个参数中注意文件路径为\因为\在C语言中为转义字符.另外,如果文件和脚本在同一个目录中,文件的完整路径可以省略.

3, 读文件

fscanf():用来读文件。函数语法如下: int MyFile;

int LoanNumber;

MyFile = fopen(“C:\\\\temp\\\\loans.txt”,”r”); fscanf(MyFile,”%d”, &LoanNumber);

需要注意的是:MyFile是个文件指针(在LoadRunner中并不是真正的指针),被用来代替实际的文件。所有文件的操作都是使用文件指针而不是文件名称。 练习1:

先创建一个文件c:\\temp\\loans.txt,文件包含的内容为: 11111 22222 33333 44444 55555

循环读取并显示该文件中的每行数据,脚本如下: Actions() {

int MyFile;

int LoanNumber,i;

// Assigning the file path to a string char FileName[80] = \

// Opening the file

// Note the use of variable to replace the file path //

MyFile = (int)fopen(FileName,\

// Reading and printing one loan number at a time for(i=1;i<=5;i++) {

fscanf(MyFile,\

lr_output_message(\

27

}

fclose(MyFile);

return 0; }

当文件打开之后,文件指针在文件的最开始。每读一次,指针就移动到下一行,这就是为什么程序能自动读取下面元素的原因。

a) 如果把循环改为for(i=1;i<=7;i++),会出现什么样的结果呢?

会出现三个都是打印55555的结果,原因是文件指针移动到最后就不再移动了,但是有7次循环,那多出来的2次循环打印的数据仍然是最后一行的数据。

b) 如果不知道该文件下包含数据的行数, 就无法用for循环。需要使用while循环。可以使用feof函数。feof(MyFile)在文件指针没有到达返回文件末尾的时候返回0,如果到末尾返回非0值。这样可以修改程序的循环为: while(feof(MyFile)== 0);

注意:如果文件末尾有空行,feof也会把它最为文件的一部分。 4,写文件 fprintf():用来往文件写。语法如下: int MyFile;

char Name[] = “John Doe”;

MyFile = fopen(“C:\\\\temp\\\\loan.txt”,”w”); fscanf(MyFile,”%s”,Name);

第一个参数是文件指针,第二个参数是格式,第三个参数是指定格式对应的变量。 Actions() {

int MyFile;

char Name[] = \

MyFile = fopen(\

// note that \

fprintf(MyFile,\

// note that we are printing a string here

LoadRunner脚本实例来验证参数化的取值

问题提出: 主要想试验下,在Controller中,多个用户,多次迭代中参数的取值.

方法:

28

脚本: 我把取到的参数值和对应的VuserID记录下来保存到一个文件中,下面是例子的脚本

long fileopen;

char *filename = \

vuser_init() {

if ((fileopen = fopen(filename,\

lr_error_message (\ return 0; } return 0; } Action() {

int id,scid; char *vuser_group;

//typedef long time_t; //time_t t; long t;

char *a = \ char *b = \

lr_whoami(&id, &vuser_group, &scid);

fprintf(fileopen,\(b),ctime(&t));

return 0; }

vuser_end() {

fclose(fileopen); return 0; }

参数设置为:

取唯一值,每次迭代更新。

(a),lr_eval_string

运行时设置的迭代次数为2。

29

场景的设置: 虚拟用户数:5个

运行模式:没有设置duration,选择的“Run until complete” 完成后的日志文件params.log的内容如下: 1,a1,b1,Thu Jan 01 08:00:05 1970 1,a2,b2,Thu Jan 01 08:00:05 1970 10,a5,b5,Thu Jan 01 08:00:05 1970 10,a6,b6,Thu Jan 01 08:00:05 1970 2,a3,b3,Thu Jan 01 08:00:05 1970 2,a4,b4,Thu Jan 01 08:00:05 1970 30,a9,b9,Thu Jan 01 08:00:05 1970 30,a10,b10,Thu Jan 01 08:00:05 1970 21,a7,b7,Thu Jan 01 08:00:05 1970 21,a8,b8,Thu Jan 01 08:00:05 1970

从生成的日志文件中可以看到VuserID分别为1,2,10,21,30 第一次迭代取参数分别为1,3,5,7,9 第二次迭代取参数分别为2,4,6,8,10

那试验的结果就是每个Vuser取参数的时候相同的Vuser在多个迭代中取的是连续的。不同的Vuser第一个的取值是计算了迭代次数后的那个顺序上的值。

LoadRunner关联函数的脚本实例--如何操作关联参数

这几天一直在学习LoadRunner的VuGen编程,今天想对关联函数web_reg_save_param做详细的试验和研究:

问题提出:如何对关联的数据进行字符串操作。下面使用了LoadRunner自带的订票例子为例,进行了这方面的试验。假设我要关联的数据是由几个字符串组成的。如何使这些字符串组成一个参数,供我后面的函数使用?

解决方法:使用多个关联函数,对关联参数进行字符串操作,最后把生成的字符串保存成一个参数,供下面调用该参数的函数使用。 脚本如下: Action() {

int number1,number2;

char session11[1000]; char string[1000]; int length; char *stringtemp;

30

//char session22[20];

value=\

web_url(\

\ \

\ \ \ \ LAST);

strcpy(string,\

strcpy(string,lr_eval_string(\

//strcpy(session1,\

sprintf(session11,\ strcat(string,\

length= strlen(lr_eval_string(session11)); length=length-2;

number1=atoi(lr_eval_string(\ number2=atoi(lr_eval_string(\

lr_output_message(\

//lr_output_message(\ stringtemp=lr_eval_string(session11); strncat(string,stringtemp,length); //srcat(string,session11);

lr_save_string(lr_eval_string(string),\

lr_output_message(\ lr_output_message(\

web_submit_data(\

\ \

web_reg_save_param(\

border=0> \

web_reg_save_param(\

31

\ \ \ \ ITEMDATA,

\{session}\ \ \ \ \ \ LAST);

lr_output_message(\{session}\

return 0; }

有两个关联的参数,session1和session2,最后生成session,被web_submit_data函数调用。蓝色部分是需要特别注意的地方。

脚本编写调试过程中遇到的问题和解释:

1. web_reg_save_param()中如果没有指定Ord=ALL的话,默认是取的第一个符合左右边界的

值,这样我们使用关联的参数时可以直接使用变量名,如session1

2. web_reg_save_param()中如果指定Ord=ALL的话,会生成一个数组,这样想取某个参数

的话,需要使用的参数名需要加_和数组中的位置,如例子中取第一个session1_1,如果这时候仍然用session1,是取不到参数的值的. 3. 顺序问题:对关联参数相关的操作,需要放到包含该关联数据的请求函数之后,如上紫色部分

代码用到关联的参数的语句,都需要放到web_url()之后,否则也不会取到关联的数据 4.注意lr_eval_string()函数和lr_save_string()函数的用法..

LoadRunner如何在大负载下测试

在大负载中使用LoadRunner进行负载测试,需要配置一些环境来满足大负载下各种资源的充足:

1.为了避免出现“No Buffer Space Available”的错误,需要进行如下配置: 1)修改注册表:

* 设置

“HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\tcpip\\Par ameters\\TcpTimedWaitDelay”为 30 * 设置

“HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\tcpip\\Par ameters\\MaxUserPort”为 65534 * 在

32

“HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Session Manager\\Sub Systems\\Windows”设置SharedSection 为 4096

2)通过在每个脚本的开头添加如下函数来设置“SHUTDOWN”模式为\

web_set_sockets_option(“SHUTDOWN_MODE”,”ABRUPT”) 2.关闭所有的杀毒,反间谍扫描软件等。同时也关闭任务扫描和所有不需要的服务。

3.脚本运行时设置:

1)设置日志为“只在错误发生时发送信息” 2)去掉错误时产生snapshot的选项

3)在miscellaneous上,去掉 定义每一步为一个事务 的选项

4)不选择 模拟浏览器缓存,选上“simulate new user on each iteration”和它的子选项

4.如果下载的页没有资源,在web_url函数中添加“Mode=HTTP”,这样会减少LG上的负载(不用转换成HTML)。默认情况下,web_url的Mode为Mode=HTML 5.重启LG并且确保他们都能跟Controller连接. 6.确保LG和控制器上有足够的剩余磁盘空间. 7.在controller中去掉web page breakdown

8.限制Vuser在所有LG上同时进行初始化的数目.可以在Controller的Tools > Options > Run-Time Settings中进行修改.每个LG都有这个设置. 9.限制controller在运行时存储的错误数.通过修改wlrun.ini中的[output]项来实现:

? FlagLimitOutputMessages=1

? MaxNumberOfOutputMessages= (default is 10,000) 10.在Controller上修改Monitor的采样率来降低CPU的使用.可以在Controlller的Tools > Options > Monitors 下修改,如下图所示:

33

11. 如果有很多错误产生,最好不要经常打开Error/Output窗口,因为这样会因为访问数据库而打开另外的数据库连接. 12.负载测试中不要使用\选项.

13.把输出信息重定向到一个文本文件中来代替输出到mdb文件中.可以在wlrun7.ini中修改[output]下的 ExportMessageToFile=1来实现.

14.不要在Controller机器上运行虚拟用户. 15.在场景中设置监视器:

* 内存使用上 mmdrv进程的private bytes * disk使用 * CPU使用 * 网络使用

16.把脚本中所与打印信息的脚本去掉.如下面的代码每次迭代都会调用一次,对大量并发用户的运行产生负面的影响.

lr_vuser_status_message(\

START Action\lr_output_message(\lr_eval_string(\

Controller处理所有虚拟用户的信息,这样会大大降低Controller的性能. 如下是类似的代码:

web_reg_find(\web_url( some url ?);

if (atoi(lr_eval_string(\lr_error_message(some message);

lr_end_transaction(\}

通常认为在脚本中插入lr_error_message是不好的,除非是调用的客户化的API失败了才有必要插入该语句.如果是LoadRunner的函数调用失败(如上面的web_url调用),它会自动发送一个错误消息.

34

在大量用户运行的情况下,控制Controller和LG之间的通信流量是非常重要的.发送多余的信息(错误,输出等信息)会增大通信流量降低负载能力.所以,通常都需要把代码中不必要的信息去掉.

17.去掉脚本中所有的sleep()的调用,用lr_think_time()来代

替.lr_think_time给LR让出控制,即LR能够在Vuser休眠的时候去做其他有用的事情.

18.不要去掉lr_think_time:使用该函数能更准确的模拟负载,对LG产生相对小的压力

19.web_reg_save_param和web_reg_find()函数:

? 在 web_reg_save_param() 中添加“Notfound=empty” 参数.

? 在 web_reg_find() 添加 \如果你想知道它是否成功可以使用

atoi(lr_eval_string(\来衡量. 20.其他

可能会出现的问题: * 测试产生了太多的错误:

错误引擎不能处理多于1.5GB的错误

如果测试过程中每秒产生多与1000个错误,Controller的行为将不可预测

* 测试产生了大量的在线数据

上面的两个问题都可以使用如下的方法解决: 例如: 场景是一个组有1000个虚拟用户 可以把这个组分成两个组: G1 100 Vusers G2 900 Vusers

这两个组可以跟原始的组产生一样的负载,对于G2在组命令行中添加如下参数:

-disable_data -disable_messages

35

_disable_data : 让这个组不发送任信息,不发送任何online信息,不写任何offline信息.

_disable_message: 让这个组不给Controller发送任何信息(错误,日志)

注意:使用上面的命令行选项会使该LG不给congtroller发送online和offline信息.这样这个组上的虚拟用户的分析数据就收集不到了. 21.如果需要远程访问,Mercury仅支持PC anywhere.

36

_disable_data : 让这个组不发送任信息,不发送任何online信息,不写任何offline信息.

_disable_message: 让这个组不给Controller发送任何信息(错误,日志)

注意:使用上面的命令行选项会使该LG不给congtroller发送online和offline信息.这样这个组上的虚拟用户的分析数据就收集不到了. 21.如果需要远程访问,Mercury仅支持PC anywhere.

36

本文来源:https://www.bwwdw.com/article/rq5w.html

Top