在我的测试计划中,我有JDBC PreProcessor,它捕获了我要保存到变量中的单个值。然后,我想将此变量作为摘要报告的文件名的一部分重用。
我不知道创建该变量是否为时已晚,因为我总是得到字面值logs/${session_id_1}-summary.cvs而不是logs/1234-summary.cvs
logs/${session_id_1}-summary.cvs
logs/1234-summary.cvs
我也不确定是否需要使用resultVariable或variableNames存储值。到目前为止,我没有运气尝试了不同的组合
resultVariable
variableNames
然后我也不清楚应该在哪一点上将预处理器连接到第一个采样器?
这是我最新的(简短)JMX版本:
<?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properties="2.9" jmeter="3.0 r1743807"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="TPCDS Benchmark Test Plan TPG Flavor" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> <boolProp name="TestPlan.functional_mode">true</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="JDBC Users" 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">1370729701000</longProp> <longProp name="ThreadGroup.end_time">1370729701000</longProp> <boolProp name="ThreadGroup.scheduler">false</boolProp> <stringProp name="ThreadGroup.duration"></stringProp> <stringProp name="ThreadGroup.delay"></stringProp> </ThreadGroup> <hashTree> <JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC_Configuration_tpcds" enabled="true"> <boolProp name="autocommit">true</boolProp> <stringProp name="checkQuery">Select 1</stringProp> <stringProp name="connectionAge">5000</stringProp> <stringProp name="dataSource">jdbcConfig_tpcds</stringProp> <stringProp name="dbUrl">jdbc:teradata://${TDPID}/database=tpcds</stringProp> <stringProp name="driver">com.teradata.jdbc.TeraDriver</stringProp> <boolProp name="keepAlive">true</boolProp> <stringProp name="password">tpcds</stringProp> <stringProp name="poolMax">10</stringProp> <stringProp name="timeout">10000</stringProp> <stringProp name="transactionIsolation">DEFAULT</stringProp> <stringProp name="trimInterval">60000</stringProp> <stringProp name="username">tpcds</stringProp> </JDBCDataSource> <hashTree/> <Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"> <elementProp name="TDPID" elementType="Argument"> <stringProp name="Argument.name">TDPID</stringProp> <stringProp name="Argument.value">${__P(target_dbs)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="DBC_USERNAME" elementType="Argument"> <stringProp name="Argument.name">DBC_USERNAME</stringProp> <stringProp name="Argument.value">${__P(dbc_username,dbc)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="DBC_PASSWORD" elementType="Argument"> <stringProp name="Argument.name">DBC_PASSWORD</stringProp> <stringProp name="Argument.value">${__P(dbc_password,dbc)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> </Arguments> <hashTree/> <JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="query1" enabled="true"> <stringProp name="dataSource">jdbcConfig_tpcds</stringProp> <stringProp name="query">${__FileToString(sql/query1.sql)}</stringProp> <stringProp name="queryArguments"></stringProp> <stringProp name="queryArgumentsTypes"></stringProp> <stringProp name="queryType">Select Statement</stringProp> <stringProp name="resultVariable"></stringProp> <stringProp name="variableNames"></stringProp> <stringProp name="queryTimeout"></stringProp> <stringProp name="resultSetHandler">Store as String</stringProp> </JDBCSampler> <hashTree> <JDBCPreProcessor guiclass="TestBeanGUI" testclass="JDBCPreProcessor" testname="Session PreProcessor" enabled="true"> <stringProp name="dataSource">jdbcConfig_tpcds</stringProp> <stringProp name="query">SELECT SESSION as session_id;</stringProp> <stringProp name="queryArguments"></stringProp> <stringProp name="queryArgumentsTypes"></stringProp> <stringProp name="queryTimeout"></stringProp> <stringProp name="queryType">Select Statement</stringProp> <stringProp name="resultSetHandler">Store as String</stringProp> <stringProp name="resultVariable">session_id</stringProp> <stringProp name="variableNames">session_id</stringProp> </JDBCPreProcessor> <hashTree/> </hashTree> <ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" 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>false</assertions> <subresults>false</subresults> <responseData>true</responseData> <samplerData>false</samplerData> <xml>true</xml> <fieldNames>true</fieldNames> <responseHeaders>false</responseHeaders> <requestHeaders>false</requestHeaders> <responseDataOnError>false</responseDataOnError> <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> <threadCounts>true</threadCounts> <idleTime>true</idleTime> <connectTime>true</connectTime> </value> </objProp> <stringProp name="filename">logs/${session_id_1}-summary.xml</stringProp> </ResultCollector> <hashTree/> </hashTree> </hashTree> </hashTree> </jmeterTestPlan>
JMeter并不真正支持即时更改侦听器测试元素的文件名,因为侦听器会 在 任何变量 之前 初始化。推荐的方式是:
通过-J命令行参数将值传递给JMeter,例如:
jmeter -Jsession_id_1=1234 -n -t /path/to/testplan.jmx
在需要时通过__P()函数引用会话ID值
${__P(session_id_1,)}
如果出于任何原因您仍然需要在JMeter测试脚本中执行此操作,则可以使用以下解决方案,但是请记住以下几点:
所以:
query1
Session PreProcessor
groovy
将以下代码放入JSR223 PostProcessor“脚本”区域:
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.reporters.ResultCollector; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.SearchByClass;
import java.lang.reflect.Field; import java.lang.reflect.Method;
StandardJMeterEngine engine = ctx.getEngine(); Field test = engine.getClass().getDeclaredField(“test”); test.setAccessible(true); HashTree testPlanTree = (HashTree) test.get(engine);
SearchByClass summaryReportsSearch = new SearchByClass(ResultCollector.class); testPlanTree.traverse(summaryReportsSearch); Collection summaryReports = summaryReportsSearch.getSearchResults(); ResultCollector summaryReport = summaryReports.iterator().next();
Class [] fileNameParam = new Class[1]; fileNameParam[0] = String.class;
Method setFileName = summaryReport.getClass().getDeclaredMethod(“setFilenameProperty”, fileNameParam); setFileName.setAccessible(true); setFileName.invoke(summaryReport, new String(vars.get(“session_id_1”)));
Method init = summaryReport.getClass().getDeclaredMethod(“initializeFileOutput”); init.setAccessible(true); init.invoke(summaryReport);
如果您使用的是JMeter 3.0,则将groovy捆绑在一起。对于以前的JMeter版本,您将需要手动安装Groovy语言支持,请查看Beanshell,JSR223和Java JMeter脚本:您一直在等待的性能!有关groovy引擎安装说明和脚本编写最佳实践的文章。