如何通过Java代码获取JMeter测试结果及汇总报告
已在Java代码中集成JMeter,测试可正常执行,但测试结果仅能输出至控制台。尝试使用logger.setFilename()后,生成的demo_result文件为空,目前仅能获取原始CSV格式的单条请求结果:
1678900803115,1,,200,,Example Thread Group 1-1,text,true,,189,120,1,1,1,0,0
1678900803117,1,,200,,Example Thread Group 1-1,text,true,,189,120,1,1,1,0,0
1678900803119,1,,200,,Example Thread Group 1-1,text,true,,189,120,1,1,1,0,0
需要获取类似如下格式的汇总结果:
summary = 3 in 00:00:00 = 46.9/s Avg: 1 Min: 1 Max: 1 Err: 0 (0.00%)
当前代码如下:
public static void initJmeter(){ StandardJMeterEngine standardJMeterEngine = new StandardJMeterEngine(); // 设置不适用gui的方式调用jmeter System.setProperty(JMeter.JMETER_NON_GUI, "true"); // 设置jmeter.properties文件,我们将jmeter文件存放在resources中,通过classload //String path = TestPlanLauncher.class.getClassLoader().getResource("jmeter.properties").getPath(); String path = "D:/Programming/JMeter/apache-jmeter-5.5/bin/jmeter.properties"; File jmeterPropertiesFile = new File(path); if (jmeterPropertiesFile.exists()) { JMeterUtils.loadJMeterProperties(jmeterPropertiesFile.getPath()); HashTree testPlanTree = new HashTree(); TestPlan testPlan = new TestPlan("Create JMeter Script From Java Code"); HTTPSamplerProxy examplecomSampler = createHTTPSamplerProxy(); LoopController loopController = createLoopController(); ThreadGroup threadGroup = createThreadGroup(); threadGroup.setSamplerController(loopController); HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup); threadGroupHashTree.add(examplecomSampler); Summariser summer = null; String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary"); if (summariserName.length() > 0) { summer = new Summariser(summariserName); } ResultCollector logger = new ResultCollector(summer); logger.setFilename("D:/Programming/JMeter/apache-jmeter-5.5/result/demo_result"); testPlanTree.add(testPlanTree.getArray()[0], logger); standardJMeterEngine.configure(testPlanTree); standardJMeterEngine.run(); } }
1. 修复ResultCollector空文件问题
你当前添加ResultCollector到HashTree的方式有误,导致它无法正确收集测试结果。将以下代码:
testPlanTree.add(testPlanTree.getArray()[0], logger);
替换为:
// 将ResultCollector添加到测试计划的子树中,确保能捕获所有样本结果 testPlanTree.add(testPlan, logger);
同时,加载JMeter配置后,可明确设置结果保存格式(确保CSV字段正确):
JMeterUtils.loadJMeterProperties(jmeterPropertiesFile.getPath()); // 明确设置结果输出格式为CSV JMeterUtils.setProperty("jmeter.save.saveservice.output_format", "csv"); // 根据需要开启需要保存的字段,比如响应时间、错误状态等 JMeterUtils.setProperty("jmeter.save.saveservice.response_time", "true"); JMeterUtils.setProperty("jmeter.save.saveservice.success", "true");
2. 让Summariser输出汇总结果到文件
默认Summariser仅输出到控制台,可通过重定向其输出流,将汇总结果写入文件。修改Summariser的初始化代码:
Summariser summer = null; String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary"); if (summariserName.length() > 0) { summer = new Summariser(summariserName); // 将汇总结果输出到指定文件 try { PrintWriter printWriter = new PrintWriter(new FileWriter("D:/Programming/JMeter/apache-jmeter-5.5/result/summary.txt")); summer.setOutput(printWriter); } catch (IOException e) { e.printStackTrace(); } }
测试结束后,summary.txt中就会生成你需要的格式的汇总结果。
3. 自定义收集汇总结果(灵活可控)
如果需要完全自定义汇总逻辑,可创建自定义ResultCollector,手动计算并生成汇总字符串:
// 创建自定义结果收集器,用于生成汇总信息 ResultCollector customSummaryCollector = new ResultCollector() { private long totalSamples = 0; private long errorCount = 0; private long totalResponseTime = 0; private long minResponseTime = Long.MAX_VALUE; private long maxResponseTime = 0; private long testStartTime; @Override public void testStarted() { super.testStarted(); testStartTime = System.currentTimeMillis(); } @Override public void sampleOccurred(SampleEvent event) { super.sampleOccurred(event); SampleResult result = event.getResult(); totalSamples++; // 统计错误数 if (!result.isSuccessful()) { errorCount++; } // 统计响应时间 long responseTime = result.getTime(); totalResponseTime += responseTime; if (responseTime < minResponseTime) { minResponseTime = responseTime; } if (responseTime > maxResponseTime) { maxResponseTime = responseTime; } } @Override public void testEnded() { super.testEnded(); long testDuration = System.currentTimeMillis() - testStartTime; // 计算吞吐量(每秒处理请求数) double throughput = testDuration > 0 ? (totalSamples * 1000.0) / testDuration : 0; // 计算平均响应时间 long avgResponseTime = totalSamples > 0 ? totalResponseTime / totalSamples : 0; // 计算错误率 double errorRate = totalSamples > 0 ? (errorCount * 100.0) / totalSamples : 0; // 格式化生成汇总字符串 String summary = String.format("summary = %6d in %s = %6.1f/s Avg: %6d Min: %6d Max: %6d Err: %6d (%.2f%%)", totalSamples, formatDuration(testDuration), throughput, avgResponseTime, minResponseTime, maxResponseTime, errorCount, errorRate); // 输出到控制台 System.out.println(summary); // 写入文件 try (FileWriter writer = new FileWriter("D:/Programming/JMeter/apache-jmeter-5.5/result/custom_summary.txt")) { writer.write(summary); } catch (IOException e) { e.printStackTrace(); } } // 格式化测试时长为 HH:MM:SS private String formatDuration(long milliseconds) { long seconds = milliseconds / 1000; long minutes = seconds / 60; long hours = minutes / 60; return String.format("%02d:%02d:%02d", hours, minutes % 60, seconds % 60); } }; // 将自定义收集器添加到测试计划树中 testPlanTree.add(testPlan, customSummaryCollector);
内容的提问来源于stack exchange,提问作者王纾林

