2012-09-03 15 views
4

在我的JMeter場景中,我正在測試SOAP Web服務。我將初始請求發送給webservice S1,然後使用它的響應來建立對S2的請求。 從S1的響應進來的形式:將無節點本身的xml節點內容提取到Jmeter中的變量中

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
<soap:Body> 
    <s:response xmlns:s="http://custom.namespace.com/namespace"> 
    ... 
     <s:responseDetails> 
      <s:detail1>some info</s:detail> 
      <s:detail2>another info<s:detail2> 
      ... 
     </s:responseDetails> 
    </s:response> 
</soap:Body> 
</soap:Envelope> 

我需要使用內部<s:responseDetails>一切建立請求,S2,但包裝不同的XML元素中:在請求而不是

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://custom.namespace.com/namespace"> 
<soap:Body> 
    <s:request> 
     <s:details> 
      <s:detail1>some info</s:detail> 
      <s:detail2>another info<s:detail2> 
      ... 
     </s:details> 
    </s:request> 
</soap:Body> 
</soap:Envelope> 

注元素<s:details><s:responseDetails>

我開始使用XPath提取希望用XPath表達式把一切都在<s:responseDetails>標籤到JMeter的變量:

  • //*[local-name()='responseDetails']/node() - 給我一組與<s:responseDetails>不同的孩子JMeter的變量,而我希望他們在一個變量
  • //*[local-name()='responseDetails'] - 給我的整個節點<s:responseDetails>,我不能因爲根標籤<s:responseDetails>,我需要<s:details>
取代的存在的使用

什麼是正確的表達得到一切內部<s:responseDetails>到變量,這樣我可以在以後使用

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://custom.namespace.com/namespace"> 
<soap:Body> 
    <s:request> 
     <s:details> 
      ${details} 
     </s:details> 
    </s:request> 
</soap:Body> 
</soap:Envelope> 

或者,也許有另一種方式來解決我的問題?

回答

4

執行以下操作:

1)添加的XPath提取像你一樣有:

  • 參考名稱:responseFragment
  • XPath query:// s:response/s:responseDetails
  • 使用命名空間=真

2)添加BeanShell的取樣器:

String fragment = vars.get("responseFragment"); 
// Improve this replacement by regexp to avoid side effects 
String newFragment = fragment.replace("responseDetails","details"); 
vars.put("modifiedFragment", newFragment); 

3)然後用:$ {modifiedFragment}

注意,BeanShell的採樣器將略有降低JMeter的表演,但它應該是合理的。

請注意,您可以使用常規基礎語言和外部文件中的腳本將JSR 223替換爲Beanshell採樣器。

使用JMeter> 2.7版本的性能將比beanshell解決方案更好,因爲新版本的JMeter引入了一種新的緩存機制,可以「編譯」Groovy腳本並使其與Java類幾乎一樣高效。

截至2012年9月3日,該機制可在JMeter Nightly build中找到。

JMeter的測試計劃例如:

