diff --git a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java index 53da366124..67173ef791 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java @@ -71,7 +71,6 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl // 一个脚本里可能包含多个场景(ThreadGroup),所以要区分开,key: 场景Id final Map scenarios = new LinkedHashMap<>(); - queue.forEach(result -> { // 线程名称: <场景名> <场景Index>-<请求Index>, 例如:Scenario 2-1 String scenarioName = StringUtils.substringBeforeLast(result.getThreadName(), THREAD_SPLIT); @@ -154,6 +153,21 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl responseResult.setResponseTime(result.getTime()); responseResult.setResponseMessage(result.getResponseMessage()); + if (JMeterVars.get(result.hashCode()) != null) { + List vars = new LinkedList<>(); + JMeterVars.get(result.hashCode()).entrySet().parallelStream().reduce(vars, (first, second) -> { + first.add(second.getKey() + ":" + second.getValue()); + return first; + }, (first, second) -> { + if (first == second) { + return first; + } + first.addAll(second); + return first; + }); + responseResult.setVars(StringUtils.join(vars, "\n")); + JMeterVars.remove(result.hashCode()); + } for (AssertionResult assertionResult : result.getAssertionResults()) { ResponseAssertionResult responseAssertionResult = getResponseAssertionResult(assertionResult); if (responseAssertionResult.isPass()) { diff --git a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java index 45e177624d..1ceb8ae6bf 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java @@ -41,8 +41,8 @@ public class JMeterService { try { Object scriptWrapper = SaveService.loadElement(is); HashTree testPlan = getHashTree(scriptWrapper); + JMeterVars.addJSR223PostProcessor(testPlan); addBackendListener(testId, debugReportId, testPlan); - LocalRunner runner = new LocalRunner(testPlan); runner.run(); } catch (Exception e) { diff --git a/backend/src/main/java/io/metersphere/api/jmeter/JMeterVars.java b/backend/src/main/java/io/metersphere/api/jmeter/JMeterVars.java new file mode 100644 index 0000000000..91dfb1edac --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/jmeter/JMeterVars.java @@ -0,0 +1,74 @@ +package io.metersphere.api.jmeter; + +import org.apache.jmeter.extractor.JSR223PostProcessor; +import org.apache.jmeter.extractor.RegexExtractor; +import org.apache.jmeter.extractor.XPath2Extractor; +import org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor; +import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy; +import org.apache.jmeter.threads.JMeterVariables; +import org.apache.jorphan.collections.HashTree; +import org.springframework.util.StringUtils; + +import java.util.*; + +public class JMeterVars { + + private JMeterVars() { + } + + // 数据和线程变量保持一致 + private static Map variables = new HashMap<>(); + + // 线程执行过程调用提取变量值 + public static void addVars(Integer testId, JMeterVariables vars, String extract) { + JMeterVariables vs = new JMeterVariables(); + if (!StringUtils.isEmpty(extract) && vars != null) { + List extracts = Arrays.asList(extract.split(";")); + Optional.ofNullable(extracts).orElse(new ArrayList<>()).forEach(item -> { + vs.put(item, vars.get(item) == null ? "" : vars.get(item)); + }); + vs.remove("TESTSTART.MS"); // 标示变量移除 + } + variables.put(testId, vs); + } + + // 递归处理所有请求,对有提取变量的增加后置脚本 + public static void addJSR223PostProcessor(HashTree tree) { + for (Object key : tree.keySet()) { + HashTree node = tree.get(key); + if (key instanceof HTTPSamplerProxy) { + StringJoiner extract = new StringJoiner(";"); + for (Object child : node.keySet()) { + if (child instanceof RegexExtractor) { + RegexExtractor regexExtractor = (RegexExtractor) child; + extract.add(regexExtractor.getRefName()); + } else if (child instanceof XPath2Extractor) { + XPath2Extractor regexExtractor = (XPath2Extractor) child; + extract.add(regexExtractor.getRefName()); + } else if (child instanceof JSONPostProcessor) { + JSONPostProcessor regexExtractor = (JSONPostProcessor) child; + extract.add(regexExtractor.getRefNames()); + } + } + if (Optional.ofNullable(extract).orElse(extract).length() > 0) { + JSR223PostProcessor shell = new JSR223PostProcessor(); + shell.setEnabled(true); + shell.setProperty("script", "io.metersphere.api.jmeter.JMeterVars.addVars(prev.hashCode(),vars," + "\"" + extract.toString() + "\"" + ");"); + node.add(shell); + } + } + if (node != null) { + addJSR223PostProcessor(node); + } + } + } + + public static JMeterVariables get(Integer key) { + return variables.get(key); + } + + public static void remove(Integer key) { + variables.remove(key); + } + +} diff --git a/backend/src/main/java/io/metersphere/api/jmeter/ResponseResult.java b/backend/src/main/java/io/metersphere/api/jmeter/ResponseResult.java index f772278e17..01b37b741a 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/ResponseResult.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/ResponseResult.java @@ -23,6 +23,8 @@ public class ResponseResult { private String body; + private String vars; + private final List assertions = new ArrayList<>(); } diff --git a/frontend/src/business/components/api/report/components/ResponseText.vue b/frontend/src/business/components/api/report/components/ResponseText.vue index cae4c07172..5240291408 100644 --- a/frontend/src/business/components/api/report/components/ResponseText.vue +++ b/frontend/src/business/components/api/report/components/ResponseText.vue @@ -22,6 +22,10 @@ + +
{{response.vars}}
+
+