fix(接口测试): 修复全局前后置脚本在启用自身场景环境不生效问题】

--bug=1010196 --user=赵勇 场景/测试计划走原场景环境变量,变量值没有生成 https://www.tapd.cn/55049933/s/1104346
This commit is contained in:
fit2-zhao 2022-02-16 10:56:31 +08:00 committed by fit2-zhao
parent b984e481d8
commit bd1ff57dd7
2 changed files with 98 additions and 226 deletions

View File

@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.EnvironmentType;
import io.metersphere.api.dto.definition.request.controller.MsCriticalSectionController;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.dto.scenario.KeyValue;
@ -94,43 +95,9 @@ public class MsScenario extends MsTestElement {
}
if (this.getReferenced() != null && this.getReferenced().equals(MsTestElementConstants.Deleted.name())) {
return;
} else if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
try {
ApiScenarioMapper apiAutomationService = CommonBeanFactory.getBean(ApiScenarioMapper.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiScenarioWithBLOBs scenario = apiAutomationService.selectByPrimaryKey(this.getId());
if (scenario != null && StringUtils.isNotEmpty(scenario.getScenarioDefinition())) {
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
// 历史数据处理
ElementUtil.dataFormatting(element.getJSONArray("hashTree"));
this.setName(scenario.getName());
this.setProjectId(scenario.getProjectId());
LinkedList<MsTestElement> sourceHashTree = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
});
// 场景变量
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
this.setVariables(variables);
}
// 场景请求头
if (StringUtils.isNotEmpty(element.getString("headers"))) {
LinkedList<KeyValue> headers = mapper.readValue(element.getString("headers"),
new TypeReference<LinkedList<KeyValue>>() {
});
this.setHeaders(headers);
}
this.setHashTree(sourceHashTree);
hashTree = sourceHashTree;
} else {
return;
}
} catch (Exception ex) {
ex.printStackTrace();
}
} else if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())
&& !this.setRefScenario(hashTree)) {
return;
}
// 设置共享cookie
config.setEnableCookieShare(enableCookieShare);
@ -160,24 +127,113 @@ public class MsScenario extends MsTestElement {
config.setVariables(this.variables);
}
HashTree scenarioTree = tree;
// 取出自身场景环境
ParameterConfig newConfig = new ParameterConfig();
if (this.isEnvironmentEnable()) {
this.setNewConfig(envConfig, newConfig);
}
if (config != null && !config.getExcludeScenarioIds().contains(this.getId())) {
scenarioTree = MsCriticalSectionController.createHashTree(tree, this.getName(), this.isEnable());
}
// 场景变量和环境变量
Arguments arguments = arguments(config);
Arguments arguments = arguments(this.isEnvironmentEnable() ? newConfig : config);
if (arguments != null) {
Arguments valueSupposeMock = ParameterConfig.valueSupposeMock(arguments);
// 这里加入自定义变量解决ForEach循环控制器取值问题循环控制器无法从vars中取值
scenarioTree.add(valueSupposeMock);
scenarioTree.add(ElementUtil.argumentsToProcessor(valueSupposeMock));
}
ElementUtil.addCsvDataSet(scenarioTree, variables, config, "shareMode.group");
ElementUtil.addCsvDataSet(scenarioTree, variables, this.isEnvironmentEnable() ? newConfig : config, "shareMode.group");
ElementUtil.addCounter(scenarioTree, variables, false);
ElementUtil.addRandom(scenarioTree, variables);
if (CollectionUtils.isNotEmpty(this.headers)) {
config.setHeaders(this.headers);
if (this.isEnvironmentEnable()) {
newConfig.setHeaders(this.headers);
} else {
config.setHeaders(this.headers);
}
}
ParameterConfig newConfig = new ParameterConfig();
// 添加全局前置
this.setGlobProcessor(this.isEnvironmentEnable() ? newConfig : config, scenarioTree, true);
if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) {
el.setParent(this);
el.setMockEnvironment(this.isMockEnvironment());
if (this.isEnvironmentEnable()) {
el.toHashTree(scenarioTree, el.getHashTree(), newConfig);
} else {
el.toHashTree(scenarioTree, el.getHashTree(), config);
}
}
}
// 添加全局后置
this.setGlobProcessor(this.isEnvironmentEnable() ? newConfig : config, scenarioTree, false);
}
private void setGlobProcessor(ParameterConfig config, HashTree scenarioTree, boolean isPre) {
if (config.getConfig() != null) {
config.getConfig().forEach((k, environmentConfig) -> {
if (environmentConfig != null) {
MsJSR223Processor processor = isPre ? environmentConfig.getPreStepProcessor() : environmentConfig.getPostStepProcessor();
if (processor != null && StringUtils.isNotEmpty(processor.getScript())) {
processor.setType("JSR223Processor");
processor.setClazzName(MsJSR223Processor.class.getCanonicalName());
boolean isConnScenarioPre = false;
if (environmentConfig.getGlobalScriptConfig() != null) {
isConnScenarioPre = isPre ? environmentConfig.getGlobalScriptConfig().isConnScenarioPreScript() :
environmentConfig.getGlobalScriptConfig().isConnScenarioPostScript();
}
String name = isPre ? "PRE_PROCESSOR_ENV_" : "POST_PROCESSOR_ENV_";
processor.setName(name + isConnScenarioPre);
processor.toHashTree(scenarioTree, processor.getHashTree(), config);
}
}
});
}
}
private boolean setRefScenario(List<MsTestElement> hashTree) {
try {
ApiScenarioMapper apiAutomationService = CommonBeanFactory.getBean(ApiScenarioMapper.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiScenarioWithBLOBs scenario = apiAutomationService.selectByPrimaryKey(this.getId());
if (scenario != null && StringUtils.isNotEmpty(scenario.getScenarioDefinition())) {
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
// 历史数据处理
ElementUtil.dataFormatting(element.getJSONArray("hashTree"));
this.setName(scenario.getName());
this.setProjectId(scenario.getProjectId());
LinkedList<MsTestElement> sourceHashTree = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
});
// 场景变量
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
this.setVariables(variables);
}
// 场景请求头
if (StringUtils.isNotEmpty(element.getString("headers"))) {
LinkedList<KeyValue> headers = mapper.readValue(element.getString("headers"),
new TypeReference<LinkedList<KeyValue>>() {
});
this.setHeaders(headers);
}
this.setHashTree(sourceHashTree);
hashTree.clear();
hashTree.addAll(sourceHashTree);
return true;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
private void setNewConfig(Map<String, EnvironmentConfig> envConfig, ParameterConfig newConfig) {
if (this.isEnvironmentEnable()) {
ApiScenarioMapper apiScenarioMapper = CommonBeanFactory.getBean(ApiScenarioMapper.class);
EnvironmentGroupProjectService environmentGroupProjectService = CommonBeanFactory.getBean(EnvironmentGroupProjectService.class);
@ -206,18 +262,6 @@ public class MsScenario extends MsTestElement {
});
newConfig.setConfig(envConfig);
}
}
if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) {
el.setParent(this);
el.setMockEnvironment(this.isMockEnvironment());
if (this.isEnvironmentEnable()) {
el.toHashTree(scenarioTree, el.getHashTree(), newConfig);
} else {
el.toHashTree(scenarioTree, el.getHashTree(), config);
}
}
}
}

