杰瑞科技汇

loadrunner java 脚本

LoadRunner 支持 Java 作为虚拟用户协议,这意味着你可以使用 Java 语言来编写性能测试脚本,这对于测试基于 Java 的技术栈(如 J2EE, Spring Boot, Hibernate, JMS, JDBC 等)的 Web 应用、API 或后端服务非常有用。

loadrunner java 脚本-图1
(图片来源网络,侵删)

为什么选择 LoadRunner Java 脚本?

  1. 强大的 Java 生态:可以直接使用 Java 库(如 Apache HttpClient, OkHttp, Jackson, Gson, JUnit TestNG 等)来构建复杂的测试逻辑,而不仅仅是录制和回放简单的 HTTP 请求。
  2. 复用现有代码:如果你的团队已经有现成的 Java 测试框架或业务逻辑代码,可以很方便地迁移或集成到 LoadRunner 脚本中。
  3. 处理复杂业务:对于需要复杂状态管理、数据驱动、加密解密、调用第三方 Java SDK 的场景,Java 脚本比 Web (HTTP/HTML) 协议更灵活、更强大。
  4. 测试非 Web 应用:除了 Web 应用,Java 脚本还可以用来测试通过 RMI、EJB、JMS、Socket 等协议通信的 Java 后端服务。

Java 脚本的核心结构

一个标准的 LoadRunner Java 脚本主要由以下几个部分构成,这些函数可以在 VuGen 的脚本视图中找到:

函数名 作用 执行时机
init() 初始化函数,用于建立数据库连接、初始化变量、读取外部数据文件等,每个虚拟用户只执行一次。 脚本开始时
action() 核心操作函数,这是脚本的主体,包含了主要的业务逻辑,如发送请求、接收响应、验证结果等,在迭代场景中,每个迭代都会执行一次。 性能测试时
end() 结束函数,用于释放资源,如关闭数据库连接、清理临时文件等,每个虚拟用户在所有迭代完成后执行一次。 脚本结束时
vuser_init() Vuser 初始化函数,通常用于登录等建立会话的操作,每个 Vuser 只执行一次。 init() 之前执行
vuser_end() Vuser 结束函数,通常用于登出等销毁会话的操作,在 end() 之后执行。 end() 之后执行

脚本执行流程vuser_init() -> init() -> [循环开始] -> action() -> action() -> ... -> [循环结束] -> end() -> vuser_end()


创建 Java 脚本的两种主要方式

录制 (Recording)

这是最简单的方式,适用于已有可操作的 GUI 应用。

  1. 新建脚本:打开 VuGen,选择 "New Script",然后选择 Java 协议。
  2. 设置录制选项
    • Application to Record: 选择你要录制的 Java 应用,这通常是一个 .jnlp (Java Web Start) 文件或一个本地的 .jar 文件。
    • Working Directory: 指定 Java 应用的主目录。
    • Classpath: 指定 Java 应用的类路径,确保 VuGen 能找到所有必需的库。
    • JVM Options: 可以设置 JVM 参数,如内存大小等。
  3. 开始录制:点击 "Record" 按钮,VuGen 会启动一个指定的 JVM 来运行你的 Java 应用,你在应用中的所有操作(如点击按钮、输入文本)都会被记录下来,并转化为 Java 代码中的 lr_ 函数调用(如 lr_think_time, lr_output_message)或对特定 Java GUI 组件的操作。

录制脚本的优缺点

loadrunner java 脚本-图2
(图片来源网络,侵删)
  • 优点:快速生成脚本骨架,无需手动编写所有代码。
  • 缺点:生成的代码通常比较冗余,不够灵活,难以维护,对于复杂的动态业务逻辑,录制往往力不从心。

手动编写 (Manual Scripting)

对于 API 测试、无界面后端服务测试或需要高度定制化的场景,手动编写是更好的选择。

  1. 新建脚本:同样选择 Java 协议创建一个新脚本。
  2. 引入外部库:在 VuGen 的 "Classpath" 设置中,添加你需要的第三方库的 .jar 文件(如 httpclient-4.5.13.jar, gson-2.10.1.jar 等)。
  3. action() 函数中编写代码:使用你熟悉的 Java 代码来构建和发送请求。

实战示例:手动编写 Java 脚本测试 REST API

假设我们要测试一个简单的用户注册 API:

  • URL: http://api.example.com/users/register
  • Method: POST
  • Header: Content-Type: application/json
  • Request Body: {"username": "testuser", "password": "password123"}
  • Expected Response: HTTP Status Code 201

步骤 1:准备环境

  1. 确保你的 LoadVuGen 安装了 Java 协议支持。
  2. 下载 httpclient-4.5.13.jarhttpcore-4.4.15.jar (或其他版本),并将其复制到你的 LoadRunner 安装目录下的 include 文件夹,或者在脚本的 "Classpath" 中指定。

步骤 2:编写脚本代码

在 VuGen 的脚本视图中,修改 action() 函数如下:

