当前位置: 首页 > 测试知识 > LoadRunner中编写自定义函数库提升脚本复用性
LoadRunner中编写自定义函数库提升脚本复用性
2026-07-24 作者cwb 浏览次数63

LoadRunner创建自定义函数库是提升脚本复用性、降低维护成本的方式。通过将常用的业务操作、检查思路、数据处理等封装成独立库做到编写一次,多处调用。

一、创建自定义函数库(.c+ .h)

典型做法是创建一个 .c 源文件和一个对应的 .h 头文件。


示例:lr_common_utils.h


c

#ifndef LR_COMMON_UTILS_H

#define LR_COMMON_UTILS_H

// 通用函数:获取随机字符串

char* lr_gen_random_string(int length);

// 业务封装:统一登录

int web_login(const char* username, const char* password);

// 内容检查:判断页面是不是包含指定文本

int lr_verify_content(const char* step_name, const char* expected_text);

#endif


示例:lr_common_utils.c


c

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include "lr_common_utils.h"


// 引入 LoadRunner API(实际环境中由 VuGen 自动包含)

#include "lrun.h"

#include "web_api.h"


// 生成指定长度的随机字符串(含大小写字母数字)

char* lr_gen_random_string(int length) {

    static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    char *randomString = NULL;

    int i, max = sizeof(charset) - 1;

    if (length < 1) return "";

    randomString = (char *)malloc(sizeof(char) * (length + 1));

    if (!randomString) return "";

    // 使用 lr 的随机数,更契合负载场景

    for (i = 0; i < length; i++) {

        int key = (int)(lr_rand() % max);

        randomString[i] = charset[key];

    }

    randomString[length] = '\0';

    return randomString; // 调用方需 free

}


// 封装 web 登录事务

int web_login(const char* username, const char* password) {

    int result;

    lr_start_transaction("login");


    // 假设登录请求

    web_submit_data("login_action",

        "Action=https://zmtests.com/login",

        "Method=POST",

        "TargetFrame=",

        "RecContentType=text/html",

        "Snapshot=t1.inf",

        "Mode=HTML",

        ITEMDATA,

        "Name=user", "Value={username}", ENDITEM,

        "Name=pass", "Value={password}", ENDITEM,

        LAST);


    result = lr_get_transaction_status("login");

    lr_end_transaction("login", result == LR_PASS ? LR_PASS : LR_FAIL);

    return result;

}


// 检查页面内容,并记录事务

int lr_verify_content(const char* step_name, const char* expected_text) {

    int found = 0;

    char step_txn[128];

    sprintf(step_txn, "%s_verify", step_name);

    lr_start_transaction(step_txn);

    web_reg_find("Text={expected_text}",

        "SaveCount=found_count",

        LAST);

    

    // 模拟一次页面获取,这里用实际请求(可在调用前完成请求)

    // 如果是证实刚完成的页面,直接从 found_count 判断

    found = atoi(lr_eval_string("{found_count}")) > 0;

    

    if (found) {

        lr_end_transaction(step_txn, LR_PASS);

        lr_output_message("%s: Verification passed.", step_name);

    } else {

        lr_error_message("%s: Verification failed! Expected: %s", step_name, expected_text);

        lr_end_transaction(step_txn, LR_FAIL);

    }

    return found;

}


二、将库添加到LoadRunner脚本

两种方式将库文件引入脚本。


方式1:作为脚本本地文件

在 VuGen 的 Solution Explorer 中,右键点击脚本名下的 Action或其他存放代码的文件夹,选择 Add Files to Script。

将准备好的 lr_common_utils.h 和 lr_common_utils.c 添加进来。它们会出现在Extra Files分类下。

在需要使用这些函数的Action文件顶部,用 #include 引入头文件:


c

#include "lr_common_utils.h"


方式2:作为全局公共库多脚本共享

如果希望多个脚本共用同一套库,可将其放在统一的文件夹中,并通过以下两种方法之一引用:

在 VuGen 中设置 include 途径:打开菜单Tools - Recording Options或运行时设置旁,在 C Language页签中,把库文件夹途径添加进 Include directories。然后脚本中直接 #include "lr_common_utils.h" 即可。

使用全局扩展文件:将库文件放入 LoadRunner 安装目录下的 config 子目录(如 ..\Micro Focus\LoadRunner\config\),并保证文件名不冲突,然后脚本中用 #include "lr_common_utils.h" 并利用 VuGen 的自动依赖检测。


方式1编译独立性好,适合团队协作和版本管理(可随脚本入库);方式2适合成熟公用库,注意 LoadRunner 版本升级时途径可能变化。


三、在脚本中调用自定义函数

库添加成功后,在Action、vuser_init、vuser_end等部分调用。


c

vuser_init()

{

    return 0;

}


Action()

{

    char *uname = lr_gen_random_string(8);

    lr_save_string(uname, "rndUser");

    free(uname); // 注意释放内存


    // 直接调用封装好的登录

    if (web_login(lr_eval_string("{rndUser}"), "123456") == LR_PASS) {

        lr_output_message("Login successful.");

    }


    // 证实首页是不是包含“Welcome”

    web_url("homepage", "URL=https://zmtests.com/home", LAST);

    lr_verify_content("home", "Welcome");


    return 0;

}


四、提升复用性的设计原则

高内聚低耦合

每个函数只负责一个清晰的功能(如登录、数据检查、签名生成),避免将多个不相关操作强行合并。


参数化动态化

所有可能变化的数据(URL、参数值、检查点文本)均通过函数参数传递,或者借助 LoadRunner 的参数化机制(lr_eval_string)。不要在库中硬编码业务值。


统一的错误处理和返回值

定义确定的返回码(如 0 成功,非0失败),库函数内部通过 lr_error_message 记录详情,外部可根据返回值决定事务成败。


避免全局变量污染

用静态变量或函数参数传递状态,如果必须使用全局变量,用 static 限制作用域,并保证线程安全(LR 中每个 Vuser 有独立内存空间,一般不存在竞态,但使用 web_save_param 等全局参数时要注意上下文)。


平台兼容性

使用 ANSI C 语法(C89/90),避免 C++ 特性(除非脚本类型为 C++ Vuser)。

需要网络或文件操作的函数,留意 LoadRunner 沙盒限制(如文件途径使用相对途径或 lr_get_attrib_string 获取脚本目录)。

对内存分配必须检查并 free,防止内存泄漏在长时间稳定性测试中被放大。


五、高级扩展DLL / .NET 程序集

当测试非常复杂如加解密算法、数据库操作且对性能要求很高时,可编译成外部 DLL。

C DLL:用 Visual Studio 创建 Win32 DLL,导出函数,然后在 LoadRunner 脚本中通过 lr_load_dll("path\\mylib.dll") 加载并直接调用。

.NET Assembly:创建 .NET Framework 类库,在 LoadRunner 的 .NET Vuser 脚本中直接引用,或在 C 脚本中通过 COM 互操作(不常用)。

这类库的复用性最强,但版本依赖和部署稍复杂,适合算法封装。


六、维护和版本控制建议

将自定义函数库文件和脚本一起纳入版本控制系统(Git、SVN)。

建立函数库变更日志,重大改动时升级版本号(如写在头文件注释中),避免旧脚本突然编译失败。

编写库的使用示例和单元测试脚本,以便在升级后快速证实。


LoadRunner脚本会逐渐积累出一套稳固的测试脚本库,大幅减少重复编码。


文章标签: 软件测试 测试工具
咨询软件测试