JSR223 PostProcessor在tearDown线程组中无法正常工作
JMeter props清理失效问题排查与解决
我创建了一个测试计划,流程如下:
- 添加Setup线程组,通过多个HTTP请求及对应JSR223断言验证前置条件
- 断言失败时,将采样器名称和预期值存入以
failedSampler_开头的props属性中,用于后续普通线程组针对缺失数据执行操作
Setup线程组中JSR223断言代码(Groovy):
import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.assertions.AssertionResult; // JSR223 Assertion (Groovy) String expectedValue = "test"; // 替换为你的预期值 String jsonString = prev.getResponseDataAsString(); def jsonSlurper = new groovy.json.JsonSlurper() def jsonObject = jsonSlurper.parseText(jsonString) log.info(jsonObject.toString()); boolean matchFound = false; // 遍历hits数组,从每个文档中获取_name字段值 jsonObject.data.record.hits.each { hit -> String actualValue = hit._name; log.info("实际值为: " + actualValue); if (expectedValue.equals(actualValue)) { matchFound = true; } } if (!matchFound) { String sampleName = SampleResult.getSampleLabel(); String failureMessage = "采样器断言失败: " + sampleName + "\n预期值: " + expectedValue + "\n未找到匹配的实际值"; props.put("failedSampler_" + sampleName, expectedValue); log.error(failureMessage); // 创建断言结果 AssertionResult result = new AssertionResult("${expectedValue} 未找到"); result.setFailure(true); result.setFailureMessage(failureMessage); prev.addAssertionResult(result); prev.setSuccessful(false); }
为验证清理逻辑,我在TearDown线程组中配置了JSR223后置处理器清除props数据,但该处理器无法彻底清除props,下一次运行时仍保留上一次的数据。TearDown中的代码如下:
import org.apache.jmeter.reporters.ResultCollector import org.apache.jorphan.collections.SearchByClass def engine = ctx.getEngine() def test = engine.getClass().getDeclaredField('test') test.setAccessible(true) def testPlanTree = test.get(engine) SearchByClass<ResultCollector> listenerSearch = new SearchByClass<>(ResultCollector.class) testPlanTree.traverse(listenerSearch) Collection<ResultCollector> listeners = listenerSearch.getSearchResults() listeners.each { listener -> def files = listener.files files.each { file -> file.value.pw.close() } } log.info('清理前props大小:' +props.size()) props.clear() log.info('清理后props大小:' +props.size())
注:当前Setup与TearDown线程组之间未添加普通线程组,核心需求是将断言失败的预期值与采样器名称关联存储到props,供后续普通线程组访问并处理缺失数据。
问题原因分析
- props的生命周期:JMeter的
props是JVM级别的全局属性,除非JVM进程重启,否则默认不会自动彻底清除。props.clear()仅清除当前测试运行的内存数据,但如果JMeter进程持续运行,下一次测试会复用JVM环境,残留之前的props数据。 - TearDown执行限制:TearDown线程组在测试计划末尾执行,
props.clear()执行后,若JMeter进程未关闭,props仍会驻留在JVM内存中,下一次测试运行时会被读取。
解决方案
方案1:测试启动前清除指定前缀的props
在Setup线程组的最开头添加一个JSR223 Sampler,专门清理上一次遗留的failedSampler_开头的props:
// 清除所有以failedSampler_开头的props属性 def keysToRemove = props.keySet().findAll { it.startsWith('failedSampler_') } keysToRemove.each { props.remove(it) } log.info("已清除上一次遗留的${keysToRemove.size()}个failedSampler属性")
方案2:标记临时属性精准清理
在断言存储时为props添加临时标记,TearDown阶段仅清理标记过的属性:
- 断言代码中存储逻辑修改:
props.put("failedSampler_" + sampleName, expectedValue) // 添加临时属性标记 props.put("temp_" + sampleName, "true")
- TearDown中的清理代码修改:
def tempKeys = props.keySet().findAll { it.startsWith('temp_') } tempKeys.each { String originalKey = "failedSampler_" + it.replace('temp_', '') props.remove(originalKey) props.remove(it) } log.info("已清除${tempKeys.size()}个临时props属性")
方案3:CI/CD场景强制重启进程
在自动化测试流水线中,每次测试运行后关闭JMeter进程,避免JVM复用导致的props残留,从根源上解决数据污染问题。
内容的提问来源于stack exchange,提问作者Islam
相关产品推荐
相关产品推荐