import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
// lr_*** 函数是 LoadRunner 提供的 C 语言风格的函数,可以在 Java 中使用
import lrapi.lr;
public class Actions {
    // 定义常量,方便维护
    private static final String BASE_URL = "http://api.example.com";
    private static final String REGISTER_ENDPOINT = "/users/register";
    private static final String USERNAME = "testuser_" + System.currentTimeMillis(); // 使用时间戳保证用户名唯一
    private static final String PASSWORD = "password123";
    int init() {
        // 初始化代码,例如创建一个全局的 HttpClient 实例
        // 注意:在 init 中创建,可以在所有 action 迭代中复用,提高性能
        return 0;
    }
    int action() {
        lr.vuser_status_message("Starting user registration test for user: " + USERNAME);
        // 1. 创建 HttpClient 和 HttpPost 对象
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BASE_URL + REGISTER_ENDPOINT);
            // 2. 设置请求头
            httpPost.setHeader("Content-Type", "application/json");
            lr.vuser_status_message("Request Header set to: application/json");
            // 3. 设置请求体
            // 使用 JSON 格式构建请求体
            String jsonPayload = String.format("{\"username\": \"%s\", \"password\": \"%s\"}", USERNAME, PASSWORD);
            httpPost.setEntity(new StringEntity(jsonPayload));
            lr.vuser_status_message("Request Body: " + jsonPayload);
            // 4. 发送请求并获取响应
            HttpResponse response = httpClient.execute(httpPost);
            // 5. 处理响应
            int statusCode = response.getStatusLine().getStatusCode();
            lr.vuser_status_message("Received Response Status Code: " + statusCode);
            HttpEntity entity = response.getEntity();
            String responseBody = entity != null ? EntityUtils.toString(entity) : null;
            lr.vuser_status_message("Response Body: " + responseBody);
            // 6. 验证结果
            if (statusCode == 201) {
                lr.output_message("User registration successful for user: " + USERNAME);
                lr.pass("Status code is 201 as expected.");
            } else {
                lr.error_message("User registration failed. Expected status code 201, but got " + statusCode);
                lr.fail("Test failed due to incorrect status code.");
            }
        } catch (ClientProtocolException e) {
            lr.error_message("ClientProtocolException: " + e.getMessage());
            lr.fail("Test failed due to a protocol error.");
            return -1; // 返回非零值表示脚本出错
        } catch (IOException e) {
            lr.error_message("IOException: " + e.getMessage());
            lr.fail("Test failed due to an IO error.");
            return -1;
        }
        // 模拟思考时间
        lr.think_time(2);
        return 0;
    }
    int end() {
        // 结束代码,例如关闭资源
        // 在 try-with-resources 中管理的资源会自动关闭,这里可以放其他清理逻辑
        return 0;
    }
}

步骤 3:参数化 (Parameterization)

为了模拟不同用户,我们需要对用户名进行参数化。

loadrunner java 脚本-图3
(图片来源网络,侵删)
  1. 在 VuGen 中,选择 "Create" -> "Parameter List"。

  2. 点击 "New Parameter",命名为 username_param

  3. 选择数据类型为 "File",然后创建一个数据文件(如 users.txt),每行一个用户名。

  4. 在脚本中,将硬编码的 USERNAME 替换为参数:

    // 原代码
    // private static final String USERNAME = "testuser_" + System.currentTimeMillis();
    // 替换为
    private static final String USERNAME = lr.eval_string("{username_param}");

步骤 4:运行和调试

  1. Run Single User: 先运行单个 Vuser,检查日志输出 (lr.vuser_status_messagelr.output_message 的内容),确认脚本逻辑是否正确。
  2. Run in Controller: 确认无误后,将脚本添加到 Controller 中,设计场景并运行负载测试。

LoadRunner Java 脚本的常用函数

除了标准的 Java 语法,你还可以使用 LoadRunner 提供的 lr_ 系列函数来增强脚本能力。

函数类别 常用函数 作用
输出和日志 lr.output_message() 输出信息到日志,级别为 "Message"。
lr.vuser_status_message() 输出信息到 Vuser 日志,在 Controller 中实时可见。
lr.error_message() 输出错误信息。
lr.log() 更底层的日志函数,可以指定日志级别。
事务 lr.start_transaction("transaction_name") 开始一个事务,用于测量特定操作的性能。
lr.end_transaction("transaction_name", LR_AUTO) 结束一个事务。LR_AUTO 表示根据事务中的最后一个 lr_ 函数(如 lr.eval_string)是否成功来自动确定事务状态。
参数 lr.eval_string("{param_name}") 获取参数的当前值。
lr.save_string("value", "param_name") 在运行时动态保存一个值到参数。
思考时间 lr.think_time(seconds) 在脚本中插入暂停,模拟真实用户的思考时间。
错误处理 lr.fail("error message") 标记当前迭代为失败。
lr.pass("success message") 标记当前迭代为成功。
关联 lr.save_search() 虽然在 Java 中不像 Web 协议那样常用,但可以用来从响应中提取数据并保存到参数。

最佳实践和注意事项

  1. 资源管理:使用 try-with-resources 语句(如 try (CloseableHttpClient ...) {})来管理数据库连接、HTTP 客户端等资源,确保它们能被正确关闭,避免内存泄漏。
  2. 避免硬编码:将 URL、端点、用户名、密码等配置信息定义为常量或参数,提高脚本的可维护性。
  3. 使用日志:善用 lr.vuser_status_message() 在关键步骤输出日志,这对于调试和分析问题至关重要。
  4. 事务分离:将核心业务逻辑(如“提交订单”)封装在一个事务中,以便精确测量其性能。
  5. 参数化:始终对动态数据(如用户ID、Session ID)和可变数据(如用户名)进行参数化,确保脚本的可重用性和数据的唯一性。
  6. 性能考虑:在 init() 中创建和初始化重量级的对象(如 HttpClient、数据库连接池),在 action() 中复用它们,而不是在每次迭代中都重新创建。
  7. 错误处理:使用 try-catch 块来捕获和处理可能发生的异常,并在发生错误时使用 lr.fail() 标记失败,而不是让脚本直接崩溃。

希望这份详细的指南能帮助你掌握 LoadRunner Java 脚本的编写!如果你有更具体的问题,比如如何处理特定的协议或技术,可以随时提出。

分享:
扫描分享到社交APP
上一篇
下一篇