JMeter预处理变量作为报告文件名的一部分

时间:2016-07-22 23:17:46

标签: sql variables jdbc jmeter

在我的测试计划中,我有JDBC PreProcessor,它捕获我试图保存到变量中的单个值。然后我想将此变量重用为摘要报告的文件名的一部分。

我想知道创建该变量的创建是否发生得太晚,因为我总是得到字面值logs/${session_id_1}-summary.cvs而不是logs/1234-summary.cvs

我也不确定是否需要使用resultVariablevariableNames来存储该值。到目前为止,我尝试了不同的组合,没有运气

那么我还不清楚我应该将预处理器连接到第一个采样器?

这是我最新的(短片)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>

2 个答案:

答案 0 :(得分:1)

在JMeter中不支持动态更改Listeners测试元素的文件名,因为在任何变量之前初始化了Listeners。推荐的方法是:

  1. 在JMeter之外获取您的Terradata会话ID ,即使用BTEQ或等效的
  2. 通过-J命令行参数将值传递给JMeter,如:

    jmeter -Jsession_id_1=1234 -n -t /path/to/testplan.jmx
    
  3. 通过__P()函数将会话ID值引用到

    ${__P(session_id_1,)}
    
  4. 如果由于任何原因你仍然需要在JMeter测试脚本中进行,这里有一个可能的解决方案,但请记住以下内容:

    1. 您需要从&#34;文件名&#34;中删除所有内容。输入摘要报告监听器。只是让它空白。
    2. 确保以下代码只执行一次且只有一个线程。
    3. 所以:

      1. 添加JSR223 PostProcessor作为query1采样器的子项,添加 Session PreProcessor
      2. 在&#34;语言&#34;中选择groovy;下拉
      3. 将以下代码放入JSR223 PostProcessor&#34; Script&#34;面积:

        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);
        
      4. 如果您正在使用JMeter 3.0,则会捆绑groovy。对于以前的JMeter版本,您需要手动安装groovy语言支持,请查看Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For!文章,了解groovy引擎安装说明和脚本最佳实践。

答案 1 :(得分:0)

您不能将变量用作摘要报告文件名的一部分,因为每个用户线程都存在一个变量,并且在初始化摘要报告之后。

改为使用属性: