近期由于公司需求,需要开发一套性能测试平台,便于公司产品接口能够快速压测(面对使用人群:性能测试、QA、开发)。通过多次调研讨论,决定基于jmeter5.1.1进行开发。
下面代码(部分)主要实现功能:把测试场景下业务接口转换为jmeter可识别的HashTree。HashTree中包含以下元素:
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