转自:http://www.ibm.com/developerworks/cn/rational/r-cn-rftloadrunner/

脚本开发,场景构建与配置,性能监控,测试结果分析

张 营 (mailto:zyingcdl@cn.ibm.com), 软件工程师, IBM
谷 林 (mailto:gulin@cn.ibm.com), 软件工程师, IBM

2008 年 3 月 28 日

本文概要介绍 IBM Rational Performance Tester (简称 RPT)和 HP Mercury LoadRunner (简称 LR)两个性能 / 压力测试工具,主要从脚本开发,场景构建与配置,性能监控,测试结果分析几个方面,对 LR 和 RPT 的使用做了详细的对比分析,并根据 IBM Lotus Form 系统测试团队从 LR 到 RPT 的迁移的工作经历中总结了一些 RPT 的一些实用技巧。对于那些需要从 LR 工具切换到 IBM RPT 的测试人员的测试技术的平滑过渡,具有较强的借鉴意义。

1 概要介绍

LoadRunner 是一种适用于各种体系架构的自动负载测试工具,通过模拟实际用户的操作行为和实施实时性能监测,来帮助用户排查和发现问题。相比于 RPT, LR 能支持更广范的协议和技术,适应面很广,为用户的特殊环境提供特殊的解决方案。LR 的组件很多,其中最核心的组件包括:

  • Vuser Generator(VuGen) 用于捕获最终用户业务流程和创建自动性能测试脚本
  • Controller 用于组织、驱动、管理和监控负载测试。
  • Load Generator 负载生成器用于通过运行虚拟用户生成负载。
  • Analysis 有助于您查看、分析和比较性能结果。

IBM Rational Performance Tester(简称 RPT)也是一款性能测试工具,适用于基于 Web 的应用程序的性能和可靠性测试。Rational Performance Tester 将易用性与深入分析功能相结合,从而简化了测试创建、负载生成和数据收集,以帮助确保应用程序具有支持数以千计并发用户并稳定运行的性能。

  • RPT 是针对 Web 应用程序的性能测试工具,基于 Windows 和 Linux 的用户界面,使用基于树型结构的测试编辑器提供高级且详细的测试视图。
  • 提供不同用户数的灵活的模拟,支持将 Windows 和 Linux 用作分布式负载生成器,使用最小化的硬件资源实现大型、多用户的测试。
  • 支持使用自定义 Java 代码的灵活测试定制。

2 脚本开发对比

LR/RPT 的脚本的开发过程通常都是采用录制 + 定制的模式。首先通过对典型业务逻辑的录制,完成脚本中的基本业务的框架,然后针对录制结果,通过参数化,数据关联,增加逻辑控制等方式加强脚本的适应性来满足特殊的业务需求。

2.1 脚本录制 / 定制过程

  • LR:直接生成面向过程的运行代码

LR 通过对基本业务的录制,VuGen 将生成的 Vuser 函数(也称作 LR API)并将他们插入到脚本中。在实践中,LR 脚本就是由这样的 Vuser 函数和一些定制代码组成的。对于基于 Web(HTTP/HTML) 的应用程序的测试,多数用户选择基于 C 语言的 LR 脚本,显然,这种 LR 脚本是一种面向过程的脚本,开发者可以对最终运行的脚本进行直接的修改与调整。对于开发者来说,这种 LR 脚本的开发方式比较灵活。相应地,这项工作,对于开发者的编程基础,尤其是 C 语言和 LR API 的了解,要求都比较高。

  • RPT:录制结果经过“翻译”生成最终的运行代码

与 LR 不同,RPT 的脚本录制过程可以拆分成两步。如图 1 所示,第一步,RPT Recorder on RAC 负责记录用户的所有 HTTP 请求,生成一系列的 Trace 文件。Trace 文件记录了用户与服务器的交互过程。第二步,当用户完成脚本的录制过程之后,RPT Test Generator 能够根据 Trace 文件“翻译”一遍,生成最终运行的测试脚本。

