工作生活

Loadrunner性能测试(三):关联函数、检查点、事务、思考

2019-07-04  本文已影响0人  零下的雨

关联函数:

image.png

该函数的功能很强大:
1、用#代表任何数字

image.png
2、使用^代表通配符
image.png
3、获取匹配到的第几个值
image.png
4、找不到时报error还是报警,建议报警,这样程序还能继续执行
image.png
5、搜索范围,建议选择全部
image.png
6、类似 java中的substring方法,从第10个字符开始截取到第50个字符
image.png
7、忽略重定向
image.png

关联数组

要实现的一个需求是进入csdn首页,能够随机点击左侧导航栏进入到相应的栏目中。

image.png
比如进入程序人生:
image.png
链接是https://www.csdn.net/nav/career,每个栏目的域名相同,后面部分不同,要从首页的源码中查看每个栏目后面的部分信息,然后提取到一个数组中:
image.png

脚本已经录制完成,在脚本中添加步骤添加函数:


image.png

要给 引号加转义符


image.png
image.png

打印:
lr_output_message(lr_eval_string("{getitems}"));
因为是数组所以打印结果是:


image.png

打印出第二个:
lr_output_message(lr_eval_string("{getitems_2}"));


image.png
image.png

获取全部的值:

    //获取数组的长度的函数lr_paramarr_len("getitems")
    //lr_paramarr_idx("getitems",i)根据下标索引获取数组中的数据
    for(i=1;i<=lr_paramarr_len("getitems");i++){
        lr_output_message(lr_paramarr_idx("getitems",i));
    }

随机获取一个值

r_output_message(lr_paramarr_random("getitems"));

使用sprintf给一个变量赋值:

     //sprintf(myurlstring,"{getitems_%d}",i); 是把"{getitems_%d}"的值赋值给myurlstring,myurlstring是char数组,必须用数组才行要不然会报错,并打印出来
     for(i=1;i<=lr_paramarr_len("getitems");i++){
        sprintf(myurlstring,"{getitems_%d}",i);
        lr_output_message(lr_eval_string(myurlstring));
     }

//保存参数的函数lr_save_string(第一个参数是参数值,第二个参数是参数名称可以随意设置),这个参数testurl可以被下面的函数使用

    lr_save_string(lr_paramarr_random("getitems"),"testurl");
    lr_output_message(lr_eval_string("{testurl}"));

拼接参数并关联应用到下面的函数中

    //拼接要访问的url
    sprintf(askurlstring, "https://www.csdn.net%s", lr_paramarr_random("getitems"));
    lr_output_message(askurlstring);//打印变量查看变量有没有拼接成功
    //把拼接的url保存到一个变量中这样才能被下面的函数应用
    lr_save_string(askurlstring,"askurlstring");
    
    //访问拼接的url
        web_url("career", 
        "URL={askurlstring}", 
        "TargetFrame=", 
        "Resource=0", 
        "RecContentType=text/html", 
        "Referer=", 
        "Snapshot=t113.inf", 
        "Mode=HTML", 
        LAST);

下面的代码实现的是打开csdn的首页,然后随机选中一个栏目,再进入栏目中随机点击一篇文章。

