|
最近有时间系统的测试一下自己写的代码,一直听说loadrunner效果不错,可是web测试的利器。不过远听不如自己用,什么东西别人说的好未必好,必须有自己的咀嚼和吸收。在这里记录一下我用loadrunner测试我的Nginx服务的过程。
估计说到loadrunner,很多人第一个头大的就是这个东东体积太大,Loadrunner11的体积更是达到了4GB!而且安装复杂,界面看的更容易让人头晕,无数的表和曲线,还有是不是冒出的各种按钮。。
说实话,第一次搞这个,我也很头大。不过经历了一些痛苦的过程,总结出来的东西,发现Loadrunner对于C++开发者来说,简直是绝配!为什么这么说?因为它的脚本就是C语言的,这对于经常写C或者C++的人来说绝不陌生,甚至手到擒来。
Loadrunner其实对于测试者而言,需要关注的只有几点。
1.我每秒事务提交数,成功了多少,失败了多少?
2.我的所有成功事务中,平均响应时间是多少?
3.在并行测试下,我的QPS曲线是一个怎样的态势?
那么,作为应用而言,千差万别,每个URL都可以不一样。如果想得到我需要的测试结果,必须写一些脚本,Loadrunner会自动加载它,关于Loadrunner的安装配置,这里不做过多叙述,百度就有。只是在这里说明一下,loadrunner如果你想压高用户并发,必须破解,在这里,loadrunner还是很厚道的,11下可以用8.5的破解方法。建议你安装的时候直接破解掉,推荐11。不过11只能在win7下运行。如果要运行在xp下,还是用9比较稳妥一些。
好了废话少说,让我们来看一个简单的loadruner的例子。
- Action()
- { lr_start_transaction("freeeyes的第一次"); web_custom_request("request2", "Method=POST", "URL=www.163.com", "RecContentType=application/json", "EncType=application/json", "Body={"name":"{freeeyes来看你啦}"}", LAST); }
复制代码
呵呵,这就是我最早的脚本,这里我来简单解释一下。
所有的loadrunner脚本启动函数都是Action(),你可以把它想象成C++里面的main(),简单吧。
lr_start_transaction这个API是必须的,说明一个事务,在Loadrunner中,事务代表的是一次操作。这里给你的当前事务一个名称,用于区别其它的事务脚本。
web_custom_request在干什么?这就是一个标准的URL请求,我向163http服务器post一条信息,那么我们来看看这些参数是干什么用的。
"request2" 你的URL请求的别名,这个你可以随便起你喜欢的。只是标一下这个URL是啥,张三李四王二麻子等等。
"Method=POST" 这个我指定POST方法,当然,你用"Method=GET"我也没意见。
"URL=www.163.com" 恩,实际的URL地址,这个地球人都知道。
"RecContentType=application/json" 指定内容格式是json的,这里不太懂的,可以去读读http1.1语法。
"EncType=application/json" 同上
"Body={\"name\":\"{自由之眼来看你啦}\"}" 这是我的post数据,格式是json的。
LAST 这是loadruner必须的,不解释。(实际上到现在我也不知道为啥必须写这个,呵呵,姑且就当是一个常量吧)
好了,以上测试脚本就完成了,简单吧,用loadrunner跑一下。
流程如下:
"工具"->"创建场景"->"选择创建并行用户数"->"路径选择你的这个脚本所在地址"->"结果设置"->"设置保存地址"
于是我很邪恶的把并行用户选择成了1000个。。
打开测试,咦?不到5秒就发现了网易开始拒绝我的服务了,我的IP在半小时内不能访问网易。。。杯具了。。更邪恶的网易。。。哈哈。
好了,以上我们就完成了一次完整的测试,测试报告保存后缀是irr。如果你觉得还不过瘾,想时不时拿出来看看,点击这个文件即可。这个文件可以生成当时测试的所有报表。至于报表的含义,以后慢慢讲,今天的目的是如何写出好的测试用例。
好了,看似很美妙,可是,遗憾的是这种简单的写法可不能满足我的要求。
我想要追加一些http的消息头,怎么做呢?- lr_start_transaction("freeeyes的第二次");
- web_add_header("devID","ASEY-1651-5648-A649-FREEEYES");
- web_add_header("ver","100");
- web_custom_request("request2", "Method=POST", "URL=www.163.com", "RecContentType=application/json", "EncType=application/json", "Body={"name":"{freeeyes又来看你啦}"}", LAST);
复制代码
web_add_header()是给你的发送头文件,添加相应的http头。这个很实用,比如,有些web服务器需要你提交请求的时候,包含自己的设备号码(devID)和版本号(ver)。你可以如此做。
那么好,继续,如果我想接收从服务器返回的结果,在做分析,怎么做呢?来看一下以下的代码- lr_start_transaction("freeeyes的第三次");
- web_add_header("devID","ASEY-1651-5648-A649-FREEEYES");
- web_add_header("ver","100");
- web_reg_find("Search=Body",
- "SaveCount=Bodycount",
- "Text=status":-1",
- LAST);
- web_custom_request("request2", "Method=POST", "URL=www.163.com", "RecContentType=application/json", "EncType=application/json", "Body={"name":"{freeeyes又来看你啦}"}", LAST);
- if(strcmp(lr_eval_string("{count1}"),"1") != 0){ lr_end_transaction("freeeyes的第三次", LR_PASS);}else{ lr_end_transaction("freeeyes的第三次", LR_FAIL);}
复制代码 这里又有了新的函数 web_reg_find()
这个函数是用来干什么的呢?这个函数的意思是在指定的缓冲中查找数值。具体如下:
web_reg_find("Search=Body", //定义查找范围
"SaveCount=Bodycount", //定义查找计数器变量名称
"Text=status\":-1", //定义查找内容
LAST);
这句话的意思就是说,我在服务器返回的结果中,查找指定字符串,如果找到了,则loadrunner会把Bodycount这个变量计数器+1。通过这种方法,我们可以确定从服务器返回的数据中,是否包含我们感兴趣的字符,如果有,则证明成功之(LR_PASS)。否则,算事务不成功(LR_FAIL)。
恩,那么也许你会说,如果我想让我的数据有参数配置,比如URL变为参数,从我指定的一个文本闻不见中去读,有方法吗?
方法肯定是有的,在loadrunner中,我可以选择一个配置文件,在配置文件中把列和我的参数绑定即可。
比如:- web_custom_request("request2", "Method=POST", "URL={URL}", "RecContentType=application/json", "EncType=application/json", "Body={"name":"{freeeyes又来看你啦}"}", LAST);
复制代码
{URL}就是我的这个变量,我在选择脚本的时候,选择绑定我的哪个文件,对列的读取,可以是随机的,也可以是顺序的。
当然,loadrunner也支持函数,比如,我可以把这段代码放在一个函数里面,让Action调用。- int login(){ lr_rendezvous("Login");
- lr_start_transaction("登录");
- web_add_header("cmd","1010"); web_add_header("devID","FREEEYES"); web_add_header("ver","100");
- web_reg_find("Search=Headers", "SaveCount=count", "Text=status: 0", LAST);
- web_custom_request("request", "Method=POST", "URL={URL}", "RecContentType=application/json", "EncType=application/json", "Body={"login":"{login}","pass":"{pass}"}", LAST);
- if(strcmp(lr_eval_string("{count}"),"1") == 0) { lr_end_transaction("登录", LR_PASS); return 1; } else { lr_end_transaction("登录", LR_FAIL); lr_error_message("login:%s\nerror:%s",lr_eval_string("{login}"),lr_eval_string("{code}")); return 0; }}
- Action(){ login()}
复制代码
这样,你就可以在一个action里面封装多次请求,并可以添加自己的逻辑。
另外,loadrunner也支持简单的C++语法,比如:- int i = 1;
- time(&timenow); //获取当前时间
- now = (struct tm *)localtime(&timenow); //把当前时间的结构指针赋值给now
- a = now->hour;//获取hour值
- b = now->minute;//获取minute值
- c = now->month + 1;
- d = now->day;
复制代码
类似这样的代码,在loadrunner下是完全可以运行的。
呵呵,好了,今天先讲到这里,有兴趣的话,下次写一点关于图表分析的内容。呵呵,抛砖引玉吧。 |
|