jmeter二次开发-java实现HashTree中字段值参数化

       近期由于公司需求,需要开发一套性能测试平台,便于公司产品接口能够快速压测(面对使用人群:性能测试、QA、开发)。通过多次调研讨论,决定基于jmeter5.1.1进行开发

      下面代码(部分)主要实现功能:把测试场景下业务接口转换为jmeter可识别的HashTree。HashTree中包含以下元素:

  1. TestPlan(测试计划)
  2. ListedHashTree(测试线程组)
  3. CSVDataSet(CSV参数化数据设置)
  4. HTTPSamplerProxy(http采集器)
  5. LoopController(loop迭代器)
  6. ThreadGroup(线程组)
  7. ConstantTimer(固定定时器)
  8. SampleSaveConfiguration(样本保存配置)
  9. ResultCollector(结果收集)
  10. HeaderManager(请求头管理)
  11. ResponseAssertion(断言)
  12. Arguments(自定义变量)
package com.xx.xx.service;

import org.apache.jmeter.JMeter;
import org.apache.jmeter.assertions.ResponseAssertion;
import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.CSVDataSet;
import org.apache.jmeter.config.RandomVariableConfig;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.engine.JMeterEngineException;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.protocol.http.util.HTTPArgument;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.samplers.SampleSaveConfiguration;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.testelement.property.*;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.timers.ConstantTimer;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import org.jooq.DSLContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 根据任务ID,把关联测试场景下的业务接口信息转换为HashTree
 * @author by dujiajun
 * @date 2020/7/21.
 */