Action_Allcode()
{
    //变量的声明必须放到前面,开始执行代码后不能声明变量
    
    //声明一个变量,必须放到首行这个位置才行
    int i;
    
    //声明一个char变量,用来存放拼接的URL地址
    char* urlstring="https://www.csdn.net";
    
    //声明一个长度为1024的char数组,下面没有用到
    char myurlstring[1024];
    //声明一个长度为1024的char数组,应用到下面的url中
    char askurlstring[1024];
    
    //声明一个char变量,用于存放栏目的名称
    char *askurltitle;
    

    web_set_sockets_option("SSL_VERSION", "TLS1.1");

    web_add_cookie("Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=6525*1*10_19814196820-1526528487575-539618; DOMAIN=www.csdn.net");

    web_add_cookie("uuid_tt_dd=10_19814196820-1526528487575-539618; DOMAIN=www.csdn.net");

    web_add_cookie("dc_tos=ptyfw6; DOMAIN=www.csdn.net");

    web_add_cookie("dc_session_id=10_1526528487575.516753; DOMAIN=www.csdn.net");

    web_add_cookie("Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1561970163; DOMAIN=www.csdn.net");

    web_add_cookie("TY_SESSION_ID=47e865f3-1857-4c8d-8791-ab14094f7f4f; DOMAIN=www.csdn.net");



    web_reg_save_param("getitems",
        "LB/ALNUMLC=<li class=\"\"><a href=\"",
        "RB=\">",
        "Ord=ALL",
        LAST);

    
    
//  web_reg_save_param_regexp(
//      "ParamName=getitems",
//      "RegExp= <li class=\"\"><a href=\"/nav/.*\">.*</a></li>",
//      "Group=0",
//      SEARCH_FILTERS,
//      LAST);
    
    

    web_url("www.csdn.net", 
        "URL=https://www.csdn.net/", 
        "TargetFrame=", 
        "Resource=0", 
        "RecContentType=text/html", 
        "Referer=", 
        "Snapshot=t109.inf", 
        "Mode=HTML", 
        EXTRARES, 
        "Url=/images/icon_close_big.png", ENDITEM, 
        "Url=/images/is_top_big.png", ENDITEM, 
        "Url=/favicon.ico", "Referer=", ENDITEM, 
        "Url=/images/icon_close_hover_big.png", ENDITEM, 
        LAST);
    
//  //打印出数组的第二个值,数组的下标是从1开始的,所以第二个是2
//      lr_output_message(lr_eval_string("{getitems_2}"));
//              
//      
//  //获取数组的长度的函数lr_paramarr_len("getitems")
//  //lr_paramarr_idx("getitems",i)根据下标索引获取数组中的数据
//  for(i=1;i<=lr_paramarr_len("getitems");i++){
//      lr_output_message(lr_paramarr_idx("getitems",i));
//  }
        
    
     //lr_paramarr_random("getitems")随机获取数组中的数据
//     lr_output_message(lr_paramarr_random("getitems"));
    
  
     
     
     //sprintf(myurlstring,"{getitems_%d}",i); 是把"{getitems_%d}"的值赋值给myurlstring,myurlstring是char数组,必须用数组才行要不然会报错,并打印出来
//     for(i=1;i<=lr_paramarr_len("getitems");i++){
//      sprintf(myurlstring,"{getitems_%d}",i);
//      lr_output_message(lr_eval_string(myurlstring));
//     }
    
    
    //保存参数的函数lr_save_string(第一个参数是参数值,第二个参数是参数名称可以随意设置),这个参数testurl可以被下面的函数使用
//    lr_save_string(lr_paramarr_random("getitems"),"testurl");
//    lr_output_message(lr_eval_string("{testurl}"));
    
     
    //拼接要访问的url
    sprintf(askurlstring, "https://www.csdn.net%s", lr_paramarr_random("getitems"));
    lr_output_message(askurlstring);//打印变量查看变量有没有拼接成功
    //把拼接的url保存到一个变量中这样才能被下面的函数应用
    lr_save_string(askurlstring,"askurlstring");
    
    //多次迭代web_url的名称都一样,本来想实现名称要根据点击的url变化,web_url的名称不能用变量参数
    //从字符串后面开始搜索'/',找到后直接截取包含'/'的后面的内容
    askurltitle=(char *)strrchr(askurlstring,'/');        
    lr_save_string(askurltitle,"askurltitlestring");//保存到askurltitlestring中并打印查看结果
    lr_output_message(lr_eval_string("{askurltitlestring}"));
    
    //添加一个关联参数,从随机进入的栏目返回的结果中获取文章url
        web_reg_save_param("articleurl",
        "LB=data-track-view='{\"mod\":\"popu_459\",\"con\":\",",
        "RB=,",
        "Ord=ALL",
        LAST);
    
    //访问拼接的url
        web_url("career", 
        "URL={askurlstring}", 
        "TargetFrame=", 
        "Resource=0", 
        "RecContentType=text/html", 
        "Referer=", 
        "Snapshot=t113.inf", 
        "Mode=HTML", 
        LAST);
    
    
    
//  //打印输出获取到的articleurl值
//  lr_output_message(lr_eval_string("{articleurl}"));
//  
//  //打印输出关联数组中的每一个值,并存到变量中
//  for(i=1;i<=lr_paramarr_len("articleurl");i++){
//      lr_output_message(lr_paramarr_idx("articleurl",i));
//  }
    
    
    //从访问的栏目url中随机取一个articleurl值并存到变量中
    lr_save_string(lr_paramarr_random("articleurl"),"articleurlstring");
    lr_output_message(lr_eval_string("{articleurlstring}"));
    
    
                      
    web_url("89089809", 
        "URL={articleurlstring}", 
        "TargetFrame=", 
        "Resource=0", 
        "RecContentType=text/html", 
        "Referer=https://www.csdn.net/nav/career", 
        "Snapshot=t118.inf", 
        "Mode=HTML", 
        EXTRARES, 
        "Url=https://www.csdn.net/favicon.ico", "Referer=", ENDITEM, 
        "Url=https://pagead2.googlesyndication.com/pagead/js/r20190626/r20190131/show_ads_impl.js", ENDITEM, 
        "Url=https://pagead2.googlesyndication.com/pub-config/r20160913/ca-pub-1076724771190722.js", ENDITEM, 
        "Url=https://www.googletagservices.com/activeview/js/current/osd.js?cb=%2Fr20100101", ENDITEM, 
        "Url=https://entry.baidu.com/rp/bwordcom?di=&user=&page_url=https%3A%2F%2Fblog.csdn.net%2FPx01Ih8%2Farticle%2Fdetails%2F89089809&logid=111&title=%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%AE%97%E6%B3%95%20-%20ConcurrentHashMap%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%20-%20%3Csdffdsfsdfdfs%3Esfsfsfsdfsdffds%3C%2FsdfsDS%3EFsd%20-%20CSDN%E5%8D%9A%E5%AE%A2&jsonp=baidu_bw_1562048038258", ENDITEM, 
        LAST);
    
    
    return 0;
}

