为了从grinder繁琐的script里解脱出来,决定压力测试平台改用JMeter。
以测试一个seam login功能为例。基本步骤如下
1. 自动为threadgroup生成request sampler
首先在workbench中加入http proxy server并开启,改browser设置通过http proxy server并访问测试网站的登入页面,之后输入测试账号登入。这时JMeter自动抓取requests,包括对其他resource例如图片,js等的request.这里我们只关心两个requests.一个是开启页面的,第二个是登入时的。所以保留这两个requests,其他统统删除。这个也可以通过在http proxy server中加exlusive filter来完成。
2.自动获取viewId
JSF让人火大的一个地方就是它隐藏在代码中的viewId, 在JSF1.2里,request中viewId不对立即会引发view can not be restored exception。而viewId在session里又是时常改变的。解决的方法是创造一个extractor,在每次request后parse 相应,分析出里面的viewId,具体实现可参考http://rfeest.blogspot.com/2008/02/jmeter-und-jsf.html
3.增加cookie manager
在threadgroup里添加http cookie manager来保持sessionId
这里是完整的testplan,因为request sampler是用proxy产生的,所以非常的冗长
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.1">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Testplan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="Benutzer definierte Variablen" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread-Gruppe" enabled="true">
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Schleifen-Controller (Loop Controller)" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<longProp name="ThreadGroup.start_time">1234863597000</longProp>
<longProp name="ThreadGroup.end_time">1234863597000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
<collectionProp name="CookieManager.cookies"/>
<boolProp name="CookieManager.clearEachIteration">false</boolProp>
</CookieManager>
<hashTree/>
<OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Once Only Controller" enabled="true"/>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="/sd4/home.seam" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">ws029</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding">ISO-8859-1</stringProp>
<stringProp name="HTTPSampler.path">/sd4/home.seam</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
</HTTPSampler>
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Browser-derived headers" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="Host" elementType="Header">
<stringProp name="Header.name">Host</stringProp>
<stringProp name="Header.value">ws029:8080</stringProp>
</elementProp>
<elementProp name="Accept-Language" elementType="Header">
<stringProp name="Header.name">Accept-Language</stringProp>
<stringProp name="Header.value">de</stringProp>
</elementProp>
<elementProp name="Accept" elementType="Header">
<stringProp name="Header.name">Accept</stringProp>
<stringProp name="Header.value">*/*</stringProp>
</elementProp>
<elementProp name="User-Agent" elementType="Header">
<stringProp name="Header.name">User-Agent</stringProp>
<stringProp name="Header.value">Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)</stringProp>
</elementProp>
<elementProp name="Accept-Encoding" elementType="Header">
<stringProp name="Header.name">Accept-Encoding</stringProp>
<stringProp name="Header.value">gzip, deflate</stringProp>
</elementProp>
<elementProp name="UA-CPU" elementType="Header">
<stringProp name="Header.name">UA-CPU</stringProp>
<stringProp name="Header.value">x86</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
<hashTree/>
</hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="/sd4/home.seam" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="notloggedin:j_id113" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">true</boolProp>
<stringProp name="Argument.name">notloggedin:j_id113</stringProp>
<stringProp name="Argument.value">notloggedin:j_id113</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
</elementProp>
<elementProp name="notloggedin:j_id113:j_id117" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">true</boolProp>
<stringProp name="Argument.name">notloggedin:j_id113:j_id117</stringProp>
<stringProp name="Argument.value">gu</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
</elementProp>
<elementProp name="notloggedin:j_id113:j_id119" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">true</boolProp>
<stringProp name="Argument.name">notloggedin:j_id113:j_id119</stringProp>
<stringProp name="Argument.value">test</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
</elementProp>
<elementProp name="notloggedin:j_id113:j_id121" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">true</boolProp>
<stringProp name="Argument.name">notloggedin:j_id113:j_id121</stringProp>
<stringProp name="Argument.value">Anmelden</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
</elementProp>
<elementProp name="javax.faces.ViewState" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.name">javax.faces.ViewState</stringProp>
<stringProp name="Argument.value">${jsfViewState}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain">ws029</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding">ISO-8859-1</stringProp>
<stringProp name="HTTPSampler.path">/sd4/home.seam</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
</HTTPSampler>
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Browser-derived headers" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="Content-Type" elementType="Header">
<stringProp name="Header.name">Content-Type</stringProp>
<stringProp name="Header.value">application/x-www-form-urlencoded</stringProp>
</elementProp>
<elementProp name="Host" elementType="Header">
<stringProp name="Header.name">Host</stringProp>
<stringProp name="Header.value">ws029:8080</stringProp>
</elementProp>
<elementProp name="Accept-Language" elementType="Header">
<stringProp name="Header.name">Accept-Language</stringProp>
<stringProp name="Header.value">de</stringProp>
</elementProp>
<elementProp name="Accept" elementType="Header">
<stringProp name="Header.name">Accept</stringProp>
<stringProp name="Header.value">image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/x-silverlight, */*</stringProp>
</elementProp>
<elementProp name="User-Agent" elementType="Header">
<stringProp name="Header.name">User-Agent</stringProp>
<stringProp name="Header.value">Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)</stringProp>
</elementProp>
<elementProp name="Accept-Encoding" elementType="Header">
<stringProp name="Header.name">Accept-Encoding</stringProp>
<stringProp name="Header.value">gzip, deflate</stringProp>
</elementProp>
<elementProp name="Referer" elementType="Header">
<stringProp name="Header.name">Referer</stringProp>
<stringProp name="Header.value">http://ws029:8080/sd4/home.seam</stringProp>
</elementProp>
<elementProp name="UA-CPU" elementType="Header">
<stringProp name="Header.name">UA-CPU</stringProp>
<stringProp name="Header.value">x86</stringProp>
</elementProp>
<elementProp name="Pragma" elementType="Header">
<stringProp name="Header.name">Pragma</stringProp>
<stringProp name="Header.value">no-cache</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
<hashTree/>
</hashTree>
</hashTree>
<ResultCollector guiclass="GraphVisualizer" testclass="ResultCollector" testname="Graph Results" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>true</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
<stringProp name="RegexExtractor.refname">jsfViewState</stringProp>
<stringProp name="RegexExtractor.regex"><input type="hidden" name="javax\.faces\.ViewState" id="javax\.faces\.ViewState" value="(.+?)" /></stringProp>
<stringProp name="RegexExtractor.template">$1$</stringProp>
<stringProp name="RegexExtractor.default"></stringProp>
<stringProp name="RegexExtractor.match_number">0</stringProp>
</RegexExtractor>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>true</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
本文介绍如何使用JMeter进行Seam登录功能的压力测试。主要包括:利用HTTP Proxy Server自动捕获请求;通过正则表达式提取器自动获取viewId;以及添加HTTP Cookie Manager来维护会话状态。
387

被折叠的 条评论
为什么被折叠?