@Repository
@Service("ConvHashTreeService")
public class ConvHashTreeService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private DSLContext dslContext;
    @Autowired
    private ScenarioDao scenarioDao;
    private ParametricFileService parametricFileService = new ParametricFileService();
    private ParametricPojo parametricPojo ;
    private Task tabTask =Task.TASK;

    /**
     * 根据场景ID,把场景中包含的接口信息转换成jmeter可识别的HashTree
     * @param taskId 接口信息集
     */
    public ListedHashTree convHashTree(String taskId){
        StressTestUtils stressTestUtils=new StressTestUtils();
        Integer scenarioId=scenarioDao.getScenarioId(taskId);
        //根据场景ID获取对应的接口信息
        List scenarioInterfaceList = scenarioDao.getScenarioInterfaces(scenarioId);
        logger.info("****************接口信息查询完毕!******************");
        //根据场景ID获取对应的参数化文件
        List parametricList=parametricFileService.getParametricByScenarioID(scenarioId);
        logger.info("****************参数化文件信息查询完毕!******************");

        try {
            stressTestUtils.setJmeterProperties();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //创建hashTree
        ListedHashTree testHashTree= new ListedHashTree();
        //创建测试计划
        TestPlan testPlan= createTestPlan();
        //线程组hashTree
        ListedHashTree threadGroupHashTree=new ListedHashTree();
        //结果收集hashTree
        ListedHashTree hashTreeResultCollectorAndHeaderManager = new ListedHashTree();
        //http请求hashTree
        ListedHashTree hashTreeHTTPSamplerProxy = new ListedHashTree();

        //迭代读取CSV文件信息,并将CSV添加到testPlan树中
        for(ParametricPojo parametricPojo:parametricList){
            String paraStr=parametricPojo.getParametricFilePath()+
                    File.separator+parametricPojo.getParametricFileName();
            if(!paraStr.isEmpty()&¶Str!=null) {
                //添加CSV参数化文件
                CSVDataSet csvDataSet = parametricFileService.setParaFile(paraStr,parametricPojo);
                //在testPlan中添加CSV文件
                testHashTree.add(testPlan, csvDataSet);
            }else {
                logger.error("paraStr文件串为空,CSV文件获取失败!");
            }
        }

        //根据场景ID查询场景变量表中记录
        List scenarioVariableconfigList = scenarioDao.getScenarioVariableconfigs(scenarioId);

        //如果场景变量表中存在相应场景记录,则创建Arguments
        if(!scenarioVariableconfigList.isEmpty()&&scenarioVariableconfigList.size()>0){
            try {
                Arguments arguments=createArguments(scenarioId);
                testHashTree.add(testPlan,arguments);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("创建自定义变量失败!");
            }
        }

        /**
         *迭代读取场景ID中所包含的所有接口信息,并转换到HashTree中
         */
        for(ScenarioInterfacePojo sampleScenarioInterface:scenarioInterfaceList){
            //根据InterfaceId查询单条接口记录
            InterfacePojo sampleInterface=new InterfaceDao(dslContext.configuration()).
                    fetchOneById(sampleScenarioInterface.getInterfaceId());
            //创建http采集器
            HTTPSamplerProxy httpSamplerProxy=createHTTPSamplerProxy(sampleInterface);
            //创建loop迭代器
            LoopController loopController= createLoopController();
            //创建线程组
            ThreadGroup threadGroup=createThreadGroup(sampleScenarioInterface,sampleInterface);
            //threadGroup.setSamplerController(loopController);

            //在线程组中设置迭代器loopController
            threadGroup.setProperty(new TestElementProperty("ThreadGroup.main_controller",loopController));
            hashTreeResultCollectorAndHeaderManager.add(createResultCollector());
            hashTreeResultCollectorAndHeaderManager.add(createHeaderManager());//添加HeaderManager

            //在httpSamplerProxy中增加ResultCollectorAndHeaderManager
            hashTreeHTTPSamplerProxy.add(httpSamplerProxy,hashTreeResultCollectorAndHeaderManager);
            //在线程组hashTree中添加httpSamplerProxy
            threadGroupHashTree.add(threadGroup,httpSamplerProxy);

            //根据接口记录中Assertion字段是否为空,来判断是否创建断言
            if(sampleInterface.getAssertion()!=null&&sampleInterface.getAssertion().length()>0){
                //在线程组hashTree中添加段言responseAssertion
                ResponseAssertion responseAssertion=createResponeAssertion(sampleInterface);
                threadGroupHashTree.add(threadGroup,responseAssertion);
            }
            //创建接口脚本固定定时器(思考时间)
            if(sampleInterface.getThinkTime()>0){
                //在线程组hashTree中添加固定定时器
                ConstantTimer constantTimer=createConstantTimer(sampleInterface);
                threadGroupHashTree.add(threadGroup,constantTimer);
            }
            //testPlan中添加线程组hashTree
            testHashTree.add(testPlan,threadGroupHashTree);
        }
        return testHashTree;
    }

    /**
     * @param s 场景接口表
     * @param i 接口信息表
     * @return threadGroup 线程组
     */
    public static ThreadGroup createThreadGroup(ScenarioInterfacePojo s,InterfacePojo i){

        ThreadGroup threadGroup=new ThreadGroup();
        threadGroup.setName(i.getInterfaceName());
        threadGroup.setNumThreads(s.getThreads());
        threadGroup.setRampUp(0);
        threadGroup.setScheduler(true);
        threadGroup.setEnabled(true);
        threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR,"continue"));
        threadGroup.setDuration(s.getDuration());//线程组执行时长
        threadGroup.setDelay(s.getStartupDelay());
        threadGroup.setProperty(TestElement.TEST_CLASS,ThreadGroup.class.getName());
        threadGroup.setProperty(TestElement.GUI_CLASS,"ThreadGroupGui");
        threadGroup.setProperty(new BooleanProperty(TestElement.ENABLED,true));
        return threadGroup;
    }

    /**
     * 创建HTTP采样器
     * @param i  接口实体
     * @return httpSamplerProxy
     */
    public static HTTPSamplerProxy createHTTPSamplerProxy(InterfacePojo i){

        HTTPSamplerProxy httpSamplerProxy=new HTTPSamplerProxy();
        int method=i.getMethod();//http请求类型:1 get  2 post 3 put

        if(method==2){ //http请求类型为post
            Arguments sampleArguments=new Arguments();
            HTTPArgument httpArgument=new HTTPArgument();
            httpSamplerProxy.setPostBodyRaw(true);
           // httpArgument.setName(i.getInterfaceName());
            httpArgument.setValue(i.getBody());
            httpArgument.setAlwaysEncoded(false);
            httpArgument.setMetaData("=");
            //httpArgument.setProperty(new BooleanProperty("HTTPArgument.always_encode",false));
            //httpArgument.setProperty(new StringProperty("Argument.value",i.getBody()));
            //httpArgument.setProperty(new StringProperty("Argument.metadata","="));
            sampleArguments.setProperty(new TestElementProperty("Arguments.arguments",httpArgument));

            ArrayList list1 = new ArrayList<>();
            list1.add(new TestElementProperty("",httpArgument));
            sampleArguments.setProperty(new CollectionProperty("Arguments.arguments",list1));
            httpSamplerProxy.setProperty(new TestElementProperty("HTTPsampler.Arguments",sampleArguments));
            httpSamplerProxy.setMethod("POST");

        }else if(method==1){//http请求类型为get
            httpSamplerProxy.setMethod("GET");
        }

        httpSamplerProxy.setEnabled(true);//启用
        httpSamplerProxy.setDomain("${ip}");
        httpSamplerProxy.setPort(i.getPort());
        httpSamplerProxy.setPath(i.getPath());
        //httpSamplerProxy.setConnectTimeout("1000");
        httpSamplerProxy.setUseKeepAlive(true);
        httpSamplerProxy.setProtocol("http");
        httpSamplerProxy.setEnabled(true);
        httpSamplerProxy.setContentEncoding("utf-8");
        httpSamplerProxy.setFollowRedirects(true);
        httpSamplerProxy.setAutoRedirects(false);
        httpSamplerProxy.setUseKeepAlive(true);
        httpSamplerProxy.setDoMultipartPost(false);
        httpSamplerProxy.setEmbeddedUrlRE(null);
        httpSamplerProxy.setProperty(new StringProperty("TestElement.test_class",
                "org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy"));
        httpSamplerProxy.setProperty(new StringProperty("TestElement.gui_class",
                "org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui"));
        httpSamplerProxy.setProperty(new StringProperty("TestElement.name",i.getInterfaceName()));
        return  httpSamplerProxy;
    }

    /**
     * 创建测试计划
     * @return
     */
    public  TestPlan createTestPlan(){
        TestPlan testPlan=new TestPlan();//创建测试计划

        //测试计划属性初始化
        testPlan.setName("testPlan");
        testPlan.setEnabled(true);
        testPlan.setFunctionalMode(false);//设置功能模块
        testPlan.setTearDownOnShutdown(true);
        testPlan.setSerialized(false);//设置序列化
        testPlan.setProperty(TestElement.TEST_CLASS,TestPlan.class.getName());
        testPlan.setProperty(TestElement.GUI_CLASS,"TestPlanGui");
        testPlan.setProperty(new BooleanProperty(TestElement.ENABLED,true));
        testPlan.setProperty(new StringProperty("TestPlan.comments",""));
        testPlan.setProperty(new StringProperty("TestPlan.user_define_classpath",""));

        Arguments arguments=new Arguments();
        arguments.setName("User Defined Variables");
        arguments.setEnabled(true);
        arguments.setProperty(new StringProperty("TestElement.gui_class","ArgumentsPanel"));
        arguments.setProperty(new StringProperty("TestElement.test_class","Arguments"));
        testPlan.setProperty(new TestElementProperty("TestPlan.user_defined_variables",arguments));
        return testPlan;
    }

    /**
     * 创建SampleSaveConfiguration
     * @return
     */
    public static SampleSaveConfiguration createSampleSaveConfiguration(){
        SampleSaveConfiguration sampleSaveConfiguration=new SampleSaveConfiguration();
        sampleSaveConfiguration.setTime(true);
        sampleSaveConfiguration.setLatency(true);
        sampleSaveConfiguration.setTimestamp(true);
        sampleSaveConfiguration.setSuccess(true);
        sampleSaveConfiguration.setLabel(true);
        sampleSaveConfiguration.setCode(true);
        sampleSaveConfiguration.setMessage(true);
        sampleSaveConfiguration.setThreadName(true);
        sampleSaveConfiguration.setDataType(true);
        sampleSaveConfiguration.setEncoding(false);
        sampleSaveConfiguration.setAssertions(true);
        sampleSaveConfiguration.setSubresults(true);
        sampleSaveConfiguration.setResponseData(false);
        sampleSaveConfiguration.setSamplerData(false);
        sampleSaveConfiguration.setAsXml(false);
        sampleSaveConfiguration.setFieldNames(true);
        sampleSaveConfiguration.setResponseHeaders(false);
        sampleSaveConfiguration.setRequestHeaders(false);
        sampleSaveConfiguration.setAssertionResultsFailureMessage(true);
        sampleSaveConfiguration.setBytes(true);
        sampleSaveConfiguration.setSentBytes(true);
        sampleSaveConfiguration.setUrl(true);
        sampleSaveConfiguration.setThreadCounts(true);
        sampleSaveConfiguration.setIdleTime(true);
        sampleSaveConfiguration.setConnectTime(true);
        return sampleSaveConfiguration;
    }

    /**
     * 创建createResultCollector
     * @return
     */
    public static ResultCollector createResultCollector(){

        ResultCollector resultCollector=new ResultCollector();
        resultCollector.setProperty(new BooleanProperty("ResultCollector.error_logging",false));
        resultCollector.setProperty(new ObjectProperty("saveConfig",createSampleSaveConfiguration()));
        resultCollector.setProperty(new StringProperty("TestElement.gui_class",
                "org.apache.jmeter.visualizers.ViewResultsFullVisualizer"));
        resultCollector.setProperty(new StringProperty("TestElement.name","View Results Tree"));
        resultCollector.setProperty(new StringProperty("TestElement.enabled","true"));
        resultCollector.setProperty(new StringProperty("filename",""));
        return resultCollector;
    }

    /**
     * 创建循环控制器
     * @return
     */
    public static LoopController createLoopController(){
        LoopController loopController=new LoopController();
        loopController.setLoops(-1);
        loopController.setProperty(new BooleanProperty("LoopController.continue_forever",false));
        loopController.setProperty(new StringProperty("TestElement.gui_class",
                "org.apache.jmeter.control.gui.LoopControlPanel"));
        loopController.setProperty(new StringProperty("TestElement.test_class",
                "org.apache.jmeter.control.LoopController"));
        loopController.setProperty(new StringProperty("TestElement.name","Loop Controller"));
        loopController.setEnabled(true);
        loopController.setProperty(TestElement.TEST_CLASS,LoopController.class.getName());
        loopController.initialize();
        return loopController;
    }

    /**
     * 创建headerManager
     * @return
     */
    public static HeaderManager createHeaderManager(){
        HeaderManager headerManager=new HeaderManager();
        ArrayList list2 = new ArrayList<>();
        Header header = new Header();
        header.setProperty(new StringProperty("Header.name","Content-Type"));
        header.setProperty(new StringProperty("Header.value","application/json"));
        TestElementProperty HeaderElement = new TestElementProperty("",header);
        list2.add(HeaderElement);
        headerManager.setProperty(new CollectionProperty("HeaderManager.headers",list2));
        headerManager.setProperty(new StringProperty("TestElement.test_class",
                "org.apache.jmeter.protocol.http.control.HeaderManager"));
        headerManager.setProperty(new StringProperty("TestElement.name","HTTP Header Manager"));
        headerManager.setProperty(new StringProperty("TestElement.enabled","true"));
        headerManager.setProperty(new StringProperty("TestElement.gui_class",
                "org.apache.jmeter.protocol.http.gui.HeaderPanel"));
        return headerManager;
    }

    /**
     * 创建接口脚本断言
     * @return
     */
    public static ResponseAssertion createResponeAssertion(InterfacePojo i){
        ResponseAssertion r =  new ResponseAssertion();
        List stringPropertiesList=new ArrayList<>();
        stringPropertiesList.add(new StringProperty("-1394046923",i.getAssertion()));
        r.setProperty(new StringProperty("TestElement.gui_class","AssertionGui"));
        r.setProperty(new StringProperty("TestElement.test_class","ResponseAssertion"));
        r.setProperty(new StringProperty("TestElement.test_name","ResponseAssertion"));
        r.setProperty(new CollectionProperty("Asserion.test_strings",stringPropertiesList));
        r.setAssumeSuccess(false);
        r.setName(i.getInterfaceName());
        r.setProperty("Assertion.test_type",16);
        r.setProperty(new StringProperty("Assertion.custom_message",null));
        //对应jmeter中测试字段的"响应文本"属性
        r.setProperty(new StringProperty("Assertion.test_field","Assertion.response_data"));
        return r;
    }

    /**
     * 创建固定定时器
     * @param i
     * @return
     */
    public static ConstantTimer createConstantTimer(InterfacePojo i){
        ConstantTimer constantTimer=new ConstantTimer();
        constantTimer.setName("ThinkTime");
        constantTimer.setProperty(new StringProperty("TestElement.gui_class","ConstantTimerGui"));
        constantTimer.setProperty(new StringProperty("TestElement.test_class","ConstantTimer"));
        constantTimer.setEnabled(true);
        constantTimer.setDelay(i.getThinkTime().toString());
        return constantTimer;
    }

    /**
     * 创建随机变量(备用)
     * @param i
     * @return
     */
    public static RandomVariableConfig createRandomVariableConfig(Interface i){
        RandomVariableConfig randomVariableConfig=new RandomVariableConfig();
        return randomVariableConfig;
    }

    /**
     * 自定义变量设置
     * @param scenarioId
     * @return
     */
    public  Arguments createArguments(Integer scenarioId){
        Arguments arguments=new Arguments();
        arguments.setName("VariableConfig");
        arguments.setEnabled(true);
        arguments.setProperty(new StringProperty("TestElement.gui_class","ArgumentsPanel"));
        arguments.setProperty(new StringProperty("TestElement.test_class","Arguments"));
        ArrayList testElementPropertyArrayList = new ArrayList<>();

        //根据场景ID,读取场景变量表中的信息
        List scenarioVariableconfigList=scenarioDao.getScenarioVariableconfigs(scenarioId);

        //读取场景变量表中的数据,并赋值
        for(ScenarioVariableconfigPojo s:scenarioVariableconfigList){
            Argument argumentVar=new Argument();
            argumentVar.setName(s.getVariableName());
            argumentVar.setProperty(new StringProperty("Argument.name",s.getVariableName()));//变量名称
            argumentVar.setProperty(new StringProperty("Argument.value",s.getVariableValue()));//变量值
            argumentVar.setProperty(new StringProperty("Argument.metadata","="));
            testElementPropertyArrayList.add(new TestElementProperty(s.getVariableName(),argumentVar));
        }
        arguments.setProperty(new CollectionProperty("Arguments.arguments",testElementPropertyArrayList));
        return arguments;
    }

    /**
     * 测试类,用于测试新生成的hashTree
     * @param testHashTree
     */
    public  void testRuner(ListedHashTree testHashTree) throws FileNotFoundException, JMeterEngineException {
        StressTestUtils stressTestUtils=new StressTestUtils();
        LocalStandardJMeterEngine engine=new LocalStandardJMeterEngine();
        System.setProperty(JMeter.JMETER_NON_GUI,"true");
        //System.setProperty(JMeter.JMETER_NON_GUI,"flase");
        String path= ConvHashTreeService.class.getClassLoader().
                getResource("jmeter.properties").getPath();
        File jmeterPropertiesFile=new File(path);

        if(jmeterPropertiesFile.exists()){
            //JMeterUtils.loadJMeterProperties(jmeterPropertiesFile.getPath());
            stressTestUtils.setJmeterProperties();
            Summariser summariser=null;
            String summariserName=JMeterUtils.getPropDefault("summariser.name","summary");
            if(summariserName.length()>0){
                summariser=new Summariser(summariserName);
            }
            //把测试结果写到此文件中
            String logFile = "D:\\tools\\apache-jmeter-5.1.1\\bin\\test.jtl";
            ResultCollector resultCollector=new ResultCollector(summariser);
            resultCollector.setFilename(logFile);
            testHashTree.add(testHashTree.getArray(),resultCollector);
            engine.configure(testHashTree);
            engine.run();
        }
    }

    /**
     * 把HashTree转换为jmx文件,测试用
     * @param h
     * @throws IOException
     */
    public  void hashTree2Jmx(ListedHashTree h) throws IOException {
        StressTestUtils stressTestUtils=new StressTestUtils();
        stressTestUtils.setJmeterProperties();
        SaveService.loadProperties();
        SaveService.saveTree(h,new FileOutputStream("D:\\tools\\apache-jmeter-5.1.1\\bin\\test.jmx"));
    }

    /**
     * 把jmx文件转换为HashTree,测试用
     * @param filePath
     * @return
     * @throws IOException
     */
    public HashTree jmx2HashTree(String filePath) throws IOException {
        StressTestUtils stressTestUtils=new StressTestUtils();
        stressTestUtils.setJmeterProperties();
        SaveService.loadProperties();
        HashTree h=SaveService.loadTree(new File(filePath));
        return h;
    }

    /**
     * 测试类
     * @param args
     */
    public static void main(String[] args) throws IOException {
        ConvHashTreeService c = new ConvHashTreeService();
        ListedHashTree hashTree=c.convHashTree("1");
        //转换为jmx文件
        c.hashTree2Jmx(hashTree);
        c.testRuner(hashTree);//执行HashTree

        //HashTree h=c.jmx2HashTree("D:\\tools\\apache-jmeter-5.1.1\\bin\\test.jmx");//由jmx文件转换hashTree
        //HashTree h=c.jmx2HashTree("D:\\tools\\apache-jmeter-5.1.1\\bin\\upload_client_conf.json.jmx");//由jmx文件转换hashTree
        //upload_client_conf.json.jmx
        // c.testRuner((ListedHashTree)h);//执行HashTree
/*        ParametricFileService parametricFileService=new ParametricFileService();
        parametricFileService.testDownloadFile();*/
    }
}

个人整理不易,如转发请注明出处,谢谢! https://blog.csdn.net/junior77/article/details/107689940

你可能感兴趣的:(Jmeter,JAVA,java)