loadrunner还有其他的关于字符串的函数没有用到,可以参考:
https://www.cnblogs.com/qmfsun/p/4900562.html

事务

统计每一个请求或者每一批请求的响应时间,评估系统的处理速度。
统计事务的成功率:评估系统的稳定性。
自动事务有两个选项:按每一个操作action为一个事务、按每一个步骤为一个事务


image.png

保存action,创建controller场景,运行查看按每一个action为一个事务的执行情况:


image.png

运行完毕,点击事务响应时间查看结果,显示最大值、最小值、平均值等信息:


image.png

再设置按每一个步骤为一个事务查看响应时间:


image.png

可以不勾选自动事务,也可以勾选,不冲突,手动设置事务:


image.png
image.png

手动定义三个事务,进入controller场景中运行查看事务响应时间:


image.png

在事务中写其他代码也会产生浪费时间,可以把这部分时间减去,代码如下:

Action_wastertime()
{
    
    double time_elapsed;//定义double类型的变量,用来存储时间
    merc_timer_handle_t timer;//定义timer 用来接收开始时间
    int i;//定义一个整型变量,可以做循环
    char b[50];//定义一个char数组,用来把double类型的时间转换成char类型,可以打印出来
    
    lr_start_transaction("testing");//开始事务
    
    web_url("www.baidu.com", 
        "URL=http://www.baidu.com/", 
        "TargetFrame=", 
        "Resource=0", 
        "RecContentType=text/html", 
        "Referer=", 
        "Snapshot=t1.inf", 
        "Mode=HTML", 
        EXTRARES, 
        "Url=/favicon.ico", "Referer=", ENDITEM, 
        LAST);


    
    timer=lr_start_timer();//开始计算时间
    
    for(i=0;i<1000;i++){
        lr_output_message("消耗时间");
    }
    
    time_elapsed=lr_end_timer(timer);//结束计算时间
    
    lr_wasted_time(time_elapsed*1000);//从毫秒换算成秒后加入浪费时间中
    
    lr_end_transaction("testing", LR_AUTO);//结束事务,事务会自动减去浪费时间

    
    sprintf(b,"%2f",time_elapsed);//把double类型的浪费时间变量转换成char类型数组,并赋值给b变量
    lr_save_string(b,"time_elapsedpara");//把变量转换成参数
    lr_output_message("浪费的时间是:%s",lr_eval_string("{time_elapsedpara}"));//打印浪费时间

    return 0;
}