这种生成临时 Trace 文件的好处是用户可以随时依据该 Trace 文件生成新的测试脚本,然后再对脚本进行测试场景定制,而不用对同一个操作过程做多次录制操作。


图 1. RPT 脚本的录制和生成架构
RPT 脚本的录制和生成架构

2.2 参数化

录制业务流程时,LR/RPT 生成一个包含录制期间用到的实际值的脚本。假设用户要使用不同于录制内容的值执行该脚本的操作时,就需要用参数替换已录制的值。这被称为脚本参数化。脚本的参数化可以简化脚本,同时增强脚本适用性。对于 LR 和 RPT 脚本,参数化过程类似,都是定义参数,为参数指定属性或者数据源的过程。但是在 LR 中,只有函数中的参数才能参数化,除此之外,其他字符串不能进行参数化。

RPT 的参数化过程同样简单(以替换用户登录密码为例来说明),首先,选中需要进行参数替换的请求页面,如图 2 所示,选中左侧的登陆请求页面。在其右侧的 Test Data 中则显示与该请求页面相关的所有数据信息,脚本录制人员可以用其他值代替图 2 中的 password 变量。


图 2. RPT 脚本参数化
RPT 脚本参数化

2.3 数据关联

数据关联类似于参数化,可以简化脚本,适应企业应用中需要动态数据的情况。默认情况下,LR 和 RPT 都能做到一些基本的数据关联,但是由于 HTTP 请求之间关联的复杂性,需要用户手动做一些数据关联。数据关联包含三个步骤,一是定义哪个录制的值需要被关联(替换);二是定义数据源。三是定义被关联的数据与数据源之间的关联关系。

LR 的数据关联过程如下:lr_save_XXXX(value,dataSource)语句将数据源的值保存到参数 dataSource 中;用 lr_eval_XXXX(dataSource)语句替换被关联的数据。

RPT 中如果需要自己定义关联,则在 HTTP 请求中的 URL 中或者 Data 中选择需要创建关联的部分,然后右键选择替换对象。其中替换对象可以是脚本中已经建立好的引用(这里的引用就是一种用户自定义的数据源),或者 RPT 自带的数据源(例如时间戳对象),或者是 Custom Code( 下节介绍 )。

图 3 中浅紫色的部分是已经被关联的 URL,运行测试时该部分将由被引用的 URL 值来替换该 URL。


图 3. RPT 数据关联
RPT 数据关联

2.4 Custom code

Custom code 是 RPT 独有的概念。尽管 RPT 脚本开发过程中,用户可以直接在 UI 层面达到对脚本的定制,但是这种定制能力毕竟有限。将定义好的 Custom Code 通过 UI 穿插到脚本之中,从而为 RPT 录制的脚本提供充足的扩展能力来保证其灵活的定制性。Custom code 本质上就是一个 Java 类。Custom Code 需要实现 com.ibm.rational.test.lt.kernel.custom.ICustomCode2 接口,并实现该接口中的如下方法:

public String exec(ITestExecutionServices tes, String[] args)
            

ITestExecutionServices tes 参数是 Test Container 中的一个实例 , 使用它可以访问 Test Container 运行态一些服务。

String[] args 参数是我们定义 Custom Code 时定义传入的参数数组。

该方法的主体就是基于传入的信息进行业务逻辑处理代码,然后将处理结果(一个字符串)返回,其返回的字符串可以被后续的请求引用。Custom Code 是一个纯 Java 的类,所以具有 Java 编程经验的人都可以根据业务需求编写自己的 Custom code。

2.5 数据池

性能 / 压力测试过程中,通常都需要为某些测试提供大量的测试数据。LR 和 RPT 都提供了数据池功能,即是将一个数据文件作为参数值赋给一个参数。

LR 中,用户可以指定该文件的多个数据以何种方式赋值到该参数中。LR 提供三种选择,顺序,随机,唯一。前两种比较容易理解,最后一种是指每个虚拟用户都从该文件中取不同的值作为参数值,如果该数据池不足够大,所有的备选值都已经被取出过一次,即该数据池资源被用尽时,LR 报错。

