测试动态 / 测试知识 / LoadRunner VuGen C语言脚本开发技巧大全
LoadRunner VuGen C语言脚本开发技巧大全
2026-07-21 作者:cwb 浏览次数:18

LoadRunner VuGen C 语言脚本开发技巧大全

LoadRunner的VuGen使用标准C语言(或类似 C 的语法)作为脚本语言,并提供了大量 lr_、web_ 等开头的API。掌握C语言基础和 LoadRunner 特有函数的结合技巧是写出稳定、高效、易维护脚本的重点。


一、脚本结构和设计原则

1.三段式结构

vuser_init:只执行一次,用于登录、初始化连接等。

Action:反复执行(根据迭代次数),存放重要业务思路。

vuser_end:只执行一次,用于退出、清理资源。

把初始化思路放在vuser_init,避免每次迭代重复登录;事务尽量放在Action中。


2.用函数封装复用思路


c

// 封装一个登录函数,返回事务是不是成功

int login(const char* user, const char* pwd) {

    int rc = 0;

    lr_start_transaction("login");

    // 提交登录请求...

    if (/* 成功 */) {

        lr_end_transaction("login", LR_PASS);

        rc = 1;

    } else {

        lr_end_transaction("login", LR_FAIL);

    }

    return rc;

}


这样可在 vuser_init 和后续需要重新登录的地方直接调用。


3 使用LR_PARAM宏代替硬编码

c

#define URL "http://www.zmtests.com"

改为:


c

lr_save_string("http://www.zmtests.com", "pUrl");

web_url("step", "URL={pUrl}", LAST);


便于统一管理和参数化。


二、参数化技巧

1.基础参数化

选中值 - 右键 - Replace with a Parameter - 创建参数并指定数据文件。


常见用法:


c

web_submit_data("login",

    "Action=http://www.zmtests.com/login",

    "Method=POST",

    "TargetFrame=",

    "Referer=",

    ITEMDATA,

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

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

    LAST);


2. 动态获取参数值

lr_eval_string("{参数名}") 返回字符串,可用于C变量比较或处理。


c

char *user = lr_eval_string("{Username}");

if (strcmp(user, "admin") == 0) { ... }


注意:lr_eval_string 返回的指针可能在下一次调用后失效,需要及时复制。可用 strcpy 或 lr_save_string 保存。


3.参数更新方法选择

Select Next Row:Sequential / Random / Unique

Update Value On:Each iteration / Each occurrence / Once


场景:模拟不同用户并发时,使用 Unique + Each iteration,并启用When out of values: Abort Vuser可保证数据不重复。如果数据有限,应设置合适的中止方法或循环使用。


4.参数化非字符串类型

整数参数可直接用 {intParam},VuGen 会自动转换为字符串,使用时再转回:


c

int num = atoi(lr_eval_string("{countParam}"));


5.参数文件使用技巧

文件首行作为列名,参数名和列名一致。

支持多个参数共享同一文件多列。

使用 lr_advance_param 可手动推进参数行,实现精细控制:


c

lr_advance_param("MyParam");

三、关联技巧

1.手动关联四步法

录制两份相同业务脚本,对比差别,找出动态值(如 Session ID)。

找到动态值出现的服务器响应,确定左右边界。

在请求之前添加关联函数 web_reg_save_param:


c

web_reg_save_param("sessionID",

    "LB=Set-Cookie: sessionid=",

    "RB=;",

    "Search=Headers",

    LAST);


用 {sessionID} 替换脚本中硬编码的动态值。


2.使用正则表达式关联

边界不规则或需一致复杂方式时,改用 web_reg_save_param_regexp:


c

web_reg_save_param_regexp(

    "ParamName=token",

    "RegExp=token[\"']?\\s*:\\s*[\"']([^\"']+)",

    "Ordinal=1",

    SEARCH_FILTERS,

    "Scope=Body",

    LAST);


可通过 RegExp 设置捕获组。


3.关联多个一致项Array

当响应中有多个相同边界的值时,使用 Ord=All:


c

web_reg_save_param("items",

    "LB=<li class=\"item\">",

    "RB=</li>",

    "Ord=All",

    LAST);


然后用数组接口获取个数和值:


c

int count = atoi(lr_eval_string("{items_count}"));

char itemName[256];

sprintf(itemName, "{items_%d}", i+1);  // 索引从1开始

lr_output_message("Item: %s", lr_eval_string(itemName));


或使用 lr_paramarr_idx、lr_paramarr_len 函数。


4.关联边界转义

特殊字符需转义:如 "LB=name=\"value\""。

