
|----------------|
| 你好,我是安然无虞。 |
文章目录
- 常用函数
- lr语言编程
- 实战练习
-
- [实战1: 唯一序列](#实战1: 唯一序列)
- [实战2: 登陆脚本](#实战2: 登陆脚本)
- [实战3: 单查询脚本](#实战3: 单查询脚本)
- [实战4: 入库脚本](#实战4: 入库脚本)

常用函数
对于常用的函数, 我们要比较熟悉, 有不清楚的地方, 记得查询官网帮助, 以下是官网在线文档, 非常具有参考价值:
参数类函数
1.lr_eval_string
功能: 将参数转化为字符串.

用法示例:
c
Action()
{
lr_save_int(0, "searchCount");
lr_save_string("我是字符串", "str1");
lr_output_message("Is zero, %s", lr_eval_string("{str1}"));
if (atoi(lr_eval_string("{searchCount}") ) == 0) {
lr_output_message("Is zero, %s", lr_eval_string("{searchCount}"));
}
lr_save_int(47, "searchCount");
if (atoi(lr_eval_string("{searchCount}") ) != 0) {
lr_output_message("Not zero, %s", lr_eval_string("{searchCount}"));
}
return 0;
}
2.lr_eval_json
功能: 将字符串或者文件转换为Json对象.

用法示例:
c
TestEval()
{
char* json_input = "{"
"\"firstName\": \"John\","
"\"lastName\": \"Smith\","
"\"address\": {"
" \"streetAddress\":\"21 2nd Street\","
" \"city\":\"New York\","
" \"state\":\"NY\","
" \"postalCode\":\"10021\""
"}"
"}";
lr_save_string(json_input, "JSON_Input_Param");
// 创建json对象(通过字符串)
lr_eval_json("Buffer={JSON_Input_Param}",
"JsonObject=json_obj_1", LAST);
// 创建json对象(通过文件)
lr_eval_json("Buffer/File=store.json",
"JsonObject=json_obj_2", LAST);
// 修改json对象值
lr_json_set_values("JsonObject=json_obj_1", "Value=test1111111", "QueryString=$.firstName", "SelectAll=Yes", Last);
// 取得json对象值
lr_json_get_values("JsonObject=json_obj_1",
"ValueParam=test_result", "QueryString=$.firstName", Last);
// json对象转换成json字符串
lr_json_stringify("JsonObject=json_obj_1", "Format=compact", "OutputParam=Result", Last);
// 打印结果
lr_log_message("%s--%s", lr_eval_string("{test_result}"), lr_eval_string("{Result}"));
return 0;
}
3.lr_json_set_values
功能: 修改json对象中的值.
用法示例: 同上
4.lr_json_get_values
功能: 获取json对象中的值.
用法示例: 同上
5.lr_json_stringify
功能: 将json对象转换成json字符串.
用法示例: 同上
6.lr_save_string
功能: 将变量以字符串类型存入参数.

用法示例:
c
char str1[100] = "我是测试字符串";
lr_save_string(str1, "param1");
lr_log_message("%s", lr_eval_string("{param1}"));
7.lr_save_int
功能: 将变量以数字类型存入参数.

用法示例:
c
int n = 1314;
lr_save_int(n, "param1");
lr_log_message("%s", lr_eval_string("{param1}"));
8.lr_save_datetime
功能: 时间格式化, 精确到秒, 存入参数.

用法示例:
c
lr_save_datetime("%Y-%m-%d %H:%M:%S", TIME_NOW, "currDateTime");
lr_output_message(lr_eval_string("{currDateTime}"));
9.lr_save_timestamp
功能: 将时间戳存入到参数, 可精确到秒, 毫秒, 微秒.
用法示例:
c
// 以秒为单位
lr_save_timestamp("param", "DIGITS=10", LAST);
lr_output_message(lr_eval_string("{param}"));
//以毫秒为单位
lr_save_timestamp("param", LAST);
lr_output_message(lr_eval_string("{param}"));
//以微秒为单位
lr_save_timestamp("param", "DIGITS=16", LAST);
lr_output_message(lr_eval_string("{param}"));
输出示例:

10.web_save_timestamp_param
功能: 将时间戳存入到参数, 固定为毫秒.
用法示例:
c
web_save_timestamp_param("tStamp", LAST );//默认以毫秒为单位,将时间戳存入参数
lr_output_message(lr_eval_string("Timestamp: {tStamp}"));
11.lr_param_sprintf
功能: 格式话字符串, 类似 sprintf

用法示例:
c
int index = 56;
char* suffix = "txt";
// 底层采用 C语言 的 sprintf 函数
lr_param_sprintf ("LOG_NAME_PARAM", "log_%d.%s", index, suffix,100);
lr_output_message("The new file name is %s",lr_eval_string("{LOG_NAME_PARAM}"));
输出示例:

12.lr_convert_string_encoding
功能: 编码转换, 可防止中文乱码.

用法示例:
c
lr_convert_string_encoding("我是中文", LR_ENC_SYSTEM_LOCALE,LR_ENC_UTF8,"ReplyMessage");
检查关联类函数
该类函数一般放在 web actions 函数的前面.
1.web_reg_find
功能: 在行动函数前面搜索指定字符串, 默认找不到则失败.
用法示例:
c
// 搜索指定字符串
web_reg_find("Search=Body",
"Text=devt_token",
LAST);
// 搜索指定字符串(开始+结束)
web_reg_find("Search=Body",
"TextPfx=\"devt_token\":\"",
"TextSfx=\"",
LAST);
// 通配搜索
web_reg_find("Text/ALNUMLC=\"devt_toke^\"",
LAST);
web_custom_request("login.do_3",
"URL={host}/devt-service/api/login.do",
"Method=POST",
"Resource=0",
"RecContentType=application/json",
"Referer={host}/devt-web/",
"Snapshot=t290.inf",
"Mode=HTML",
"EncType=application/json",
"Body= {\"acctName\":\"admin\",\"acctPwd\":\"11111111\",\"typ e\":\"0\"}",
LAST);
2.web_reg_save_param
功能: 将动态数据注册到参数.
用法示例:
c
//从服务端返回中取得数据,支持双右边界
web_reg_save_param("devtToken",
"LB=\"devt_token\":\"",
"RB=\"",
LAST);
web_custom_request("login.do_3",
"URL={host}/devt-service/api/login.do",
"Method=POST",
"Resource=0",
"RecContentType=application/json",
"Referer={host}/devt-web/",
"Snapshot=t290.inf",
"Mode=HTML",
"EncType=application/json",
"Body= {\"acctName\":\"admin\",\"acctPwd\":\"11111111\",\"type\":\"0\"}",
LAST);
lr_log_message("取得数据为: %s", lr_eval_string("{devtToken}"));
3.web_reg_save_param_regexp
功能: 将动态数据注册到参数, 比 web_reg_save_param函数功能强大.
用法示例:
c
//从服务端返回中取得数据
web_reg_save_param_regexp(
"ParamName=devtToken",
"RegExp=(\"devt_token\":\".*?\")",
"Group=0",
SEARCH_FILTERS,
"Scope=BODY",
LAST);
web_custom_request("login.do_3",
"URL={host}/devt-service/api/login.do",
"Method=POST",
"Resource=0",
"RecContentType=application/json",
"Referer={host}/devt-web/",
"Snapshot=t290.inf",
"Mode=HTML",
"EncType=application/json",
"Body= {\"acctName\":\"admin\",\"acctPwd\":\"11111111\",\"type\":\"0\"}",LAST);
lr_log_message("取得 token 为:%s",lr_eval_string("{devtToken}"));
4.web_reg_save_param_json
功能: 以 json 方式解析动态数据并注册到参数 (要求数据为json格式).
用法示例:
c
//从服务端返回中取得数据
web_reg_save_param_json(
"ParamName=devtToken",
"QueryString=$..devt_token",
SEARCH_FILTERS,
"Scope=BODY",
LAST);
5.web_reg_save_param_xpath
功能: 以 xpath 方式解析动态数据并注册到参数 (要求数据为XML格式).
用法示例:
c
web_reg_save_param_xpath( "ParamName=CorrelationParameter", "QueryString=/LR_EXTENSION[1]/object[1]/object[1]/array[1]",
"DFEs=JsonXml",
"ReturnXML=Yes",
SEARCH_FILTERS,
"Scope=Body",
LAST);
6.web_reg_save_param_attrib
功能: 以 html 文档方式解析动态数据并注册到参数.
用法示例:
c
//<INPUT TYPE="HIDDEN" NAME="field1" VALUE="Usj3xEEneBBTcIi6IXNHBBaz7D7ytfDmmbgOKjVuc59C">
web_reg_save_param_attrib(
"ParamName=param1",
"TagName=input",
"Extract=value",
"Name=field1",
"Type=*",
SEARCH_FILTERS,
"IgnoreRedirections=No",
LAST);
日志类函数
1.lr_output_message
功能: 向日志文件、输出窗口和其他测试报告摘要发送消息.
用法示例:
c
lr_output_message("取得token为: %s", lr_eval_string("{devtToken}"));
2.lr_log_message
功能: 向日志文件发送消息.
用法示例:
c
lr_log_message("取得token为: %s", lr_eval_string("{devtToken}"));
3.lr_debug_message
功能: 向日志文件发送调试信息 (需要设置日志级别).
用法示例:
c
lr_debug_message((LR_MSG_CLASS_RESULT_DATA | LR_MSG_CLASS_PARAMETERS, lr_eval_string("1111{devtToken}"));
4.lr_error_message
功能: 向日志文件发送错误消息 (红色显示).
用法示例:
c
lr_error_message("取得token为: %s", lr_eval_string("{devtToken}");
行动类函数
1.web_rest
功能: 使用 HTTP 支持的任何方法发送 REST API 请求.
用法示例:
- 基本上录制脚本的时候都是以该函数生成, 可参考录制脚本中的样例或者官网说明.
c
//Get
web_rest("get all customers info",
"URL=http://myServer/customers?limit={limit}&offset= {offset}",
"Method=GET",
LAST);
//Put
web_rest("update customer info",
"URL=http://myServer/customers/{cust_id}",
"Method=PUT",
"ResType=JSON",
"Body={ \"address\":\"yyyy\", ... }",
LAST);
//Post
web_rest("create new customer",
"URL=http://myServer/customers/",
"Method=POST",
"ResType=JSON",
"Body = { \"name\":\"john\", \"address\":\"xxxx\", ... }", /* BodyFile for large content */
LAST);
//Delete
web_rest("delete customer",
"URL=http://www.example.com/customers/{cust_id}",
"Method=DELETE",
LAST);
2.web_custom_request
功能: 允许使用 HTTP 支持的任何方法创建自定义的HTTP请求.
用法示例: 同上类似
常用C函数
1.sprintf
功能: 格式话字符串.

用法示例:
c
char* param1="I am param1!";
char* param2="I am param2!";
int num1=123;
char dest[100];
sprintf(dest,"%s %s %d",param1,param2,num1);
lr_log_message(dest);
输出示例:

2.strcat
功能: 连接两个字符串.
用法示例:
c
char fullpath[1024];
char * filename = "logfile.txt";
strcpy(fullpath, "c:\\tmp");
strcat(fullpath, "\\");
strcat(fullpath, filename);
lr_output_message ("当前文件路径为 %s", fullpath);
输出示例:

3.strchr
功能: 查找第一次出现的字符.

用法示例:
c
char* string = "His Excellency the Duke of Exeter";
char* first_x, *last_x;
first_x = (char*)strchr(string, 'x');
lr_output_message ("第一次出现的字符 x: %s", first_x);
last_x = (char*)strrchr(string, 'x');
lr_output_message ("最后一次出现的字符 x: %s", last_x);
输出示例:

4.strcmp
功能: 比较两个字符串的字母顺序, 可用于判断是否相等.

5.strcpy
功能: 将一个字符串复制到另一个字符串(注意哦, 是复制不是在字符串末尾追加).
用法示例:
c
char fullpath[1024], * filename = "logfile.txt";
strcpy(fullpath, "c:\\tmp");
lr_output_message("fullpath after strcpy: %s", fullpath);
输出示例:

6.stricmp
功能: 对两个字符串进行不区分大小写的比较.
用法示例:
c
int result;
char tmp[20];
char string1[] = "The quick brown dog jumps over the lazy fox";
char string2[] = "The QUICK brown dog jumps over the lazy fox";
result = stricmp(string1, string2);
if (result > 0)
strcpy(tmp, "greater than");
else if (result < 0)
strcpy(tmp, "less than");
else
strcpy(tmp, "equal to");
lr_output_message ("strcmp: String 1 is %s string 2", tmp);
7.strlen
功能: 返回字符串的长度.
用法示例:
c
int is_digit, i = 0;
char* str = "1234567k89";
unsigned int len = strlen(str);
do {
if (i == len) {
lr_output_message ("No letters found in string");
return -1;
}
is_digit = isdigit(str[i++]);
}
while (is_digit);
lr_output_message ("The first letter appears in character %d of string", i);
8.strncat
功能: 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾, 直到 n 字符长度为止.
用法示例:
c
char src[50], dest[50];
strcpy(src, "This is source");
strcpy(dest, "This is destination");
strncat(dest, src, 5);
lr_log_message("最终的目标字符串: |%s|", dest);
9.strncmp
功能: 把 str1 和 str2 进行比较, 最多比较前 n 个字节.
用法示例:
c
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
ret = strncmp(str1, str2, 4);
if(ret < 0) {
lr_log_message("str1 小于 str2");
} else if(ret > 0) {
lr_log_message("str2 小于 str1");
} else {
lr_log_message("str1 等于 str2");
}
10.strncpy
功能: 把 src 所指向的字符串复制到 dest, 最多复制 n 个字符.
用法示例:
c
char src[40];
char dest[12];
memset(dest, '\0', sizeof(dest));
strcpy(src, "This is runoob.com");
strncpy(dest, src, 10);
lr_log_message("最终的目标字符串: %s\n", dest);
11.strnicmp
功能: 把 str1 和 str2 进行不区分大小写比较, 最多比较前 n 个字节.
用法示例:
c
int result;
char tmp[20];
char string1[] = "The quick brown dog jumps over the lazy fox";
char string2[] = "The quick brown DOG jumps over one lazy fox";
result = strnicmp( string1, string2 ,10);
if (result > 0)
strcpy(tmp, "greater than");
else if (result < 0)
strcpy(tmp, "less than");
else
strcpy(tmp, "equal to");
lr_output_message ("stricmp: String 1 is %s string 2", tmp);
12.strrchr
功能: 查找最后一次出现的字符.
用法示例:
c
char* string = "His Excellency the Duke of Exeter";
char* first_x, *last_x;
first_x = (char*)strchr(string, 'x');
lr_output_message ("第一次出现的字符 x: %s", first_x);
last_x = (char*)strrchr(string, 'x');
lr_output_message ("最后一次出现的字符 x: %s", last_x);
13.strspn
功能: 该函数返回一个 str1 中第一个 不在 str2 中出现的字符下标.
用法示例:
c
int len;
const char str1[] = "ABCDEFG019874";
const char str2[] = "ABCD";
len = strspn(str1, str2);
lr_log_message("初始段匹配长度 %d\n", len );
输出示例:

14.strstr
功能: 在字符串 str1 中查找第一次出现字符串 str2 的位置, 不包含终止符.
用法示例:
c
int offset;
char* position;
char* str = "The quick brown dog jumps over the lazy fox";
char* search_str = "dog";
position = (char*)strstr(str, search_str);
offset = (int)(position - str + 1);
lr_output_message ("The string \"%s\" was found at position %d", search_str, offset);
输出示例:

15.strtok
功能: 分解字符串 str 为一组字符串, delim 为分隔符.

用法示例:
c
char path[] = "c:\\microfocus\\lrun\\bin\\wlrun.exe";
char separators[] = ".\\";
char* token;
// Get the first token
token = (char*)strtok(path, separators);
if (!token) {
lr_output_message ("No tokens found in string!");
return( -1 );
}
// While valid tokens are returned
while (token != NULL ) {
lr_output_message ("%s", token );
// Get the next token
token = (char*)strtok(NULL, separators);
}
输出结果:

lr语言编程
1.基础语法
LoadRunner12 默认为C语言, 同时支持Java和JavaScript, 建议大家主要学习C语言, 毕竟性能最高.
所以这里的讲解均以 C语言为基础.
2.变量使用
LoadRunner中的变量 其实就是C语言中的变量, 不过有以下几点约束:
- 变量可以定义在.h头文件中
- 变量可以定义在Action函数外部
- 变量可以定义在Action开始的部分
- Action体内不可以定义变量, 会编译报错
代码示例:
c
int a1=0;
int a2=0;
char* p1;
char str2[]="string111111222";
Action()
{
lr_log_message("%s",&str2[5]);
p1=lr_eval_string("{param1}");
lr_log_message("%s",p1);
//int a3=0;//此处编译会报错
return 0;
}
3.参数操作
参数是LoadRunner中的一个概念.
参数可以认为是C语言中的一个全局变量, 我们在写脚本的时候, 要学会用参数化的思想去解决问题.
- 字符串参数类操作
c
char str1[]="str111";
//参数的取值
lr_log_message("%s",lr_eval_string("{param1}"));
lr_log_message("%s",lr_eval_string("{param2}"));
//参数的赋值
lr_save_string(str1,"param1");
lr_save_string("new param2","param2");
//参数的取值
lr_log_message("%s",lr_eval_string("{param1}"));
lr_log_message("%s",lr_eval_string("{param2}"));
- int参数类操作
c
//参数的取值
lr_log_message("%s",lr_eval_string("{param1}"));
lr_log_message("%s",lr_eval_string("{param2}"));
//参数的赋值
lr_save_int(11,"param1");
lr_save_int(22,"param2");
//参数的取值
lr_log_message("%s",lr_eval_string("{param1}"));
lr_log_message("%s",lr_eval_string("{param2}"));
4.参数变量互转
参数与变量相互转换, 注意参数统一格式为字符.
c
char str1[]="str111";
char format1[200]="";
int n1=0;
//参数转字符串变量
strcpy(str1, lr_eval_string("{param1}"));
lr_output_message("%s", str1);
//参数转数值变量(参数统一为字符,故先转 int)
n1=atoi(lr_eval_string("{param2}"));
lr_output_message("%d", n1);
//格式化参数
sprintf(format1,"%s---%d",str1,n1);
lr_log_message("%s",format1);
//参数转参数
lr_save_string(lr_eval_string("{param1}"),"param2");
5.逻辑控制
C语言中的顺序、分支、循环 同样适用于 LoadRunner.
C语言中的函数同样可以在 LoadRunner 中使用.
LR中的函数可以定义在Action外部, 也可以定义在.h头文件中.
c
void say(int flag){
if(flag==0){
lr_log_message("我是偶数");
}else{
lr_log_message("我是奇数");
}
}
Action() {
int i=0;
for(i=0;i<10;i++){
if(i%2==0){
say(0);
}else{
say(1);
}
}
return 0;
}
6.JavaScript脚本
在C语言的脚本中我们可以通过 web_js_run函数 来运行一些 JS脚本, 使用 JS语言 可以快速写出非常强大的语言.
举个小例子:
- 准备 js1.js (直接放在工作目录下)
javascript
function test1(){
return new Date().getTime();
}
function test2(a,b){
return a+b;
}
- 准备 js2.js (直接放在工作目录下)
javascript
function test3() {
var user = '{ "id": 1, "name": "longge1" }';
var tuser = JSON.parse(user);
return tuser.name;
}
- LR 主要脚本如下:
c
Action{
web_js_run("Code=test3()",
"ResultParam=jsVal",
SOURCES,"File=js1.js",
ENDITEM,"File=js2.js",
ENDITEM,
LAST);
lr_log_message("%s",lr_eval_string("{jsVal}"));
}
我们之前在录制脚本的时候, 选择的都是 C语言作为主体脚本, 其实JavaScript 也可以作为录制的主体脚本语言.
实战练习
实战1: 唯一序列
需求: 在一些场景压测时, 需要唯一序列号, 我们可以采用如下思路实现
思路: 让每一个 Vuser 的序列统一采用 VuserID+时间戳 (时间戳不重复)
过程数据模拟:

脚本:
c
char seq[20];
// 取唯一序列
char* GetSeq(){
// 先取第一个 Vuser 唯一前缀,保证不同线程之间不冲突
// start是内置参数UserID类型
char* start = lr_eval_string("{start}");
// 将毫秒级时间戳存入参数tamp中
web_save_timestamp_param("tamp",LAST);
// 保证线程内部不冲突
sleep(1);
// 注意哦这里不是数字相加, 而是字符串拼接
sprintf(seq,"%s%s",lr_eval_string(" {start}"),lr_eval_string("{tamp}"));
return seq;
}
Action()
{
int i=0;
for(i=0; i<100; i=i+1)
{
lr_log_message("%s",GetSeq());
}
return 0;
}
实战2: 登陆脚本
要求: 录制一套完整的脚本, 内容包括登陆动作:
- 登陆逻辑放置在 actions 里面
- 易变的常量实现参数化 (主机、用户名、密码、端口...)
- 登陆实现规则关联
- 登陆采用5个以上账号
首先, 录制登陆脚本:

然后将易变的常量实现参数化:
其中主机和端口因为是固定的, 所以可以设计成Custom自定义类型, 而这里要5个用户, 所以用户名和密码需要分别设计为File文件类型:


实现之后的脚本:

这里我们将其放到一个事务中, 并将动态数据注册到参数 devtToken 中, 用来检查是否登陆成功:

然后在最后判断事务是否正常退出:

实战3: 单查询脚本
要求: 录制一套完整的脚本, 内容包括至少一个单查询:
- 登陆放置在 init 里面, 退出放置在end, 核心逻辑放置在 actions 里面
- 易变的常量实现参数化 (主机、用户名、密码、端口...)
- 登陆实现规则关联
- 选择一个查询条件设计为20种以上组合
- 查询设置为一个事务, 并采用业务判断成功与否
登录功能和前面的类似, 这里的 qryText 是 File文件类参数, 里面的内容是 查询文本.
登录成功后需要为后续的请求添加请求头 Authorization, 所以需要使用 web_add_auto_header()函数.
这里我们虽然也使用了事务, 但是采用的是结果断言的方式: web_reg_find()函数, 判断请求是否成功, 所以这里的事务可以不用检查结果, 自动结束.

实战4: 入库脚本
要求: 录制一套完整的脚本, 内容包括一次提交动作:
- 登陆放置在 init 里面, 推出放置在 end, 核心逻辑放置在 actions 里面
- 易变的常量实现参数化 (主机、用户名、密码、端口...)
- 登陆实现规则关联
- 入库内容 (如发布消息) 采用自定义函数模拟生成
- 入库设置为一个事务, 并采用业务判断成功与否
其中自定义函数GetTitle()用于生成不同的标题, 并且以字符串文本的形式存入title参数中, 这样一来发布不同的消息请求 标题内容都是变化的:


|----------------------|
| 遇见安然遇见你,不负代码不负卿。 |
| 谢谢老铁的时间,咱们下篇再见~ |