在 RPT 中,用户只能顺序从数据池中读入测试数据。RPT 的数据池是以 XML 格式存储的,并且在测试开始时,将数据池中的所有数据都加载到内存中,这样的实现模式不利于测试中使用大数据量。不过灵活的 Custom Code 功能可以弥补这方面的不足。对于大量的测试数据,可以通过自定义 Custom Code 来实现 On Demand 的数据读取和加载。


图 4. RPT 数据池
RPT 数据池

2.6 流程控制

LR 脚本大部分是基于 C 语言的,因此 C 语言中的流程控制语句(例如判断、循环等)都可以加入到 LR 脚本中。RPT 的流程控制操作可以通过 UI 界面轻松进行,它提供了灵活的流程控制模式,包括 IF 条件控制结构,和 LOOP 循环结构。

1. IF 条件控制结构

在 RPT 脚本中,可以将一部分连续的页面或者 HTTP 请求放到一个 IF 条件中去,然后由判断条件来确定 IF 结构中的页面或者 HTTP 请求是否被执行。其判断条件可以是 RPT 自动参数化后的参数,也可以是 Custom Code 的返回值,或者是数字、字符串等。

图 5 是添加了 IF 条件后的脚本,包含了为 IF 语句设置判断条件的配置界面。


图 5. RPT IF 条件控制结构
RPT IF 条件控制结构

同样,RPT 也支持 IF-ELSE 的结构。

2. LOOP 循环结构

RPT 中的另外一种流程控制结构就是 LOOP 结构,如图 6 脚本中,将所有的页面放到了一个 LOOP 结构中,然后可以通过指定循环次数来确定其中的脚本循环执行多少次。


图 6. LOOP 控制结构
LOOP 控制结构

2.7 全局信息

这里所说的全局信息,实际上是脚本运行时,LR/RPT 产生的内部数据,例如:当时的运行时间,Vu 所在用户组组名,迭代编号等。在 LR 中,所有的全局信息作为特殊的参数类型,供脚本开发者使用。例如 : 如果一个变量为 Group Name 类型,则该变量的值即为当前用户所在的用户组的组名。

RPT 中的全局信息,存在 IDataArea 对象中。IDataArea 对象包含三个方面的信息,分别是“Test Data”、“Virtual User Data”、“Engine Data”,这些信息都可以通过 Custom Code 来获得。

Custom Code 的实现需要继承 ICustomCode2 类,并实现该接口的核心方法“public String exec(ITestExecutionServices tes, String[] args)”,该方法的第一个参数就可以获得 IDataArea 对象,然后获得全局信息。同时用户也可以向 IDataArea 对象中添加信息,提供给测试脚本的其它地方使用。

2.8 错误控制

LR 用户可以指定脚本执行期间的错误的处理方法。默认情况下,当脚本执行出现错误,脚本将退出执行。用户也可以配置运行设置指示当 Vuser 出现错误时仍继续执行脚本。除此之外,用户还可以在脚本中加入 lr_error_message 函数,便于用户对日志的分析。

RPT 中,当脚本运行出现错误,脚本将继续执行 , 可能后续会出现很多错误。

2.9 Debug

LR VuGen 可用作常规文本编辑器。您可以在其中打开任何文本文件并进行编辑。当重播期间在输出窗口中显示错误消息时,您可以双击该错误消息, VuGen 将使光标跳到导致问题的测试行。您还可以将光标置于错误代码上并按 F1 键,查看该错误代码的联机帮助 .

RPT 在运行完一个测试之后,会产生相应的测试日志,如果在测试过程中发生任何错误,RPT 会以“Message”的形式提示出该请求发生错误。如图 7 中的测试日志中被选中的 Message 表示该 HTTP 请求在引用前面的关联值时发生错误。


图 7. RPT 错误日志
RPT 错误日志 

3 场景构建与配置对比

脚本只是定义了某些用户的操作步骤,而一个场景则包含了有关如何模拟实际用户的所有信息。LR 和 RPT 的场景构建过程比较类似,只是对脚本循环的控制,分配负载生成器等配置上略有差别。