如果边界包含换行,可尝试 \r\n,或使用 Search=Body 时开启 Extended 选项。


5.自动关联的使用

录制后VuGen会自动扫描关联建议,可快速建立规则,但必须检查生成的边界是不是鲁棒,避免只对单一响应有效。


四、事务和检查点

1.事必须须成对出现


c

lr_start_transaction("T01_SubmitOrder");

// ... 业务请求 ...

lr_end_transaction("T01_SubmitOrder", LR_AUTO);


严禁事务名称不一致、忘记结束事务或在子函数里开始却不结束。


2.使用检查点判断事务成功


c

web_reg_find("Text=Payment Successful",

    "SaveCount=success_count",

    LAST);


web_submit_data("pay", ...);


if (atoi(lr_eval_string("{success_count}")) > 0)

    lr_end_transaction("T01_Pay", LR_PASS);

else

    lr_end_transaction("T01_Pay", LR_FAIL);


SaveCount 记录了出现次数,即使一次也可用于判断。


3. 事务内不应包含思考时间

如果业务需要,应把 lr_think_time 放到事务外面,或在 Controller 中设置事务不计思考时间。

在VuGen中,可在 Run-time Settings - General - Think Time 设置忽略或按比例回放。


4.图像检查点

c

web_image_check("src=images/logo.gif",

    "Alt=Company Logo",

    LAST);


证实页面完整性。


五、日志和调试

1. lr_output_message 和 lr_log_message

lr_output_message 始终输出到日志和控制台,适合调试。

lr_log_message 发送到 LoadRunner 内部日志,仅在对应日志级别启用时才可见。


c

lr_output_message("当前用户:%s,订单号:%s", lr_eval_string("{user}"), orderNo);


2.设置日志级别

在脚本中动态调整:


c

lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG | LR_MSG_CLASS_RESULT_DATA, LR_MSG_ON);

// 调试后关闭

lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG, LR_MSG_OFF);


或在 Run-time Settings 的 Log 选项中勾选 Extended log。


3.使用断点和Watch

VuGen 支持设置断点,右键菜单可添加变量到 Watch 窗口,观察参数值变化。

回放时可按 F5 逐步执行。


4.输出服务器返回内容

c

web_reg_save_param("responseBody", "LB=", "RB=", "Search=Body", LAST);

// 请求...

lr_output_message("%s", lr_eval_string("{responseBody}"));


对于调试关联非常有用。


六、C语言常见问题

1.字符串操作安全

永不要使用未初始化的 char 数组作为输出。

使用 snprintf 或保证缓冲区足够大的 sprintf。


c

char temp[512];

snprintf(temp, sizeof(temp), "Order_%s", lr_eval_string("{orderID}"));


LoadRunner 的sprintf在某些版本可能导致栈溢出,安全做法是用 lr_save_string 组合或 snprintf。


2.动态内存管理

VuGen 允许 malloc/free,但必须及时释放,避免在长期运行时内存泄漏。

也可以利用 lr_eval_string 的自动管理,但注意其返回指针的生命周期。

如果使用大量字符串,优先用 LoadRunner 参数系统存储。


3.类型转换

字符串 - 整数:atoi(lr_eval_string("{count}"))

整数 - 字符串:lr_save_int(myNum, "myParam") 或 sprintf

浮点数:可使用 atof,保存浮点参数需用 lr_save_string。


4.处理空参数

c

char *val = lr_eval_string("{optionalParam}");

if (val == NULL || strcmp(val, "") == 0) {

    // 空值处理

}


5.避免全局变量冲突

Action 文件中的全局变量在迭代间会保留,注意重置或用vuser_init初始化。

使用static限制作用域。


6.文件名和途径

文件操作时,相对途径指向脚本目录,可用 lr_get_attrib_string 获取绝对途径。


c

char scriptDir[1024];

lr_get_attrib_string("ScriptDir", scriptDir, sizeof(scriptDir));


七、错误处理和恢复

1.遇到错误继续执行


c

lr_continue_on_error(1);  // 后续步骤即便出错也继续

web_url("step1", ...);

lr_continue_on_error(0);  // 恢复默认


或通过 Run-time Settings - Miscellaneous - Continue on error 全局设置。


2.获取HTTP返回码


c

web_url("step", ...);

int httpCode = web_get_int_property(HTTP_INFO_RETURN_CODE);

if (httpCode != 200) {

    lr_end_transaction("T1", LR_FAIL);

}


3.手动结束脚本


c

lr_exit(LR_EXIT_ABORT, LR_FAIL);