<?xml version="1.0" encoding="UTF-8"?> 
<jmeterTestPlan version="1.2" properties="2.3" jmeter="2.8-SNAPSHOT.20120903"> 
    <hashTree> 
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" 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="User Defined Variables" enabled="true"> 
     <collectionProp name="Arguments.arguments"/> 
     </elementProp> 
     <stringProp name="TestPlan.user_define_classpath"></stringProp> 
    </TestPlan> 
    <hashTree> 
     <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true"> 
     <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> 
     <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="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">1346673693000</longProp> 
     <longProp name="ThreadGroup.end_time">1346673693000</longProp> 
     <boolProp name="ThreadGroup.scheduler">false</boolProp> 
     <stringProp name="ThreadGroup.duration"></stringProp> 
     <stringProp name="ThreadGroup.delay"></stringProp> 
     </ThreadGroup> 
     <hashTree> 
     <JavaSampler guiclass="JavaTestSamplerGui" testclass="JavaSampler" testname="Java Request" enabled="true"> 
      <elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true"> 
      <collectionProp name="Arguments.arguments"> 
       <elementProp name="Sleep_Time" elementType="Argument"> 
       <stringProp name="Argument.name">Sleep_Time</stringProp> 
       <stringProp name="Argument.value">100</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="Sleep_Mask" elementType="Argument"> 
       <stringProp name="Argument.name">Sleep_Mask</stringProp> 
       <stringProp name="Argument.value">0xFF</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="Label" elementType="Argument"> 
       <stringProp name="Argument.name">Label</stringProp> 
       <stringProp name="Argument.value">OK</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="ResponseCode" elementType="Argument"> 
       <stringProp name="Argument.name">ResponseCode</stringProp> 
       <stringProp name="Argument.value">200</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="ResponseMessage" elementType="Argument"> 
       <stringProp name="Argument.name">ResponseMessage</stringProp> 
       <stringProp name="Argument.value">200</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="Status" elementType="Argument"> 
       <stringProp name="Argument.name">Status</stringProp> 
       <stringProp name="Argument.value">OK</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="SamplerData" elementType="Argument"> 
       <stringProp name="Argument.name">SamplerData</stringProp> 
       <stringProp name="Argument.value"></stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
       <elementProp name="ResultData" elementType="Argument"> 
       <stringProp name="Argument.name">ResultData</stringProp> 
       <stringProp name="Argument.value">&lt;soap:Envelope xmlns:soap=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt; &lt;soap:Body&gt;  &lt;s:response xmlns:s=&quot;http://custom.namespace.com/namespace&quot;&gt;   &lt;s:responseDetails&gt;    &lt;s:detail1&gt;some info&lt;/s:detail1&gt;    &lt;s:detail2&gt;another info&lt;/s:detail2&gt;   &lt;/s:responseDetails&gt;  &lt;/s:response&gt; &lt;/soap:Body&gt; &lt;/soap:Envelope&gt;</stringProp> 
       <stringProp name="Argument.metadata">=</stringProp> 
       </elementProp> 
      </collectionProp> 
      </elementProp> 
      <stringProp name="classname">org.apache.jmeter.protocol.java.test.JavaTest</stringProp> 
     </JavaSampler> 
     <hashTree> 
      <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor" enabled="true"> 
      <stringProp name="XPathExtractor.default"></stringProp> 
      <stringProp name="XPathExtractor.refname">TOTO</stringProp> 
      <stringProp name="XPathExtractor.xpathQuery">//s:response/s:responseDetails</stringProp> 
      <boolProp name="XPathExtractor.validate">false</boolProp> 
      <boolProp name="XPathExtractor.tolerant">false</boolProp> 
      <boolProp name="XPathExtractor.namespace">true</boolProp> 
      <boolProp name="XPathExtractor.whitespace">true</boolProp> 
      </XPathExtractor> 
      <hashTree/> 
     </hashTree> 
     <DebugSampler guiclass="TestBeanGUI" testclass="DebugSampler" testname="Debug Sampler" enabled="true"> 
      <boolProp name="displayJMeterProperties">false</boolProp> 
      <boolProp name="displayJMeterVariables">true</boolProp> 
      <boolProp name="displaySystemProperties">false</boolProp> 
     </DebugSampler> 
     <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>false</message> 
       <threadName>true</threadName> 
       <dataType>false</dataType> 
       <encoding>false</encoding> 
       <assertions>true</assertions> 
       <subresults>false</subresults> 
       <responseData>false</responseData> 
       <samplerData>false</samplerData> 
       <xml>false</xml> 
       <fieldNames>false</fieldNames> 
       <responseHeaders>false</responseHeaders> 
       <requestHeaders>false</requestHeaders> 
       <responseDataOnError>false</responseDataOnError> 
       <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> 
       <assertionsResultsToSave>0</assertionsResultsToSave> 
       <bytes>true</bytes> 
       <hostname>true</hostname> 
       <threadCounts>true</threadCounts> 
       <sampleCount>true</sampleCount> 
      </value> 
      </objProp> 
      <stringProp name="filename"></stringProp> 
     </ResultCollector> 
     <hashTree/> 
     </hashTree> 
    </hashTree> 
    </hashTree> 
</jmeterTestPlan> 

的另一種方式:

1)添加的XPath提取像你一樣有:

  • 參考名稱:responseFragment
  • XPath查詢: // s:response/s:responseDetails/*
  • 使用namespaces = true

2)添加BeanShell的取樣器:

int number = Integer.parseInt(vars.get("fullAnswer_matchNr")); 
StringBuilder builder = new StringBuilder(); 
for(int i=0;i<number;i++) { 
    builder.append(vars.get("fullAnswer_"+(i+1))); 
} 
vars.put("body", builder.toString()); 

3)用身體

這一個是乾淨了一點,因爲沒有更換

+0

我是BeanShell Sampler的新手,我想問一下:如果我將在負載測試中使用BeanShell,會帶來任何問題scenari o有很多線程? –

+0

我更新了我的答案。 –

+0

謝謝你這個偉大的答案!我必須花一些時間來實現解決方案,然後才能接受答案 –

0

你能忽略<s:details>標籤併發送這樣的請求:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://custom.namespace.com/namespace"> 
<soap:Body> 
    <s:request> 
     ${details} 
    </s:request> 
</soap:Body> 
</soap:Envelope> 
+0

我不能發送時,因爲請求詳細信息應該包含在''中,並且作爲響應,它們被封裝在'' –