检查点

loadrunner结束事务中的LR_AUTO只是通过状态码来区分事务是否成功,比如登录时密码错误,能正常返回界面告诉用户密码错误请重新输入密码,对loadrunner来说检测到服务器返回是200的状态码,所以检测到事务成功了,但是从业务角度来说并没有成功,所以需要通过检查点来判断事务是否真正的成功。

插入函数,函数要放到请求之前,可以按文本去查也可以按字符串去查:


image.png

根据统计次数大于等于1判断请求成功。


image.png

也可以使用函数自定义修改事务的状态:
lr_set_transaction_status_by_name(LR_FAIL,"protectcar");
lr_set_transaction_status_by_name(LR_PASS,"protectcar");

勾选和不勾选这个对注册检查点web_reg_find()函数无效。


image.png

思考时间

image.png
image.png

思考时间就是模拟用户暂停发请求的时间,为了让loadrunner模拟真实的场景,是需要使用思考时间的。


image.png
思考时间定为5秒,按最小值50%,最大值200%随机选取思考时间:
image.png

集合点01

集合点适用场景是并发测试,主要关注大用户量的并发。分为两种情况:1、所有用户都在并发请求,请求的模块可能是不同的 2、所有用户都在提交同一个请求。

集合点是不能模拟真实场景,至少不能很绝对的模拟,因为不可能达到绝对的并发,服务器接收到请求也是有先后顺序的,处理请求也是需要队列处理,所以达不到绝对意义的并发。

并发测试:相对严格的并发,并没有绝对严格的并发测试。并发测试属于压力测试的一个子集。

压力测试:关注系统最大的瓶颈是多少,系统在什么时候会发生崩溃,系统在什么样的场景下会发生崩溃。并发测试属于压力测试的一个子集。做压力测试时不需要设置思考时间,直接压测就行。

负载测试:评估性能指标,当系统有100个人、1000个人、10000个人访问的时候系统的处理情况是什么,cpu、内存、数据库等的表现是什么样的。

稳定性测试:系统在标准用户数、最佳状态下的长时间的一种运行,比如cpu利用率在70%~80%左右,资源充分利用并且还有上升的空间的一种状态。

系统的最大用户数:是指某一个指标出现极限时的一种状态,不可能所有指标都出现极限状态,比如内存到达极限,或者cpu到达极限等等。

容量测试:模拟系统长时间运行后的性能状态,目前流行的关系型数据库中都有自己的存储引擎,比如使用索引、关键字等可以很快速的查询出数据。比如查询1000条和查询1亿条时数据库的处理速度是什么样的,sql语句是否要优化等的测试。

集合点02

先创建一个事务,再创建一个集合点就会出现事务统计的时间不准确的情况,因为因为集合点是要等所有用户到达后统一去发起下一个请求,所以集合点中有一个等待的时间,暂停的时间是要统计到事务的时间中的,所以集合点不能放到事务里面要放到外面,这样事务统计的时间才准确。

模拟场景一:集合点放在事务里面,查看统计时间

image.png

每隔10秒会释放5个用户:


image.png

事务的响应时间:


image.png

模拟场景二:集合点放在事务外面,查看统计时间

image.png
前5秒先运行5个用户,其他用户等待状态:
image.png
到时间再释放5个
image.png
全部释放开始运行
image.png
事务响应时间:
可见最大时间比上一个场景的时间小,最后一个运行时间也变小了
image.png

模拟场景三:上两个场景持续运行时间太长,导致一些虚拟用户迭代失败,现在改成持续运行3分钟
可以看出后到集合点的用户已用时间短:

image.png

了解场景中的集合

image.png

每隔10秒释放5个用户,在场景中设置当运行的用户到达时就可以开始发出请求


image.png