View File

@ -1,25 +1,13 @@
package io.metersphere.api.dto.definition.request;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONType;
import io.metersphere.api.dto.RunningParamKeys;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.sampler.MsDebugSampler;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler;
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.save.SaveService;
@ -27,9 +15,7 @@ import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jorphan.collections.HashTree;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@EqualsAndHashCode(callSuper = true)
@ -57,47 +43,10 @@ public class MsThreadGroup extends MsTestElement {
}
if (CollectionUtils.isNotEmpty(hashTree)) {
MsJSR223Processor preProcessor = null;
MsJSR223Processor postProcessor = null;
boolean isConnScenarioPre = false;
boolean isConnScenarioPost = false;
//获取projectConfig
String projectId = this.checkProjectId(hashTree);
if(StringUtils.isNotEmpty(projectId)){
this.checkEnvironmentConfig(projectId,config,hashTree);
}
if (config.getConfig() != null) {
if (config.isEffective(projectId)) {
EnvironmentConfig environmentConfig = config.getConfig().get(projectId);
if (environmentConfig != null) {
preProcessor = environmentConfig.getPreStepProcessor();
postProcessor = environmentConfig.getPostStepProcessor();
if(environmentConfig.getGlobalScriptConfig() != null ){
isConnScenarioPre = environmentConfig.getGlobalScriptConfig().isConnScenarioPreScript();
isConnScenarioPost = environmentConfig.getGlobalScriptConfig().isConnScenarioPostScript();
}
}
}
}
//检查全局前后置脚本
if (preProcessor != null && StringUtils.isNotEmpty(preProcessor.getScript())) {
preProcessor.setType("JSR223Processor");
preProcessor.setName("PRE_PROCESSOR_ENV_"+isConnScenarioPre);
preProcessor.setClazzName("io.metersphere.api.dto.definition.request.processors.MsJSR223Processor");
preProcessor.toHashTree(groupTree, preProcessor.getHashTree(), config);
}
for (MsTestElement el : hashTree) {
el.toHashTree(groupTree, el.getHashTree(), config);
}
if (postProcessor != null && StringUtils.isNotEmpty(postProcessor.getScript())) {
postProcessor.setType("JSR223Processor");
postProcessor.setName("POST_PROCESSOR_ENV_"+isConnScenarioPost);
postProcessor.setClazzName("io.metersphere.api.dto.definition.request.processors.MsJSR223Processor");
postProcessor.toHashTree(groupTree, postProcessor.getHashTree(), config);
}
if(!config.isOperating()){
if (!config.isOperating()) {
MsDebugSampler el = new MsDebugSampler();
el.setName(RunningParamKeys.RUNNING_DEBUG_SAMPLER_NAME);
el.toHashTree(groupTree, el.getHashTree(), config);
@ -105,127 +54,6 @@ public class MsThreadGroup extends MsTestElement {
}
}
private String checkProjectId(List<MsTestElement> hashTree) {
String projectId = this.getProjectId();
if (StringUtils.isEmpty(projectId)) {
for (MsTestElement el : hashTree) {
if (el instanceof MsHTTPSamplerProxy) {
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) el;
projectId = httpSamplerProxy.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (el instanceof MsJDBCSampler) {
MsJDBCSampler jdbcSampler = (MsJDBCSampler) el;
projectId = jdbcSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (el instanceof MsTCPSampler) {
MsTCPSampler tcpSampler = (MsTCPSampler) el;
projectId = tcpSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (el instanceof MsScenario) {
MsScenario scenario = (MsScenario)el;
if(scenario.getHashTree() != null){
for (MsTestElement itemEl : scenario.getHashTree()) {
if (itemEl instanceof MsHTTPSamplerProxy) {
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) itemEl;
projectId = httpSamplerProxy.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (itemEl instanceof MsJDBCSampler) {
MsJDBCSampler jdbcSampler = (MsJDBCSampler) itemEl;
projectId = jdbcSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (itemEl instanceof MsTCPSampler) {
MsTCPSampler tcpSampler = (MsTCPSampler) itemEl;
projectId = tcpSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
}else {
projectId = itemEl.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
}
}
}
if(StringUtils.isEmpty(projectId)){
projectId = el.getProjectId();
}
}
}
}
return projectId;
}
private void checkEnvironmentConfig(String projectId, ParameterConfig config, List<MsTestElement> hashTree) {
//检查全局前后置脚本
if (config.getConfig() == null) {
// 单独接口执行
this.setProjectId(projectId);
String environmentId = null;
for (MsTestElement el : hashTree) {
if (el instanceof MsHTTPSamplerProxy) {
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) el;
environmentId = httpSamplerProxy.getUseEnvironment();
if (StringUtils.isNotEmpty(environmentId)) {
break;
}
} else if (el instanceof MsJDBCSampler) {
MsJDBCSampler jdbcSampler = (MsJDBCSampler) el;
environmentId = jdbcSampler.getEnvironmentId();
if (StringUtils.isNotEmpty(environmentId)) {
break;
}
} else if (el instanceof MsTCPSampler) {
MsTCPSampler tcpSampler = (MsTCPSampler) el;
environmentId = tcpSampler.getUseEnvironment();
if (StringUtils.isNotEmpty(environmentId)) {
break;
}
} else if (el instanceof MsScenario) {
Map<String, EnvironmentConfig> envConfig = new HashMap<>(16);
MsScenario scenario = (MsScenario)el;
// 兼容历史数据
if (scenario.getEnvironmentMap() == null || scenario.getEnvironmentMap().isEmpty()) {
scenario.setEnvironmentMap(new HashMap<>(16));
if (StringUtils.isNotBlank(environmentId)) {
// 兼容1.8之前 没有environmentMap但有environmentId的数据
scenario.getEnvironmentMap().put(RunModeConstants.HIS_PRO_ID.toString(), environmentId);
}
}
if (scenario.getEnvironmentMap() != null && !scenario.getEnvironmentMap().isEmpty()) {
scenario.getEnvironmentMap().keySet().forEach(itemProjectId -> {
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(scenario.getEnvironmentMap().get(itemProjectId));
if (environment != null && environment.getConfig() != null) {
EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
env.setApiEnvironmentid(environment.getId());
envConfig.put(itemProjectId, env);
if (StringUtils.equals(environment.getName(), MockConfigStaticData.MOCK_EVN_NAME)) {
this.setMockEnvironment(true);
}
}
});
config.setConfig(envConfig);
}
}
}
if (StringUtils.isNotEmpty(environmentId)) {
config.setConfig(ElementUtil.getEnvironmentConfig(environmentId, projectId, this.isMockEnvironment()));
}
}
}
public ThreadGroup getThreadGroup() {
LoopController loopController = new LoopController();
loopController.setName("LoopController");