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脚本会逐渐积累出一套稳固的测试脚本库,大幅减少重复编码。