第一个选项是说当所有的虚拟用户都到达时才发出请求,与设置的每隔10秒释放5个用户是有冲突的,这样每隔10秒释放5个用户,释放后用户要等待,等待所有的用户都被释放后才发出请求


image.png

vuser之间的超时值设置为10秒,是说当选中第一个选项时,在用户还没到达但是已经超时了就不再等待用户了,直接发出请求,这样不浪费时间


image.png

这个配置是说当有1个用户到达时就发出请求:


image.png

一般使用默认的配置就可以:


image.png

模拟场景四,设置等所有用户到达时才发起请求

image.png
不太明显。

函数总结:
lr_output_message(lr_eval_string("{参数名称}"))
打印结果是否获取成功
web_reg_save_param_ex()关联参数
web_reg_save_param()关联函数
lr_paramarr_len("getitems")获取数组的长度
lr_paramarr_idx("getitems",i)根据下标索引获取数组中的数据
lr_paramarr_random("getitems")随机获取数组中的数据
sprintf(myurlstring,"{getitems_%d}",i); 是把"{getitems_%d}"的值赋值给myurlstring,myurlstring是char数组,必须用数组才行要不然会报错
lr_save_string(lr_paramarr_random("getitems"),"testurl");//lr_save_string(第一个参数是参数值,第二个参数是参数名称可以随意设置)
web_reg_find检查点函数,要放到请求之前
lr_log_message("要打印的日志内容");
lr_get_attrib_string("在运行时设置中其他属性的参数名称")
web_custom_request()发送自定义请求,与web_url,web_sumbit_data()一样
web_add_header("content_type","application/json")增加请求头,如果接口中需要在header中传token,也可以用这个函数把token加到请求头中,因为token会随着登录的变化而变化,所以需要先使用关联函数获取到token然后再把token放到header中供下面的接口使用。
web_get_int_property(HTTP_INFO_RETURN_CODE)获取上一个请求的返回码,返回类型是int,可以赋值给变量,用于判断请求结果。
lr_load_dll("md5.dll");加载md5.dll 加密方法放到loadrunner的bin目录下,直接引用dll,然后就可以直接用他里面的加密方法了。测试中也可能是其他的加密方法,可以找开发要。
lr_convert_string_encoding()转换字符类型,下面会讲解具体使用方法。
web_reg_save_param_xpath()接口返回内容是xml时可以通过这个关联函数获取参数,查询路径是xpath路径
web_reg_save_param_xpath(
"ParamName=error_code",
"QueryString=/response/error_code",
SEARCH_FILTERS,
LAST);

事务相关函数
lr_start_transaction("testing");//开始事务
timer=lr_start_timer();//开始计算时间
//浪费时间的代码
time_elapsed=lr_end_timer(timer);//结束计算时间
lr_wasted_time(time_elapsed*1000);//从毫秒换算成秒后加入浪费时间中
lr_end_transaction("testing", LR_AUTO);//结束事务,事务会自动减去浪费时间

自定义事务状态函数:
lr_set_transaction_status_by_name(LR_FAIL,"protectcar");

补充函数总结:
lr_get_attrib_string("在运行时设置中其他属性的参数名称")

image.png
image.png

lr_continue_on_error(1);//出现错误继续执行
//中间可以放要执行的代码
lr_continue_on_error(0);//出现错误不继续执行,关闭开关,与运行时设置的遇到错误继续执行是一样的。

web_get_int_property(HTTP_INFO_RETURN_CODE)获取上一个请求的返回码

image.png

web_add_header();
登录成功后获取token,下面其他的接口都需要在header中添加token,所以在下面所有的接口前增加web_add_header增加token。

image.png

lr_convert_string_encoding("A", NULL, LR_ENC_UTF8, "stringInUnicode");
参数分别是sourceString,fromEncoding,toEncoding ,paramName
fromEncoding和toEncoding有三种:LR_ENC_SYSTEM_LOCALE 、LR_ENC_UTF8 、LR_ENC_UNICODE
该函数返回0是转换成功,返回-1是转换失败。
下图中是把参数转换字符类型,打印结果后面会带\x00

image.png
image.png
上一篇下一篇

猜你喜欢

热点阅读