7.4 事务状态赋值技巧

LR_AUTO:根据动作函数的返回状态自动判断。

LR_PASS / LR_FAIL:显式设定。

LR_STOP:非正常停止(如条件不满足时中止事务但不标记失败)。


八、性能优化和运行时设置

1.减少日志输出

在 Controller 运行时,必须关闭 Extended log,只保留标准日志,可大幅降低 I/O 开销。


2.设置合理思考时间

在 Run-time Settings 中可限制为录制值的 50%~150% 随机,或固定值。

不要在事务中包含过大或随机的思考时间,以免影响响应时间统计。


3.关联缓冲区大小

如果返回内容特别大,关联可能截断,需设置:


c

web_set_max_html_param_len("100000");


或使用 web_reg_save_param 的 MaxLength 属性。


4.少用 lr_output_message 在并发场景

高并发时大量打印会拖慢 Vuser,尽量用条件编译或仅在调试时启用。


5.DNS 缓存和连接复用

勾选 Simulate browser cache 和 Use persistent connections 可贴近真实浏览器行为,但需根据测试目的调整。

在 Run-time Settings → Internet Protocol 中设置。


九、高级脚本技术

1.文件读写自定义数据


c

FILE *f = fopen("output.txt", "a");

if (f) {

    fprintf(f, "User %s, Time: %ld\n", lr_eval_string("{user}"), time(NULL));

    fclose(f);

}


注意:多 Vuser 并发写同一文件需自行处理锁(如使用文件队列或 VTS)。


2.调用外部 DLL


c

lr_load_dll("myutils.dll");

// 声明函数

int __declspec(dllimport) Add(int a, int b);

// 调用

int result = Add(3,4);


3.使用Virtual Table Server

可在多 Vuser 间共享数据、同步唯一值,比文件操作更可靠。

函数:vtc_connect、vtc_send_row、vtc_retrieve_row 等。


4.数据库证实


c

lr_db_connect("StepName=DB1",

    "ConnectionString=...",

    "ConnectionName=conn1",

    LAST);

lr_db_executeSQLStatement("StepName=verify",

    "ConnectionName=conn1",

    "SQLStatement=SELECT count(*) FROM orders WHERE ...",

    "DatasetName=ds",

    LAST);


5.加密和编码

Base64 编解码:lr_base64_encode / lr_base64_decode

MD5/SHA:可加载 crypto DLL 或使用 lr_decrypt(用于负载脚本)。

对参数进行简单加密,提升数据安全性。


十、录制和回放设置

1.选择正确的脚本方式

HTML-based script:直观,适合页面元素确定的场景。

URL-based script:录制每个请求,更底层,适合非 HTML 应用或需精确控制资源下载的测试。


2.自动生成脚本后的清理

删除不必要的请求(如第三方统计、广告),保证压测结果准确。

合并无意义的额外 web_url,减少脚本大小。


3.端口映射和代理设置

使用 web_set_proxy 可动态设置代理。

web_set_sockets_option 设置超时等。


4.处理自定义Header


c

web_add_header("Authorization", "Bearer {token}");


十一、集合点和 IP 欺骗

1.集合点使用


c

lr_rendezvous("before_pay");

lr_start_transaction("pay");

// ...


在 Controller 的 Scenario - Rendezvous 中设置激活方法。

注意集合点应放在事务开始之前,否则会影响事务时间统计。


2.IP 欺骗

在 Controller 的 Scenario 中启用 IP Spoofer,并为每个 Vuser 分配不同 IP。

脚本无需改动,但需保证负载生成器支持 IP 别名。