LR 中,Controller 组件负责场景的创建。您需要在一个场景中添加一个或多个脚本,并为每个脚本分配相应的 Vuser 组。然后,您可以为每个 Vuser 组分配多个虚拟用户,指定模拟该用户组的负载生成器。图 8 中,负载生成器即为本机,即负载生成器跟 Controller 是同一台机器,如果该处配置成其他计算机的 IP 地址,那么该用户组的负载模拟将由其他计算机完成。LR 中不能通过 Controller 指定一个脚本执行与否的概率,但是可以通过 C 语言开发,完成随机调用脚本的功能。Runtime-Setting 包含了所有针对该场景的一些附加配置,如脚本循环次数,等待时间,网络模拟等。


图 8. LR 场景创建
LR 场景创建

RPT 中测试场景,是通过“Schedule”来组织的。Schedule 通过用户组、循环控制、随机选择器等功能部件来组织测试脚本使其满足实际场景。用户组则由循环控制或者随机选择器,再加上测试脚本等元素组成。循环控制用来控制其下的测试脚本需要循环执行的次数。随机选择器是为了实现在多个测试脚本中随机选择一个来执行。可以为随机选择器指定权重,通过权重值来决定在多个随机选择项中某项被随机选中的概率大小。图 9 是一个 RPT 创建场景的例子,其中“Schedule Element Details”提供了对 Schedule 的丰富配置功能,与 LR 中的 Run-Time 配置功能类似。


图 9. RPT 场景创建
RPT 场景创建

RPT 的负载生成器配置也比较简单,首先选中要放到其它 RPT 主机上进行模拟的 User Group,然后在其配置界面中选中“Run this group on the following locations”,在其中添加远端的 RPT 主机信息。


图 10. RPT 负载生成器配置
RPT 负载生成器配置 

4 性能监控功能对比

LR 和 RPT 内部都集成了一些实时监控器,RPT 可以对事务,Web,系统,Web 应用服务器等资源进行实时监控。LR 的监控范围更广泛一些,除了上述资源之外,还可以对网络,防火墙,Web 服务器,数据库,ERP,Java 等资源进行实时监控。无论使用那种测试工具,在自动测试过程中的任何时间,用户都可以获知系统的多种性能指标的当前值和变化趋势。

在一个测试场景中,用户需要将被监控的服务器信息加入到资源监控列表中。LR 中,如图 11 所示,从左侧资源树中选择资源种类,在右侧对应资源状态显示窗口中,右键添加被监控的服务器名称。


图 11. LR 添加被监控的服务器信息
LR 添加被监控的服务器信息

RPT 中,图 12 所示,用户需要在 Schedule 的配置窗中的“Resource Monitoring”标签栏添加需监控的服务器。


图 12. RPT 添加被监控的服务器信息
RPT 添加被监控的服务器信息 

5 测试结果分析功能对比

LR 和 RPT 都提供了测试结果的多种图表以及图表之间的叠加效果,方便用户分析测试结果。LR 中测试结果图表的生成由 Analysis 组件完成。默认情况下,用户可以直接看到测试的总体概要分析,吞吐率,事务平均响应时间等图表,如果用户希望看到其他资源的监控图,可以通过添加图表完成(图 13)。“Merge Graghs”可以帮助用户将同一个测试结果中的多种资源的结果进行叠加(图 14)。“Cross Result”可以生成多次测试结果的比较分析图(图 15)。


图 13. LR 添加其他资源监控图
LR 添加其他资源监控图

图 14. LR 同一次测试中多种监控图的叠加
LR 同一次测试中多种监控图的叠加

图 15. LR 多次历史测试结果之间的比较
LR 多次历史测试结果之间的比较

RPT 也为测试结果提供了直观的图表表现,默认情况下,用户可以直接看到对测试成功率的总体柱状图,整个测试过程完成的总体信息列表,测试中页面的反应时间曲线图等报告。也可以通过添加其他监控信息的方法,将其他资源的监控图叠加到当前的监控图中。


