JMeter在ASP.Net 项目中的实现之 域登陆及POST方法的实现
Posted 埃森哲测试中心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JMeter在ASP.Net 项目中的实现之 域登陆及POST方法的实现相关的知识,希望对你有一定的参考价值。
背景
本项目由于是基于ASP.Net的程序设计,运用B/S架构,经讨论决定用JMeter对如下动作进行性能测试
员工的工时填写保存提交(实现POST Request)
工时Excel批量导入
Excel报告下载
本篇文章主要是分享如何在ASP.Net下实现POST Request。我的任务是探索一下JMeter对上述需求的可行性,抛开性能测试的细节不提,这些动作一定得在JMeter上能够模拟出来才行,要不然,什么并发,什么吞吐量,什么相应时间的,全都无法实现。
Q
系统登陆不是通过普通页面登陆,而是域登陆(弹出对话框登陆)。这就意味着无论什么抓包工具都无法捕捉登陆的HTTP Request,没有HTTP Request,JMeter也就无法模拟登陆。如何将那些被测服务都抓到?
Q
Badboy直接抓包的脚本无法在JMeter直接执行怎么办?
Q
由于系统采用ASP.Net,每一个HTTP Request的Post Body中都包含最新当前页面的信息(VIEW_STATE等7个参数),如果无法动态获得这些参数的信息,HTTP Request请求就无法成功怎么办?
1. 解决域登陆
JMeter提供了专有功能Add - > Config Element - >
HTTP Authorization Manager。其中: Base URL为被测的URL,http头不能缺少,里面不能有多余的空格。Username, Password, Domain正常填写,Realm默认为空,Mechanism默认就行,只需要将HTTP Authorization Manager添加并如下图更新。
2. 如何将那些被测服务都抓到?
我们可以通过Badboy自动抓包,或者是通过Fiddler提供信息手动抓包。下载并安装这两款软件。首先,我们先用Badboy自动抓包
第一步:打开Badboy,并将被测URL输入到指定框中,并点击旁边的绿色转至箭头,会自动出发录制过程
第二步:在右面出现的页面中正常操作,输入userName和password并点击登陆
第三步:录制结束后,点击停止录制。左侧栏生成的就是录制好的脚本
第四步:将该Script导出 Menu -> File -> Export to JMeter(就是图中Demo.jmx文件)
第五步:用JMeter打开该jmx文件,删掉那些多余的HTTP Request,改名就是下图的样子了
3. Badboy直接抓包的脚本无法在JMeter直接执行怎么办?
点击执行并右键Thread Group -> Add -> Listener -> View Result Tree添加并查看,之所以Response Code为401是因为401 - Unauthorized 访问被拒绝
根本原因:经调查,发现是因为Implementation值不正确,需要和开发确认,该系统的Implementation为HttpClient4,不是JAVA
解决方法:与开发确认类型,如果是HttpClient4,需要将所有服务的Implementation改为HttpClient4,
再次执行,有所改善,服务均返回200成功
4. ASP.Net中独有的页面信息(VIEW_STATE等属性)的获取
接着上面的章节讲,虽然表面表面上执行成功,但是实际上由于没有正确的VIEW_STATE等信息,实际上还是失败了。
参数是ASP.Net独有的,目前需要用在POST Body的参数如下:
EVENTTARGET
EVENTARGUMENT
LASTFOCUS
VIEWSTATE
VIEWSTATEGENERATOR
VIEWSTATEENCRYPTED
EVENTVALIDATION
这些参数每一个具体是干什么的身为自动化工程师我们是不需要细细去了解的,它就是记录页面上的内容, 而我们真正需要关心的是这些值是从哪里来的?
经调查得,POST服务的那这些属性值是从上一个服务,也就是PostHolidayPressAddButton中的输出得到的。这就是为什么我们需要保留这个PostHolidayPressAddButton。但是麻烦的是这个PostHolidayPressAddButton中的输入,还有这些参数,并且参数和输出的这些参数值不一样,那这些值是从哪里来的呢?这些只是从上一个GET请求GetHolidayPage的输出得到的。幸运的是这个请求只有输出,没有输入的POST body,所以我们终于找到源头了,这就是为什么我连Get服务也保留,正常的接口测试应该只保留被测接口一个,其他的不需要,可是谁让ASP.net特殊呢。这就好比探宝,先是通过第一个Get提示我们下一站在哪里,当我们到达下一站之后,在提示我们下一站在哪里,直到终点,它从不在开始的时候就告诉我们终点在哪里。
好了,既然知道了,VIEW属性的源头,我们如何提取这些值,并且参数化?
需要引入BeanShell脚本页(Add ->Sampler ->BeanShell Sampler),在上面写一些JAVA代码,将上一个HTTPRequest的Response中的值提取出来存入到JMeter变量中,并在接下来的HTTPRequest中使用该变量,已实现值的传递
上一个Request的Response如下:
第一段提取用的JAVA代码如下:
public static String getValueFromhtml(String str, String keyword){
String tempStr = "";
String strStart = "value=\"";
String strEnd = "\" />";
tempStr = str.substring(str.indexOf(keyword)+keyword.length(),str.length());
tempStr = tempStr.substring(tempStr.indexOf(strStart)+strStart.length(),tempStr.length());
return tempStr.substring(0, tempStr.indexOf(strEnd));
}
var strLoginPageResponseXML = prev.getResponseDataAsString();
vars.put("EVENTTARGET", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "EVENTTARGET")));
vars.put("EVENTARGUMENT", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "EVENTARGUMENT")));
vars.put("LASTFOCUS", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "LASTFOCUS")));
vars.put("VIEWSTATE", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "VIEWSTATE")));
vars.put("VIEWSTATEGENERATOR", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "VIEWSTATEGENERATOR")));
vars.put("VIEWSTATEENCRYPTED", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "VIEWSTATEENCRYPTED")));
vars.put("EVENTVALIDATION", java.net.URLEncoder.encode(getValueFromHTML(strLoginPageResponseXML, "EVENTVALIDATION")));
第一个POST Request的Response如下:
Response的格式不同,所以之前写的BeanShell JAVA代码不能复用,必须另行写一个,如下:
public static String getValue(String str, String keyword){
String tempStr = "";
String strSeparator = "|";
tempStr = str.substring(str.indexOf(keyword)+keyword.length()+1,str.length());
return tempStr.substring(0, tempStr.indexOf(strSeparator));
}
var strLoginPageResponseXML = prev.getResponseDataAsString();
vars.put("EVENTTARGET", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "EVENTTARGET")));
vars.put("EVENTARGUMENT", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "EVENTARGUMENT")));
vars.put("LASTFOCUS", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "LASTFOCUS")));
vars.put("VIEWSTATE", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "VIEWSTATE")));
vars.put("VIEWSTATEGENERATOR", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "VIEWSTATEGENERATOR")));
vars.put("VIEWSTATEENCRYPTED", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "VIEWSTATEENCRYPTED")));
vars.put("EVENTVALIDATION", java.net.URLEncoder.encode(getValue(strLoginPageResponseXML, "EVENTVALIDATION")));
由于我之前写的Java代码中有encode的功能,所以在下图中,取消勾选Encode,避免双重Encode。
变量被引用的形式为${变量名}
再次执行一下,成功插入数据了
最后让我们再总结一下本文分享的重要知识点
系统要求域登陆的话,使用JMeter的HTTP Authorization Manager实现登陆
在HTTP Request中Server Name or IP栏中不应该填写http或https等HTTP头
如果是HTTP,Port Number默认是80;如果是HTTPS,Port Number默认是443
Implementation是否为JAVA还是HttpClient4,需要与开发确认。可能Badboy自动抓包的值不正确
查看执行结果,需要创建结果树View Result Tree
ASP.Net的POST HTTP Request需要获得最新的页面信息(VIEWSTATE,EVENTVALIDATION等),这些信息需要从上一个服务的Response中获得,一直追溯到最近的GET服务为止。
通过XPATH提取器或自己写一段Java代码将Response的页面信息提取到JMeter变量中,以供以后的Request使用。
执行成功后,应该登陆系统确认服务是否真的执行成功
关于Excel文件上传批量导入和Excel文件下载的接口的实现,将在接下来的(二),(三)中呈现
埃森哲测试中心
分享一切关于测试的文章
以上是关于JMeter在ASP.Net 项目中的实现之 域登陆及POST方法的实现的主要内容,如果未能解决你的问题,请参考以下文章
ASP.Net / IIS 7.5 无法识别用于 OutputCache 的 jMeter
为啥我在使用 jmeter 时无法在 asp.net Web 应用程序中成功登录?