最近小猴子正在研究LoadRunner,这款工具虽然可以录制脚本,非常方便,但也支持手写脚本。虽然在手写脚本的过程中磕磕绊绊,但也有些收获,小记下来方便日后回顾,希望也能帮助到正在学习的你,如有错误欢迎指教。
如何完成接口自动化测试。
大致思路是:从参数化文件中读取测试数据和预期结果,并与服务器产生交互,得到服务器返回后与预期结果对比,将结果写入HTML报告中。
思路清晰后,就开始编写代码了,这里使用LoadRunner自带的飞机订票系统的登录接口进行测试。
步骤一:初始化的工作可以放在vuser_init()中,先创建测试结果文件,如代码清单1-1所示。
//定义全局变量,可以在Vuser_action(),Vuser_end()中使用
long file;
char t_result[1024];
int num;
vuser_init()
{ //首先创建测试结果文件
//获取系统时间
lr_save_datetime("%Y%m%d%H%M%S",DATE_NOW,"now_date");
//拼接测试结果文件名称
strcpy(t_result,"D:\\reportTest");
strcat(t_result,lr_eval_string("\\{now_date}"));
strcat(t_result,"report.html");
lr_log_message("文件路径%s",lr_eval_string(t_result));
//生成并打开测试结果文件
file = fopen(t_result,"at+");//at+ 打开或建立一个文本文件,允许读或在文件末写入数据
//在没有手动在D盘中创建reportTest文件夹的时候,下面代码始终报错,手动在D盘中创建文件夹后,脚本执行成功,文件创建成功
if (file == NULL) {
lr_error_message("创建 %s 文件失败", t_result);
return -1;
}else{
lr_log_message("创建%s文件成功", t_result);
}
//写入测试文件头部html信息
strcpy(t_result,"<html><table border=‘1’><tr><td>描述</td><td>预期结果</td><td>实际结果</td><td>Y/N</td></tr>");
//int fputs(const char *str,FILE *file)str表示需要写入文件的字符串,file表示需要写入的文件流
num=fputs(t_result,file);
//下面的判断是进行调试看是否写入成功的,调试通后,可以删除,并将上行代码替换成fputs(t_result,file);
lr_output_message("%d",num);
if(num==0){
lr_log_message("写入文件:%s","成功");
}else{
lr_log_message("写入文件:%s","失败");
}
return 0;
}
步骤二:处理和服务器的交互以及判断需要在Action中编写代码,如代码清单1-2所示。
Action()
{ //登录接口功能自动化
char is_pass[1024]; //存储测试结果状态
int result; //定义预期值与实际值的比较结果
char *para=lr_eval_string ("登录接口");//这里后期测试多个接口,可以使用参数化取值lr_eval_string("{参数名}")
web_set_max_html_param_len("20000");
//关联参数,获取userSession <input type="hidden" name="userSession" value="141291.997650871HczHHAHpVcQVzzzHtDzAzpctcHHf"/>
web_reg_save_param("userSession","LB=\"userSession\" value=\"","RB=\"",LAST);
//开始手写脚本时,只写了执行登录的步骤,这样根本获取不到userSession的值,后来经过检查,发现该链接是获取userSession的关键链接,若无下方的方法,获取不到userSession的值(因为在http://127.0.0.1:1080/cgi-bin/nav.pl?in=home请求下找到userSession的值)
web_url("welcome.pl",
"URL=http://127.0.0.1:1080/cgi-bin/nav.pl?in=home",
"TargetFrame=",
"Resource=0",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/cgi-bin/welcome.pl?signOff=1",
"Mode=HTML",
LAST);
// 取得服务器返回请求状态state或者获取返回页面中的标题, 这里获取登录成功后,服务器返回HTML中的用户名<b>jojo</b>,
web_reg_save_param("actualResult","LB=<b>","RB=</b>","Search=All",LAST);
//发送请求
web_submit_data("login",
"Action=http://127.0.0.1:1080/cgi-bin/login.pl",
"Method=POST",
"TargetFrame=body",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/cgi-bin/nav.pl?in=home",
"Mode=HTML",
ITEMDATA,
"Name=userSession", "Value={userSession}", ENDITEM,
"Name=username", "Value=jojo", ENDITEM, //后期可对该值进行参数化
"Name=password", "Value=bean", ENDITEM, //bean,后期课对密码进行参数化,与用户名一一对应
"Name=login.x", "Value=51", ENDITEM,
"Name=login.y", "Value=15", ENDITEM,
"Name=JSFormSubmit", "Value=off", ENDITEM,
LAST);
web_submit_data("login.pl",
"Action=http://127.0.0.1:1080/cgi-bin/login.pl?intro=true",
"Method=GET",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/cgi-bin/login.pl",
"Mode=HTML",
ITEMDATA,
"Name=intro", "Value=ture", ENDITEM,
LAST);
//这里是调试使用,查看实际结果是否取到值,期望值是做了参数化操作,在参数化时设置好期望的数据
lr_log_message("实际结果%s",lr_eval_string("{actualResult}"));
lr_log_message("期望结果%s",lr_eval_string("{expectedResult}"));
//比较预结果和实际结果 strcmp(str1,str2)用于比较两个字符串并根据比较结果返回整数,若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数
result=strcmp(lr_eval_string("{expectedResult}"),lr_eval_string("{actualResult}"));
if(result==0){
strcpy(is_pass,"通过");
}else{
strcpy(is_pass,"失败");
}
//写入测试描述
strcpy(t_result,"<tr><td>");
strcat(t_result,para);
strcat(t_result,"</td>");
//写入预期结果
strcat(t_result,"<td id='yq'>");
strcat(t_result,lr_eval_string("{expectedResult}"));
strcat(t_result,"</td>");
//写入实际结果
strcat(t_result,"<td id='sj'>");
strcat(t_result,lr_eval_string("{actualResult}"));
strcat(t_result,"</td>");
//写入是否通过
strcat(t_result,"<td>");
strcat(t_result,is_pass);
strcat(t_result,"</td></tr>");
num=fputs(t_result,file);
//下面的判断是进行调试看是否写入成功的,调试通后,可以删除,并将上行代码替换成fputs(t_result,file);
if(num==0){
lr_log_message("登录接口结果写入成功");
}else{
lr_log_message("登录接口结果写入失败");
}
return 0;
}
步骤三:最后不要忘记处理一些关闭和清理工作,在vuser_end中完成,代码入1-3所示。
vuser_end()
{
//结束测试
strcpy(t_result,"</tale></html>");
fputs(t_result,file);
if(fclose(file)){
lr_error_message("文件%s关闭失败",t_result);
}
return 0;
}
步骤四:至此代码已经写完了,现在可以点击运行了。
查看文档结果:
调试以上脚本,小猴子遇到了好几个问题:
1、创建测试结果文件,创建不成功,原因是我自己在D盘中创建结果集的时候,未创建文件夹reportTest,后续执行找不到这个文件夹,导致创建文件失败。
2、获取不到实际结果值,经过检查的时候发现web_reg_save_param()使用错误,左右边界未定义正确,导致获取不到数值。
3、strcmp(lr_eval_string("{expectedResult}"),lr_eval_string("{actualResult}"))单独打印出来的值是相同,但是使用strcmp(),函数比较的时候,始终不相等,经过检查发现写脚本的时候粗心多写了{}导致的,去除{}后,问题完美解决。
strcmp()函数用法:
比较预结果和实际结果 strcmp(str1,str2)用于比较两个字符串并根据比较结果返回整数,若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。
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";
// Case-sensitive comparison
result = strcmp( string1, string2);
if(result > 0)
strcpy(tmp, "greater than");
else if(result < 0)
strcpy(tmp, "less than");
else
strcpy(tmp, "equal to");