文章标签: 软件测试 测试工具
热门标签 换一换
第三方软件国产化测试 第三方信创测试 CNAS软件测评报告 CMA软件测评报告 首版次软件认定 软件结题验收 软件测试报告书 软件质量检测 数据库测试 H5应用测试 软件质检机构 第三方质检机构 第三方权威质检机构 信创测评机构 信息技术应用创新测评机构 信创测试 软件信创测试 软件系统第三方测试 软件系统测试 软件测试标准 工业软件测试 软件应用性能测试 应用性能测试 可用性测试 软件可用性测试 软件可靠性测试 可靠性测试 系统应用测试 软件系统应用测试 软件应用测试 软件负载测试 API自动化测试 软件结题测试 软件结题测试报告 软件登记测试 软件登记测试报告 软件测试中心 第三方软件测试中心 应用测试 第三方应用测试 软件测试需求 软件检测报告定制 软件测试外包公司 第三方软件检测报告厂家 CMA资质 软件产品登记测试 软件产品登记 软件登记 CNAS资质 cma检测范围 cma检测报告 软件评审 软件项目评审 软件项目测试报告书 软件项目验收 软件质量测试报告书 软件项目验收测试 软件验收测试 软件测试机构 软件检验 软件检验检测 WEB应用测试 API接口测试 接口性能测试 第三方系统测试 第三方网站系统测试 数据库系统检测 第三方数据库检测 第三方数据库系统检测 第三方软件评估 课题认证 第三方课题认证 小程序测试 app测试 区块链业务逻辑 智能合约代码安全 区块链 区块链智能合约 软件数据库测试 第三方数据库测试 第三方软件数据库测试 软件第三方测试 软件第三方测试方案 软件测试报告内容 网站测试报告 网站测试总结报告 信息系统测试报告 信息系统评估报告 信息系统测评 语言模型安全 语言模型测试 软件报告书 软件测评报告书 第三方软件测评报告 检测报告厂家 软件检测报告厂家 第三方网站检测 第三方网站测评 第三方网站测试 检测报告 软件检测流程 软件检测报告 第三方软件检测 第三方软件检测机构 第三方检测机构 软件产品确认测试 软件功能性测试 功能性测试 软件崩溃 稳定性测试 API测试 API安全测试 网站测试测评 敏感数据泄露测试 敏感数据泄露 敏感数据泄露测试防护 课题软件交付 科研经费申请 软件网站系统竞赛 竞赛CMA资质补办通道 中学生软件网站系统CMA资质 大学生软件网站系统CMA资质 科研软件课题cma检测报告 科研软件课题cma检测 国家级科研软件CMA检测 科研软件课题 国家级科研软件 web测评 网站测试 网站测评 第三方软件验收公司 第三方软件验收 软件测试选题 软件测试课题是什么 软件测试课题研究报告 软件科研项目测评报告 软件科研项目测评内容 软件科研项目测评 长沙第三方软件测评中心 长沙第三方软件测评公司 长沙第三方软件测评机构 软件科研结项强制清单 软件课题验收 软件申报课题 数据脱敏 数据脱敏传输规范 远程测试实操指南 远程测试 易用性专业测试 软件易用性 政府企业软件采购验收 OA系统CMA软件测评 ERP系统CMA软件测评 CMA检测报告的法律价值 代码原创性 软件著作登记 软件著作权登记 教育APP备案 教育APP 信息化软件项目测评 信息化软件项目 校园软件项目验收标准 智慧软件项目 智慧校园软件项目 CSRF漏洞自动化测试 漏洞自动化测试 CSRF漏洞 反序列化漏洞测试 反序列化漏洞原理 反序列化漏洞 命令执行 命令注入 漏洞检测 文件上传漏洞 身份验证 出具CMA测试报告 cma资质认证 软件验收流程 软件招标文件 软件开发招标 卓码软件测评 WEB安全测试 漏洞挖掘 身份验证漏洞 测评网站并发压力 测评门户网站 Web软件测评 XSS跨站脚本 XSS跨站 C/S软件测评 B/S软件测评 渗透测试 网站安全 网络安全 WEB安全 并发压力测试 常见系统验收单 CRM系统验收 ERP系统验收 OA系统验收 软件项目招投 软件项目 软件投标 软件招标 软件验收 App兼容性测试 CNAS软件检测 CNAS软件检测资质 软件检测 软件检测排名 软件检测机构排名 Web安全测试 Web安全 Web兼容性测试 兼容性测试 web测试 黑盒测试 白盒测试 负载测试 软件易用性测试 软件测试用例 软件性能测试 科技项目验收测试 首版次软件 软件鉴定测试 软件渗透测试 软件安全测试 第三方软件测试报告 软件第三方测试报告 第三方软件测评机构 湖南软件测评公司 软件测评中心 软件第三方测试机构 软件安全测试报告 第三方软件测试公司 第三方软件测试机构 CMA软件测试 CNAS软件测试 第三方软件测试 移动app测试 软件确认测试 软件测评 第三方软件测评 软件测试公司 软件测试报告 跨浏览器测试 软件更新 行业资讯 软件测评机构 大数据测试 测试环境 网站优化 功能测试 APP测试 软件兼容测试 安全测评 第三方测试 测试工具 软件测试 验收测试 系统测试 测试外包 压力测试 测试平台 bug管理 性能测试 测试报告 测试框架 CNAS认可 CMA认证 自动化测试
专业测试,找专业团队,请联系我们!
咨询软件测试 400-607-0568