本主题解释了如何使用自定义 Load Test 组件扩展 Parasoft Load Test 功能。在本章节中:
关于自定义 Load Test 组件
Parasoft Load Test 功能可以通过创建自定义 Load Test 组件来扩展。Parasoft Load Test 充当 Load Test 组件或负载测试 bean 的容器。 Load Test 组件是一个功能核心,它定义了负载测试期间虚拟用户的行为。负载测试容器向组件提供以下服务:
- 根据负载测试场景创建、调用和配置虚拟用户(以及 Load Test 组件)。
- 从本地机器和远程机器收集组件报告,并将它们累积到一个组合负载测试报告中。
- 在开始负载测试之前,将组件序列化到远程计算机。
- 提供在负载测试项目文件中保存组件配置的方法。
- 提供通过 GUI 进行组件配置的方法。
可以通过扩展位于com.parasoft.simulator.api 包中的 Load Test 组件 Java API 的 SimRunnable类来创建 Load Test 组件。SimRunnable 表示可运行的 Simulator。Simulator 是负载测试容器的名称,它模拟多个虚拟用户活动。
构建组件示例
组件示例位于 SOATest/负载测试安装的 examples\dev\components
文件夹中。这个 simple-runnable-source.jar 和 socket-runnable-source.jar 归档包含本教程中所描述组件的资源、配置和构建文件。您将需要将这些归档解压到 Load Test 组件项目目录,该目录必须手动创建。
创建一个 Load Test 组件项目目录
若要在负载测试安装之外创建组件项目目录,请执行以下操作:
- 将
simple-runnable-source.jar
复制到组件项目目录中,并解压组件源归档文件。 - 将
socket-runnable-source.jar
解压到SocketRunnable
目录,该目录必须手动创建。每个源目录包含一个component-build.xml
ANT 构建脚本。 - 打开这个文件并确保
load.test.install.root
属性指向您的 SOAtest/Load Test 安装目录。 - 将
load.test.jar.path
属性更改为指向loadtest.jar
文件(该文件位于 SOAtest/Load Test 安装目录的eclipse\plugins\com.parasoft.xtest.libs.web_[version_number]\root
中)。
创建一个 SimpleRunnable Load Test 组件项目
若要在 Eclipse 中创建一个 SimpleRunnable Load Test 组件项目,请执行以下步骤:
- 打开新建项目“New Project”向导,选择 Java Project,然后单击 Next。
- 命名项目为
SimpleRunnable
。 - 选择 Create project from existing source,选择 SocketRunnable 目录,然后单击 Next。
- 在 Source 选项卡中,确保默认输出文件夹设置为
SocketRunnable/target/classes
。 - 打开 Libraries 选项卡,单击 Add External Jar 并添加 parasoft.jar 和 com.parasoft.api.jar (在
eclipse\plugins\com.parasoft.xtest.libs.web_[version]\root
directory of your SOAtest/Load Test 安装目录中)。 - 在 Eclipse 中,右键单击 component-build.xml 并选择 Run As> Ant Build 以创建组件 .jar 文件。
注意
组件应该使用 Java 1.5 JRE 构建,最好使用 JRE 1.5.0_18。
每个示例项目中的component-build.xml
ANT 脚本的默认目标构建一个组件 jar 归档文件,该文件可以作为自定义或内置组件部署到负载测试中。如果使用 Eclipse 来编译此处描述的组件项目,请从 component-build.xml
脚本的 jar 目标中删除 compile 目标依赖项。 创建一个 SocketRunnable Load Test 组件项目
SocketRunnable 组件扩展了 SimpleRunnable 组件。首先编译 SimpleRunnable
,然后从 SimpleRunnable 根目录中将 main.jar
放入 SocketRunnable 项目的 lib
目录。
若要在 Eclipse 中创建一个 SocketRunnable Load Test 组件项目,请执行以下步骤:
- 打开新建项目“New Project”向导,选择 Java Project,然后单击 Next。
- 选择 Create project from existing source,选择 SimpleRunnable 目录,然后单击 Next。
- 在 Source 选项卡中,确保默认输出文件夹设置为
SimpleRunnable/target/classes
。 - 打开 Libraries 选项卡,单击 Add External Jar 并添加 parasoft.jar 和 com.parasoft.api.jar (在
eclipse\plugins\com.parasoft.xtest.libs.web_[version]\root
directory of your SOAtest/Load Test 安装目录中)。 - 在 Libraries 选项卡中,确保
lib/jtidy-r820.jar
和lib/main.jar
在项目类路径上。 - 在 Eclipse 中,右键单击 component-build.xml 并选择 Run As> Ant Build 以创建组件 .jar 文件。
将示例组件加载/部署到负载测试中
组件可以作为外部存档加载到负载测试中,也可以作为内置组件部署。
从外部存档加载组件
若要从外部存档加载组件:
- 在负载测试 GUI 中选择负载测试配置树的 Profiles 节点。
- 在项目配置视图中,单击 Select。
- 在选择组件归档文件对话框中,选择 Local option,单击 Next,然后选择您的 Load Test 组件归档文件。
- 单击 Finish。组件部署视图将如下所示。
如果组件验证失败,错误消息将显示在 Deployment 视图的下表中。
将组件存档作为内置组件部署
若要将组件存档作为内置组件部署到负载测试应用程序中,请执行以下操作:
将组件 jar 存档文件放置 SOAtest/Load Test 安装的
eclipse\plugins\com.parasoft.xtest.libs.web_[version]\root\lt-components\built-in
文件夹中。- 重启负载测试。
- 从 File 菜单中,选择 Customize Preferences。您将在内置组件部署视图中看到组件部署细节,如下所示。
如果一个内建组件已经成功部署,那么它将在内建的下拉列表中的 Select component Archive 对话框中可用,如下图所示:
使用 Load Test 组件 API
通过从负载测试应用程序菜单栏的 Help 菜单中选择 API> Component API 子菜单,可以获得 Load Test 组件 API 的 Javadoc 文档。
分析 SimpleRunnable 组件示例
本节将研究 SimpleRunnable Load Test 组件。
SimpleRunnable 是一个基本组件,它模拟可配置持续时间的测试执行,并以可配置的频率产生错误。它的设计目的是让您熟悉 Load Test 组件 API 以及组件存档创建和部署的过程。
运行 Load Test 组件的主要方法(PrivateContext 上下文)。模拟用户活动的组件行为应该在此方法中实现。组件运行方法由特定概要文件的虚拟用户对象调用。然后由负载测试应用程序根据负载测试场景调用虚拟用户。
SimpleRunnable 的其余方法执行容器所需的各种服务。下面,我们将描述最重要的组件方法。有关其他方法的详细信息,请查看 SimpleRunnable 类的源代码和 SimRunnable 的 JavaDoc。
下面是对该组件最重要的方法的描述:
- SimRunnableOutput run(PrivateContext context) – 组件的核心功能方法。各种容器特定的变量都可以通过 PrivateContext 作为参数传递给这个方法。有关可用上下文变量的列表,请参阅 API 文档中的 PrivateContext。
- String canRun() – 此方法由容器调用,以确保组件已正确配置并可以调用。检查所有组件成员变量是否正确初始化。如果没有,返回一个错误描述。如果组件准备好了,返回 null。返回非 null 错误描述将阻止负载测试启动,并显示错误字符串。
boolean done() – 容器在调用该类的 run() 方法后调用此方法,以确定组件是否已完成其活动。组件可以模拟一个多步骤的用户活动,每个步骤后面都跟着负载测试概要文件中配置的虚拟用户判断时间。在这种情况下,run() 方法将被多次调用,直到 done() 返回 true。返回 false 将导致框架保留这个组件类的实例所属的虚拟用户,并再次调用它的 run() 方法。返回 true 将导致该组件类的实例所属的虚拟用户从虚拟用户池中删除。
重要项 - 释放虚拟用户
您最终需要从 done() 方法返回 true,以便从池中删除虚拟用户。一旦虚拟用户从池中删除,如果负载测试场景需要,它将被相同概要文件的新虚拟用户替换。释放虚拟用户非常重要,因为它允许框架跟踪计划的虚拟用户的起伏或每秒命中的次数。
- SimRunnable prototype() – 这是一个工厂方法。每次容器创建虚拟用户时,都会为其分配一个组件类的新实例。当组件部署到容器中时,容器创建组件类的实例,该实例用作创建组件类对象的原型,这些对象在负载测试期间分配给虚拟用户。框架调用组件类的 prototype() 方法来获取组件原型的副本,并让组件决定如何进行复制。在实现此方法时,请确保将所有必要的组件成员变量复制到新创建的组件实例中。可以按值或引用来复制组件类成员:
- 按引用复制组件类成员时,请注意这些类成员应该受到充分的保护,以防止并发访问或修改。如果这成为一个问题,请考虑按值复制(深拷贝)。
- 当按值复制组件类成员时(深拷贝),请记住,在负载测试应用程序运行负载测试时,可以同时存在成百上千的虚拟用户(以及该类的实例)。应用程序中虚拟用户的数量取决于负载测试模式和负载测试场景中计划的值。 Load Test 组件占用的内存过大,可能会导致应用程序耗尽内存。在本例中,考虑按引用复制成员变量。
- void onDeploy(DeploymentContext context) – 当组件存档部署到容器中时,容器将调用此方法。各种部署特定的变量都可以通过 DeploymentContext 作为参数传递给这个方法。该方法的 SimpleRunnable 实现表现了如何访问包含在组件部署中的配置(和其他)文件。
- void writeExternal() and void readExternal() – 将组件状态传输到远程计算机的方法。
注意,SimpleRunnable 类的 writeExternal() 和 readExternal() 方法只有框架实现,不编写也不读取任何数据。这些方法用于将组件状态转移到远程负载测试机器。SimpleRunnable 组件不需要这种状态传输,因为组件存档中包含的组件外部配置文件用于本地和远程机器上的组件配置。我们将在不同组件示例中研究 writeExternal() 和 readExternal() 的实现。
接下来,让我们看看 SimpleRunnable 的外部配置文件。SimpleRunnable 组件的源文件夹包含两个组件配置文件:LongExecTime.cfg and ZeroExecTime.cfg.其中之一包含在组件归档文件中(请查阅 component-build.xml ANT 脚本)。
当将组件存档部署到容器中时,将解压缩存档,并通过 DeploymentContext 的 DEPLOYMENT_BASE 属性将存档内容提供给组件。SimpleRunnable 类的 onDeploy 方法的实现展示了如何定位和解析 .cfg 组件配置文件来初始化 SimpleRunnableConfiguration 实例。如果负载测试配置包含远程机器,那么在负载测试开始之前将组件存档传输到每个远程机器,然后部署每个组件。
部署过程完成后,将调用 onDeploy 方法。onDeploy 方法从 .cfg 文件初始化组件,该文件包含在组件存档中。只有当组件存档文件在远程安装时不存在,或者其在主计算机和远程计算机上的校验不同时,才会将其序列化到远程计算机。这确保了只有在需要时才会将组件存档传输到远程机器。
组件存档描述符
每个组件存档的根目录中必须包含 lt-jar.xml 组建存档描述符。描述符必须包含从 SimRunnable 派生的主组件类的类名,以及从 SimRunnableOutput 派生的组件输出的类名。有关组件存档描述符文件格式的示例,请参阅所包含组件的 lt-jar.xml 文件。
使用 SimpleRunnable 组件运行负载测试
一旦将 SimpleRunnable 组件部署到负载测试中,并熟悉 SimpleRunnable 源代码和组件存档结构,就可以修改组件存档配置,重新运行负载测试,并查看修改后的组件配置的效果。例如,您可以按照以下步骤来更改此组件模拟的测试执行时间:
- 在 .cfg 文件中添加 execTimeMs 参数。
- 运行组件存档 ANT 构建脚本。
- 在 Load Test 组件视图中,单击 Reload 按钮。
- 重新运行负载测试。注意,负载测试报告的统计部分中的测试执行时间遵循配置的执行时间持续时间。
执行统计数据反映了组件配置文件的 execTimeMs 参数更改到 1200。
分析 SocketRunnable 组件示例
本节研究 SocketRunnable 组件。SocketRunnable 类扩展了 SimpleRunnable,并演示了以下内容:
- 在应用程序日志中记录内部错误。
- 创建组件配置 GUI 面板。
- 创建负载测试概要文件 GUI 面板,它允许概要文件特定的组件配置。
- 保存负载测试项目中的组件配置。
- 将组件配置转移到远程机器。
- 使用 jar 库扩展组件功能。
- 本地化组件资源。
SocketRunnable 组件使用 SocketTest 类实例建立到特定主机和端口的连接,发送可自定义的请求,并使用 Java 套接字接收响应。属于组件的 SocketTest 实例可以在 SocketRunnable 组件视图中进行配置。
在应用程序日志中记录内部错误
您可能立即需要日志,因此可以从 SocketRunnable 构造函数中的引擎中获取日志。Engine engine = (Engine)context.get(PrivateContext.ENGINE);
ComponentLog log = engine.getComponentLog();
创建组件配置 GUI 面板
组件可以通过实现 SimRunnableConfigViewProvider 接口向容器提供自定义配置视图。容器将在上面显示的 Load Test Runnable 组件面板的 Configuration 选项卡中显示这个视图。容器调用 SimRunnableConfigViewProvider 接口的 getConfigView() 方法来获取组件的配置视图。在本例中,SocketRunnableView 类实现组件配置视图。SocketRunnableView 类使用位于 com.parasoft.loadtest.component.example.socket.test.view 包中的 SocketTest*View 类进行单独的 SocketTest 实例配置。
为特定于概要文件的组件配置创建负载测试概要文件 GUI 面板
可以设计 Load Test 组件来实现特定于负载测试概要的行为。实现 ProfileRunnable 或 Subprofilerunable 接口的类充当 Load Test 组件的特定于概要的子组件。这些类实现组件的特定于概要的行为。
SocketRunnable 示例中有两个类实现了 ProfileRunnable 接口:SocketProfileRunnable 和 SocketTestWrapper。SocketProfileRunnable 充当可运行的根概要文件;它是 SocketTestWrappers 的容器。SocketRunnable 类保存 SocketProfileRunnable 的一个实例,其中存储所有已配置的 SocketTestWrappers。SocketRunnable 还保存 SocketTestWrappers 的 Vector;这个 Vector 表示特定负载测试概要文件的可运行概要文件的一个选项。负载测试配置中的每个概要文件都保存其组件类的副本。这保证了概要文件特定的组件配置不会冲突,也不会相互覆盖。
SocketRunnable 的 populateSubProfileRunnables() 方法根据从概要文件特定的 PrivateContext 获得的 ProfileRunnableMap 填充 selectedProfileRunnables Vector。ProfileRunnableMap 包含负载测试概要特定于 ProfileRunnable 的选项。
为了让您选择负载测试概要特定的 ProfileRunnables,SocketRunnable 组件实现了 ProfileRunnableViewProvider 接口,如下所示。
SocketRunnable 使用 API 的 ProfileRunnableTreeView。
保存负载测试项目中的组件配置
Load Test 组件可以通过实现 SaveablePropertiesProvider 接口将其配置保存到负载测试项目中。组件配置由 SimRunnableProperties 类表示,该类存储组件属性 name/value 对。
组件属性必须保存为独立于组件类的字符串值。这一点保证了即使没有部署组件,也可以将项目读入负载测试应用程序。同时,这允许项目存储不同的组件类型配置。容器使用 SimRunnableProperties 类的标记字段将适当的属性实例返回给组件。标记值应该由组件开发人员设置。SoatestRunnable 使用 "SOCKET_RUNNABLE_SAVEABLE_PROPS_V.1” 字符串作为其可保存属性标签。
如果保存组件配置需要比一组 name/value 属性对更复杂的数据结构,可以使用 XML 作为替代。将组件配置序列化为 XML 表示形式,并将 XML 字符串保存在 SimRunnableProperties 实例的单个 name/value 对中。有关如何使用 XML 保存和恢复组件配置的示例,请参阅 SocketRunnableXMLSerializer。
将组件配置转移到远程机器
必须将 Load Test 组件配置转移到远程负载测试机器上,该配置可以从负载测试项目文件中读取,也可以由您和您的团队修改。组件状态传输应该在组件类实现的 ParasoftExternalizable 接口的 readExternal/writeExternal 方法中实现。由于 SocketRunnable 组件的可配置部分由 SocketProfileRunnable 类型的 rootProfileRunnable 成员变量表示,因此必须将其传输到远程机器。SocketProfileRunnable 类到远程机器的序列化在该类 readFrom/writeOn 和 readExternal/writeExternal 方法的实现中得到了演示。或者,远程机器的序列化可以重用将组件配置保存到负载测试项目的代码。对于 SocketRunnable 示例,可以重用 SocketRunnableXMLSerializer 类功能,以 XML 字符串的形式将组件配置序列化/反序列化到远程机器。
使用 jar 库扩展组件功能
您的组件代码可以使用您选择的 jar Java 库。SocketRunnable 示例代码使用 Jtidy 库来分析它可以接收到的响应 Web 页面请求的 HTML 代码(请参阅 SocketTest 类的 checkTidy 方法)。组件依赖 jar 文件必须包含在组件 jar 存档库文件夹中(请参阅 component-build.xml ant 脚本构建的 socket.jar 组件归档文件)。
本地化组件资源
您可以使用 LocalizationUtil API 类来本地化组件字符串。SocketRunnable 示例的 Localization 类加载适当的资源包并包装 LocalizationUtil 方法,以便更容易地访问。