JMeter预处理变量作为报告文件名的一部分 [英] JMeter pre-processed variable as part of report file name
问题描述
在我的测试计划中,我有JDBC PreProcessor,它捕获了我要保存到变量中的单个值.然后,我想将此变量作为摘要报告的文件名的一部分重用.
In my test plan I have JDBC PreProcessor that captures a single value that I'm trying to save into a variable. Then I want to reuse this variable as part of summary report's file name.
我想知道创建该变量是否为时已晚,因为我总是得到文字值logs/${session_id_1}-summary.cvs
而不是logs/1234-summary.cvs
I wonder if creating that creating that variable happens too late because I always get literal value logs/${session_id_1}-summary.cvs
rather than logs/1234-summary.cvs
我也不确定是否需要使用resultVariable
或variableNames
来存储值.到目前为止,我没有运气尝试过不同的组合
I'm also not sure if I need to use resultVariable
or variableNames
to store the value. So far I tried different combinations with no luck
然后我也不清楚应该在哪一点上将预处理器连接到第一个采样器?
Then I'm also not clear at which point I should attach the pre-processor, to the first sampler?
这是我最新的(简短)JMX版本:
Here's my latest (short) version of 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中实际上不支持动态更改侦听器测试元素的文件名,因为在任何变量之前 都已初始化了侦听器.推荐的方法是:
Changing filenames of Listeners test elements on the fly is not really supported in JMeter as Listeners are being initialized before any variables. The recommended way is:
- 在JMeter之外获取您的Terradata会话ID,即使用 BTEQ 或等效的
-
通过-J命令行参数将值传递给JMeter:
- Get your Terradata session id outside of JMeter, i.e. using BTEQ or equivalent
Pass the value to JMeter via -J command line argument like:
jmeter -Jsession_id_1=1234 -n -t /path/to/testplan.jmx
通过 __P()函数引用会话ID值,其中要求为
Refer the session id value via __P() function where required as
${__P(session_id_1,)}
如果出于任何原因仍然需要在JMeter测试脚本中执行此操作,则可以采用以下解决方案,但是请记住以下几点:
If for any reason you still need to do it inside JMeter test script, here is a possible solution, however keep in mind the following:
- 您需要从摘要报告"侦听器的文件名"输入中删除所有内容.只是让它空白.
- 确保以下代码仅一次执行且仅使用一个线程执行一次.
- You need to remove everything from "Filename" input of the Summary Report listener. Just let it be blank.
- Make sure that below code is executed only once and with only one thread.
所以:
- 将 JSR223 PostProcessor 添加为
query1
采样器和<在Session PreProcessor
之后
- 在语言"下拉列表中选择
groovy
-
将以下代码放入JSR223 PostProcessor脚本"区域:
- Add JSR223 PostProcessor as a child of the
query1
sampler and after theSession PreProcessor
- Select
groovy
in the "Language" drop-down Put the following code into JSR223 PostProcessor "Script" area:
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语言支持,请查看
If you're using JMeter 3.0 - groovy is bundled. For previous JMeter versions you will need to install groovy language support manually, check out Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! article for groovy engine installation instructions and scripting best practices.
这篇关于JMeter预处理变量作为报告文件名的一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!