图 16. RPT 叠加其他资源监控图
RPT 叠加其他资源监控图

RPT 也可以实现多次测试结果的比较。在 RPT 的“Test Navigator”中选择待比较的测试结果,在其右键菜单中选择“Compare”,打开“Compare Results”窗口,然后将需要做比较的测试结果添加进来,在下一步中选择要显示的报告,点击“Finish”按钮打开比较结果的显示页面。图 17 是一个测试结果的比较报告。


图 17. RPT 多次历史测试结果之间的比较报告
RPT 多次历史测试结果之间的比较报告 

6 Rational Performance Tester 实用技巧

1)调整日志采样频率和粒度以适应不同的测试场景

RPT 的 Schedule 提供了测试数据的采样频率和采样粒度的配置,以适应不同的测试场景。在做长时间测试时,在 Schedule 的配置面板中的“Statistics”标签中通过适当增加日志采样间隔时间、日志级别和采样用户量,降低 RPT 的压力,避免因采样数据量过大,使内存耗尽,导致 RPT 无法响应。


图 18. Statistics 配置
Statistics 配置

在测试过程中,RPT 会记录测试中的请求数据和响应数据,以便在测试之后查看测试过程中的数据和错误信息。对于长时间测试,会产生大量的请求和响应数据,这些大量的日志信息会让 RPT 不堪重负。在 Schedule 配置部分的“Test Log”标签中提供了日志记录的级别设置,对于长时间的测试,推荐使用图 19 所示的配置,记录错误和警告信息的级别为“All”,而对于其它信息则只记录“Primary Test Actions”即可。


图 19. LOG 配置
LOG 配置

2)通过 Custom Code 实现多条测试数据的随机读取

在 RPT 中通常采用 DataPool 的形式作为少量测试数据(例如模拟多个用户登录所用的多个用户名密码信息)的输入。不过 DataPool 的读取方式为顺序读取。如果对于输入数据需要随机读取,则可以通过 Custom Code 来实现。其实现方式可以是将测试数据存为“*.cvs”等格式文件,然后通过文件操作,并根据随机数从文件中读取内容作为测试输入数据。

3)使用超大测试数据集文件

对于在测试过程中存在少量测试数据分次作为测试输入数据时(例如模拟多个用户登录所用的多个用户名密码信息),通常采用 DataPool 的形式,但是在测试数据量较大时该方法就不再适用,因为对于 DataPool 中的数据,测试开始时就被全部加载到内存,如果测试数据量过大,这种方式会造成大量的内存浪费。

这种情况可以通过 RPT 提供的扩展功能 Custom Code 来定制代码,达到在测试过程中在需要的时候再去加载所需的内容,其实现也可以采用文件操作的方式。

 

总结

本文中,我们概要介绍了 RPT 和 LoadRunner 两个性能压力测试工具,从多方面对两个工具进行详细的对比分析,并根据实践经验总结了一些 RPT 的实用技巧。通过本文,并学习链接中的网站,希望您能更快,更多的了解和使用 Rational Performance Tester 工具。

免责声明和公开声明

本文所述观点是基于作者个人对相关产品的理解,并不代表 IBM 的官方观点,IBM 不对本文中的信息负责。本文是在本人的知识范围内写成的。如果您发现有异议的地方,请与本人联系。

参考资料

学习


获得产品和技术

 

作者简介

张营,软件工程师,现在 IBM 中国软件开发实验室 Lotus 测试开发中心工作,目前从事 IBM Lotus Forms 系统测试。之前从事过 IBM Workplace Collaboration Services 功能测试,自动化测试。对软件测试、协同软件有浓厚兴趣。
 
谷林是 IBM 中国一名软件工程师,现在 IBM 中国软件开发实验室 Lotus 测试开发中心工作,目前从事 IBM Lotus Forms 系统测试。对 Java、Web 技术和软件体系结构有着浓厚的兴趣,并在 Java 软件开发和软件测试方面有较丰富的经验。