feat(接口测试): 处理环境和场景前后置

This commit is contained in:
AgAngle 2024-02-04 17:24:53 +08:00 committed by Craftsman
parent f065ec134e
commit 9b4431e5a2
54 changed files with 573 additions and 173 deletions

View File

@ -43,8 +43,10 @@ public abstract class AbstractJmeterElementConverter<T extends MsTestElement> im
*/
public void parseChild(HashTree tree, AbstractMsTestElement element, ParameterConfig config) {
if (element != null && element.getChildren() != null) {
element.getChildren().forEach(child ->
getConverterFunc.apply(child.getClass()).toHashTree(tree, child, config));
element.getChildren().forEach(child -> {
child.setParent(element);
getConverterFunc.apply(child.getClass()).toHashTree(tree, child, config);
});
}
}
}

View File

@ -38,4 +38,8 @@ public abstract class AbstractMsTestElement implements MsTestElement {
* 子组件
*/
private LinkedList<AbstractMsTestElement> children;
/**
* 父组件
*/
private AbstractMsTestElement parent;
}

View File

@ -0,0 +1,11 @@
package io.metersphere.api.constants;
/**
* @Author: jianxing
* @CreateTime: 2024-02-02 19:15
*/
public class ApiConstants {
public static final String HTTP_PROTOCOL = "HTTP";
private ApiConstants() {}
}

View File

@ -27,6 +27,13 @@ public class ApiParamConfig extends ParameterConfig {
* value 为对应的插件 ID
*/
private Map<Class<? extends AbstractMsTestElement>, String> testElementClassPluginIdMap;
/**
* AbstractMsTestElement 实现类与接口协议的映射
* key AbstractMsTestElement 实现类对象
* value 为对应的接口协议
* 环境前后置忽略协议需要使用
*/
private Map<Class<? extends AbstractMsTestElement>, String> testElementClassProtocalMap;
@Override
@ -53,5 +60,4 @@ public class ApiParamConfig extends ParameterConfig {
String pluginId = testElementClassPluginIdMap.get(msTestElement.getClass());
return pluginConfigMap.get(pluginId);
}
}

View File

@ -34,4 +34,17 @@ public class ApiScenarioParamConfig extends ApiParamConfig {
return super.getProtocolEnvConfig(msTestElement);
}
}
/**
* 获取当前环境或者环境组的配置
* @param projectId
* @return
*/
public EnvironmentInfoDTO getEnvConfig(String projectId) {
if (BooleanUtils.isTrue(grouped)) {
return projectEnvMap.get(projectId);
} else {
return getEnvConfig();
}
}
}

View File

@ -3,6 +3,7 @@ package io.metersphere.api.dto.assertion;
import io.metersphere.project.api.assertion.MsAssertion;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
@ -20,5 +21,5 @@ public class MsAssertionConfig {
/**
* 断言列表
*/
private List<MsAssertion> assertions;
private List<MsAssertion> assertions = new ArrayList<>(0);
}

View File

@ -22,4 +22,6 @@ public class ApiDebugRunRequest {
@NotNull
@Schema(description = "请求内容")
private Object request;
@Schema(description = "项目ID")
private String projectId;
}

View File

@ -33,4 +33,5 @@ public class MsCommonElement extends AbstractMsTestElement {
*/
@Valid
private MsAssertionConfig assertionConfig;
}

View File

@ -4,6 +4,7 @@ import io.metersphere.project.api.processor.MsProcessor;
import jakarta.validation.Valid;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
@ -15,12 +16,12 @@ import java.util.List;
public class MsProcessorConfig {
/**
* 是否启用全局前置
* 默认为 false
* 默认为 true
*/
private Boolean enableGlobal = false;
private Boolean enableGlobal = true;
/**
* 处理器列表
*/
@Valid
private List<MsProcessor> processors;
private List<MsProcessor> processors = new ArrayList<>(0);
}

View File

@ -58,7 +58,7 @@ public class ApiScenarioAddRequest {
private String environmentId;
@Schema(description = "场景的通用配置")
private ScenarioConfig scenarioConfig;
private ScenarioConfig scenarioConfig = new ScenarioConfig();
@Schema(description = "步骤集合")
@Valid

View File

@ -56,6 +56,10 @@ public class ApiScenarioStepCommonDTO {
@Schema(description = "csv文件id集合")
private List<String> csvFileIds;
@Schema(description = "项目fk")
@NotBlank
private String projectId;
@Valid
@Schema(description = "子步骤")
private List<? extends ApiScenarioStepCommonDTO> children;

View File

@ -16,9 +16,6 @@ public class ApiScenarioStepDTO extends ApiScenarioStepCommonDTO {
@Schema(description = "资源编号")
private String resourceNum;
@Schema(description = "项目fk")
private String projectId;
@Schema(description = "版本号")
private String versionId;

View File

@ -20,10 +20,6 @@ public class ApiScenarioStepRequest extends ApiScenarioStepCommonDTO {
@Size(min = 1, max = 50, message = "{api_scenario_step.resource_num.length_range}")
private String resourceNum;
@Schema(description = "项目fk")
@Size(min = 1, max = 50, message = "{api_scenario_step.project_id.length_range}")
private String projectId;
@Schema(description = "版本号")
@Size(min = 1, max = 50, message = "{api_scenario_step.version_id.length_range}")
private String versionId;

View File

@ -56,7 +56,7 @@ public class ApiScenarioUpdateRequest {
private String environmentId;
@Schema(description = "场景的通用配置")
private ScenarioConfig scenarioConfig;
private ScenarioConfig scenarioConfig = new ScenarioConfig();
@Valid
@Schema(description = "步骤集合")

View File

@ -13,21 +13,21 @@ public class ScenarioConfig {
/**
* 场景变量
*/
private ScenarioVariable variable;
private ScenarioVariable variable = new ScenarioVariable();
/**
* 前置处理器配置
*/
private MsProcessorConfig preProcessorConfig;
private MsProcessorConfig preProcessorConfig = new MsProcessorConfig();
/**
* 后置处理器配置
*/
private MsProcessorConfig postProcessorConfig;
private MsProcessorConfig postProcessorConfig = new MsProcessorConfig();
/**
* 断言配置
*/
private MsAssertionConfig assertionConfig;
private MsAssertionConfig assertionConfig = new MsAssertionConfig();
/**
* 其他配置
*/
private ScenarioOtherConfig otherConfig;
private ScenarioOtherConfig otherConfig = new ScenarioOtherConfig();
}

View File

@ -7,7 +7,7 @@ import lombok.Data;
@Data
public class ScenarioStepConfig extends ApiScenario {
@Schema(description = "是否使用源场景环境")
private Boolean enableScenarioEnv;
private Boolean enableScenarioEnv = false;
@Schema(description = "是否使用当前场景参数如果为false则使用源场景参数")
private Boolean useCurrentScenarioParam = false;

View File

@ -3,6 +3,7 @@ package io.metersphere.api.dto.scenario;
import io.metersphere.project.dto.environment.variables.CommonVariables;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
@ -14,9 +15,9 @@ public class ScenarioVariable {
/**
* 普通变量
*/
private List<CommonVariables> commonVariables;
private List<CommonVariables> commonVariables = new ArrayList<>(0);
/**
* csv变量
*/
private List<CsvVariable> csvVariables;
private List<CsvVariable> csvVariables = new ArrayList<>(0);
}

View File

@ -1,5 +1,6 @@
package io.metersphere.api.parser.api;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.dto.definition.HttpResponse;
import io.metersphere.api.dto.converter.ApiDefinitionImport;
import io.metersphere.api.dto.converter.ApiDefinitionImportDetail;
@ -279,7 +280,7 @@ public class Swagger3Parser<T> implements ImportParser<ApiDefinitionImport> {
ApiDefinitionImportDetail apiDefinition = new ApiDefinitionImportDetail();
apiDefinition.setName(name);
apiDefinition.setPath(formatPath(path));
apiDefinition.setProtocol("HTTP");
apiDefinition.setProtocol(ApiConstants.HTTP_PROTOCOL);
apiDefinition.setMethod(method);
apiDefinition.setProjectId(this.projectId);
apiDefinition.setCreateUser(importRequest.getUserId());

View File

@ -1,19 +1,37 @@
package io.metersphere.api.parser.jmeter;
import io.metersphere.api.dto.request.MsCommonElement;
import io.metersphere.project.api.assertion.MsAssertion;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.dto.ApiParamConfig;
import io.metersphere.api.dto.ApiScenarioParamConfig;
import io.metersphere.api.dto.assertion.MsAssertionConfig;
import io.metersphere.project.api.assertion.MsResponseCodeAssertion;
import io.metersphere.api.dto.request.MsCommonElement;
import io.metersphere.api.dto.request.http.MsHTTPElement;
import io.metersphere.api.dto.request.processors.MsProcessorConfig;
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverter;
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverterFactory;
import io.metersphere.api.parser.jmeter.processor.assertion.AssertionConverterFactory;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.api.assertion.MsAssertion;
import io.metersphere.project.api.assertion.MsResponseCodeAssertion;
import io.metersphere.project.api.processor.MsProcessor;
import io.metersphere.project.dto.environment.EnvironmentConfig;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import io.metersphere.project.dto.environment.processors.ApiEnvProcessorConfig;
import io.metersphere.project.dto.environment.processors.ApiEnvRequestProcessorConfig;
import io.metersphere.project.dto.environment.processors.EnvProcessorConfig;
import io.metersphere.project.dto.environment.processors.EnvRequestScriptProcessor;
import io.metersphere.sdk.constants.MsAssertionCondition;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 10:07
@ -25,17 +43,24 @@ public class MsCommonElementConverter extends AbstractJmeterElementConverter<MsC
@Override
public void toHashTree(HashTree tree, MsCommonElement element, ParameterConfig config) {
// todo 开关默认开启关闭则运行该接口时不执行全局前置
// preProcessorConfig.getEnableGlobal();
// 解析前置处理器
handlePreProcessor(tree, element.getPreProcessorConfig(), config);
// 解析后置处理器
handlePostProcessor(tree, element.getPostProcessorConfig(), config);
EnvironmentInfoDTO envInfo = getEnvInfo(element, config);
// 解析前置处理器包括环境前置
addProcessors(tree, element, config, envInfo, true);
// 解析后置处理器包括环境后置
addProcessors(tree, element, config, envInfo, false);
// 处理断言
handleAssertion(tree, element.getAssertionConfig(), config);
}
private EnvironmentInfoDTO getEnvInfo(MsCommonElement element, ParameterConfig config) {
if (config instanceof ApiParamConfig apiParamConfig) {
return apiParamConfig.getEnvConfig();
} else if (config instanceof ApiScenarioParamConfig apiScenarioParamConfig) {
return apiScenarioParamConfig.getEnvConfig(element.getProjectId());
}
return null;
}
private void handleAssertion(HashTree tree, MsAssertionConfig assertionConfig, ParameterConfig config) {
// todo 开关默认开启关闭则运行该接口时不执行全局前置
// assertionConfig.getEnableGlobal();
@ -56,19 +81,80 @@ public class MsCommonElementConverter extends AbstractJmeterElementConverter<MsC
.forEach(assertion -> AssertionConverterFactory.getConverter(assertion.getClass()).parse(tree, assertion, config, finalIsIgnoreStatus));
}
private void handlePreProcessor(HashTree tree, MsProcessorConfig preProcessorConfig, ParameterConfig config) {
if (preProcessorConfig == null || preProcessorConfig.getProcessors() == null) {
private void addProcessors(HashTree tree, MsCommonElement msCommonElement, ParameterConfig config,
EnvironmentInfoDTO envInfo, boolean isPre) {
MsProcessorConfig processorConfig = isPre ? msCommonElement.getPreProcessorConfig() : msCommonElement.getPostProcessorConfig();
if (processorConfig == null || processorConfig.getProcessors() == null) {
return;
}
preProcessorConfig.getProcessors()
.forEach(processor -> MsProcessorConverterFactory.getPreConverter(processor.getClass()).parse(tree, processor, config));
AbstractMsTestElement parent = msCommonElement.getParent();
String protocol = null;
if (parent instanceof MsHTTPElement) {
protocol = ApiConstants.HTTP_PROTOCOL;
} else {
if (config instanceof ApiParamConfig apiParamConfig) {
protocol = apiParamConfig.getTestElementClassProtocalMap().get(parent.getClass());
}
}
List<MsProcessor> beforeStepProcessors = new ArrayList<>(0);
List<MsProcessor> afterStepProcessors = new ArrayList<>(0);
// 开启全局前置才处理环境前置处理器
if (BooleanUtils.isTrue(processorConfig.getEnableGlobal()) && envInfo != null) {
EnvironmentConfig envConfig = envInfo.getConfig();
EnvProcessorConfig envProcessorConfig = isPre ? envConfig.getPreProcessorConfig() : envConfig.getPostProcessorConfig();
addEnvProcessors(envProcessorConfig, beforeStepProcessors, afterStepProcessors, protocol, true);
}
Function<Class<?>, MsProcessorConverter<MsProcessor>> getConverterFunc =
isPre ? MsProcessorConverterFactory::getPreConverter : MsProcessorConverterFactory::getPostConverter;
// 处理环境中步骤前处理器
beforeStepProcessors.forEach(processor ->
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config));
processorConfig.getProcessors()
.forEach(processor -> getConverterFunc.apply(processor.getClass()).parse(tree, processor, config));
// 处理环境中步骤后处理器
afterStepProcessors.forEach(processor ->
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config));
}
private void handlePostProcessor(HashTree tree, MsProcessorConfig postProcessorConfig , ParameterConfig config) {
if (postProcessorConfig == null || postProcessorConfig.getProcessors() == null) {
return;
private void addEnvProcessors(EnvProcessorConfig envProcessorConfig,
List<MsProcessor> beforeStepProcessors,
List<MsProcessor> afterStepProcessors,
String protocol,
boolean isPre) {
// 获取环境中的前后置处理器
ApiEnvProcessorConfig apiProcessorConfig = envProcessorConfig.getApiProcessorConfig();
ApiEnvRequestProcessorConfig requestProcessorConfig = apiProcessorConfig.getRequestProcessorConfig();
List<MsProcessor> processors = requestProcessorConfig.getProcessors();
for (MsProcessor processor : processors) {
if (processor instanceof EnvRequestScriptProcessor requestScriptProcessor) {
// 如果是脚本处理器处理步骤内前置脚本前后配置以及忽略的协议
Boolean beforeStepScript = requestScriptProcessor.getBeforeStepScript();
List<String> ignoreProtocols = requestScriptProcessor.getIgnoreProtocols();
if (ignoreProtocols.contains(protocol)) {
return;
}
if (BooleanUtils.isTrue(beforeStepScript)) {
beforeStepProcessors.add(processor);
} else {
afterStepProcessors.add(processor);
}
} else {
// 其他处理器
if (isPre) {
// 如果是前置则在前置处理器之前执行
beforeStepProcessors.add(processor);
} else {
// 如果是后置则在后置处理器之后执行
afterStepProcessors.add(processor);
}
}
}
postProcessorConfig.getProcessors()
.forEach(processor -> MsProcessorConverterFactory.getPostConverter(processor.getClass()).parse(tree, processor, config));
}
}

View File

@ -1,22 +1,34 @@
package io.metersphere.api.parser.jmeter;
import io.metersphere.api.constants.ApiScenarioStepRefType;
import io.metersphere.api.dto.ApiScenarioParamConfig;
import io.metersphere.api.dto.request.MsScenario;
import io.metersphere.api.dto.request.processors.MsProcessorConfig;
import io.metersphere.api.dto.scenario.ScenarioConfig;
import io.metersphere.api.dto.scenario.ScenarioStepConfig;
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverter;
import io.metersphere.api.parser.jmeter.processor.MsProcessorConverterFactory;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
import io.metersphere.project.api.processor.MsProcessor;
import io.metersphere.project.dto.environment.EnvironmentConfig;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import io.metersphere.project.dto.environment.processors.EnvProcessorConfig;
import io.metersphere.sdk.util.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 10:07
*
* <p>
* 脚本解析器
*/
public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenario> {
@ -24,26 +36,127 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
@Override
public void toHashTree(HashTree tree, MsScenario msScenario, ParameterConfig msParameter) {
ApiScenarioParamConfig config = (ApiScenarioParamConfig) msParameter;
EnvironmentInfoDTO envInfo = config.getEnvConfig(msScenario.getProjectId());
// 添加环境的前置
addEnvScenarioProcessor(tree, msScenario, config, envInfo, true);
// 添加场景前置
addScenarioProcessor(tree, msScenario, config, true);
ApiScenarioParamConfig chileConfig = getChileConfig(msScenario, config);
parseChild(tree, msScenario, chileConfig);
// 添加场景后置
addScenarioProcessor(tree, msScenario, config, false);
// 添加环境的后置
addEnvScenarioProcessor(tree, msScenario, config, envInfo, false);
}
/**
* 添加环境的前后置
*
* @param tree
* @param msScenario
* @param config
* @param envInfo
* @param isPre
*/
private void addEnvScenarioProcessor(HashTree tree,
MsScenario msScenario,
ApiScenarioParamConfig config,
EnvironmentInfoDTO envInfo,
boolean isPre) {
if (isRef(msScenario.getRefType())) {
ScenarioStepConfig scenarioStepConfig = msScenario.getScenarioStepConfig();
if (scenarioStepConfig == null || BooleanUtils.isFalse(scenarioStepConfig.getEnableScenarioEnv())) {
// 引用的场景如果没有开启源场景环境不添加环境的前后置
return;
}
} else if (isCopy(msScenario.getRefType())) {
// 复制场景不添加环境的前后置
return;
} else {
// 当前场景添加环境的前后置
// do nothing
}
ScenarioConfig scenarioConfig = msScenario.getScenarioConfig();
MsProcessorConfig scenarioProcessorConfig = isPre ? scenarioConfig.getPreProcessorConfig() : scenarioConfig.getPostProcessorConfig();
Boolean enableGlobal = scenarioProcessorConfig.getEnableGlobal();
if (BooleanUtils.isFalse(enableGlobal) || envInfo == null) {
// 如果场景配置没有开启全局前置不添加环境的前后置
return;
}
// 获取环境中的场景级前后置
EnvironmentConfig envConfig = envInfo.getConfig();
EnvProcessorConfig processorConfig = isPre ? envConfig.getPreProcessorConfig() : envConfig.getPostProcessorConfig();
List<MsProcessor> envScenarioProcessors = processorConfig.getApiProcessorConfig()
.getScenarioProcessorConfig()
.getProcessors();
if (CollectionUtils.isEmpty(envScenarioProcessors)) {
return;
}
Function<Class<?>, MsProcessorConverter<MsProcessor>> getConverterFunc =
isPre ? MsProcessorConverterFactory::getPreConverter : MsProcessorConverterFactory::getPostConverter;
// 添加前后置
envScenarioProcessors.forEach(processor ->
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config));
}
private void addScenarioProcessor(HashTree tree, MsScenario msScenario, ParameterConfig config, boolean isPre) {
if (isCopy(msScenario.getRefType())) {
// 复制的场景没有前后置
return;
}
// 获取场景前后置
ScenarioConfig scenarioConfig = msScenario.getScenarioConfig();
MsProcessorConfig processorConfig = isPre ? scenarioConfig.getPreProcessorConfig() : scenarioConfig.getPostProcessorConfig();
List<MsProcessor> scenarioPreProcessors = processorConfig.getProcessors();
if (CollectionUtils.isEmpty(scenarioPreProcessors)) {
return;
}
Function<Class<?>, MsProcessorConverter<MsProcessor>> getConverterFunc =
isPre ? MsProcessorConverterFactory::getPreConverter : MsProcessorConverterFactory::getPostConverter;
// 添加场景前置处理器
scenarioPreProcessors.forEach(processor ->
getConverterFunc.apply(processor.getClass()).parse(tree, processor, config));
}
private boolean isRef(String refType) {
return StringUtils.equalsAny(refType, ApiScenarioStepRefType.REF.name(), ApiScenarioStepRefType.PARTIAL_REF.name());
}
private boolean isCopy(String refType) {
return StringUtils.equals(refType, ApiScenarioStepRefType.COPY.name());
}
/**
* 获取子步骤的配置信息
* 如果使用源场景环境则使用当前场景的环境信息
*
* @param msScenario
* @param config
* @return
*/
private ApiScenarioParamConfig getChileConfig(MsScenario msScenario, ApiScenarioParamConfig config) {
if (!isRef(msScenario.getRefType())) {
// 非引用的场景使用当前环境参数
return config;
}
ScenarioStepConfig scenarioStepConfig = msScenario.getScenarioStepConfig();
if (scenarioStepConfig != null && BooleanUtils.isTrue(scenarioStepConfig.getEnableScenarioEnv())) {
// 使用源场景环境
ApiScenarioParamConfig chileConfig = BeanUtils.copyBean(new ApiScenarioParamConfig(), config);
chileConfig.setGrouped(msScenario.getGrouped());
// 清空环境信息
chileConfig.setEnvConfig(null);
chileConfig.setProjectEnvMap(null);
if (BooleanUtils.isTrue(msScenario.getGrouped())) {

View File

@ -4,6 +4,8 @@ import io.metersphere.project.api.processor.ExtractPostProcessor;
import io.metersphere.project.api.processor.SQLProcessor;
import io.metersphere.project.api.processor.ScriptProcessor;
import io.metersphere.project.api.processor.TimeWaitingProcessor;
import io.metersphere.project.dto.environment.processors.EnvRequestScriptProcessor;
import io.metersphere.project.dto.environment.processors.EnvScenarioScriptProcessor;
import java.util.HashMap;
import java.util.Map;
@ -21,11 +23,15 @@ public class MsProcessorConverterFactory {
preConverterMap.put(ScriptProcessor.class, new ScriptPreProcessorConverter());
preConverterMap.put(SQLProcessor.class, new SqlPreProcessorConverter());
preConverterMap.put(TimeWaitingProcessor.class, new TimeWaitingProcessorConverter());
preConverterMap.put(EnvRequestScriptProcessor.class, new ScriptPreProcessorConverter());
preConverterMap.put(EnvScenarioScriptProcessor.class, new ScenarioScriptProcessorConverter());
postConverterMap.put(ScriptProcessor.class, new ScriptPostProcessorConverter());
postConverterMap.put(SQLProcessor.class, new SqlPostProcessorConverter());
postConverterMap.put(TimeWaitingProcessor.class, new TimeWaitingProcessorConverter());
postConverterMap.put(ExtractPostProcessor.class, new ExtractPostProcessorConverter());
postConverterMap.put(EnvRequestScriptProcessor.class, new ScriptPostProcessorConverter());
postConverterMap.put(EnvScenarioScriptProcessor.class, new ScenarioScriptProcessorConverter());
}
public static MsProcessorConverter getPreConverter(Class<?> processorClass) {

View File

@ -0,0 +1,38 @@
package io.metersphere.api.parser.jmeter.processor;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.project.api.processor.ScriptProcessor;
import io.metersphere.project.dto.environment.processors.EnvScenarioScriptProcessor;
import org.apache.jmeter.protocol.java.sampler.BeanShellSampler;
import org.apache.jmeter.protocol.java.sampler.JSR223Sampler;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree;
/**
* 环境场景级前置处理器处理
*
* @Author: jianxing
* @CreateTime: 2023-12-26 14:49
*/
public class ScenarioScriptProcessorConverter extends ScriptProcessorConverter {
@Override
public void parse(HashTree hashTree, ScriptProcessor scriptProcessor, ParameterConfig config) {
if (!needParse(scriptProcessor, config) || !scriptProcessor.isValid()) {
return;
}
EnvScenarioScriptProcessor scenarioScriptProcessor = (EnvScenarioScriptProcessor) scriptProcessor;
Boolean associateScenarioResult = scenarioScriptProcessor.getAssociateScenarioResult();
TestElement processor;
if (isJSR233(scriptProcessor)) {
processor = new JSR223Sampler();
} else {
processor = new BeanShellSampler();
}
parse(processor, scriptProcessor);
// 标记当前处理器是否关联场景结果
processor.setName("ASSOCIATE_RESULT_PROCESSOR_" + associateScenarioResult);
hashTree.add(processor);
}
}

View File

@ -14,7 +14,7 @@ import org.apache.jorphan.collections.HashTree;
public class ScriptPostProcessorConverter extends ScriptProcessorConverter {
@Override
public void parse(HashTree hashTree, ScriptProcessor scriptProcessor, ParameterConfig config) {
if (!needParse(scriptProcessor, config)) {
if (!needParse(scriptProcessor, config) || !scriptProcessor.isValid()) {
return;
}
// todo 处理公共脚本

View File

@ -14,7 +14,7 @@ import org.apache.jorphan.collections.HashTree;
public class ScriptPreProcessorConverter extends ScriptProcessorConverter {
@Override
public void parse(HashTree hashTree, ScriptProcessor scriptProcessor, ParameterConfig config) {
if (!needParse(scriptProcessor, config)) {
if (!needParse(scriptProcessor, config) || !scriptProcessor.isValid()) {
return;
}
// todo 处理公共脚本

View File

@ -24,15 +24,11 @@ import io.metersphere.sdk.dto.api.task.ApiExecuteFileInfo;
import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO;
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.EncryptUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.*;
import io.metersphere.system.config.MinioProperties;
import io.metersphere.system.domain.TestResourcePool;
import io.metersphere.system.dto.pool.TestResourceDTO;
import io.metersphere.system.dto.pool.TestResourceNodeDTO;
import io.metersphere.system.dto.pool.TestResourcePoolReturnDTO;
import io.metersphere.system.service.CommonProjectService;
import io.metersphere.system.service.SystemParameterService;
import io.metersphere.system.service.TestResourcePoolService;
@ -134,9 +130,7 @@ public class ApiExecuteService {
// todo 接口用例 method 获取定义中的数据库字段
String executeScript = parseExecuteScript(request.getTestElement(), parameterConfig);
TestResourceNodeDTO testResourceNodeDTO = getProjectExecuteNode(request.getProjectId());
doDebug(reportId, testId, taskRequest, executeScript, testResourceNodeDTO);
doDebug(reportId, testId, taskRequest, executeScript, request.getProjectId());
}
/**
@ -146,13 +140,21 @@ public class ApiExecuteService {
* @param testId 资源ID
* @param taskRequest 执行参数
* @param executeScript 执行脚本
* @param testResourceNodeDTO 资源池
* @param projectId 项目ID
*/
private void doDebug(String reportId,
String testId,
TaskRequestDTO taskRequest,
String executeScript,
TestResourceNodeDTO testResourceNodeDTO) {
String projectId) {
TestResourcePoolReturnDTO testResourcePoolDTO = getGetResourcePoolNodeDTO(projectId);
TestResourceNodeDTO testResourceNodeDTO = getProjectExecuteNode(testResourcePoolDTO);
if (StringUtils.isNotBlank(testResourcePoolDTO.getServerUrl())) {
// 如果资源池配置了当前站点则使用资源池的
taskRequest.setMsUrl(testResourcePoolDTO.getServerUrl());
}
// 将测试脚本缓存到 redis
String scriptRedisKey = getScriptRedisKey(reportId, testId);
stringRedisTemplate.opsForValue().set(scriptRedisKey, executeScript);
@ -169,18 +171,21 @@ public class ApiExecuteService {
}
}
private TestResourceNodeDTO getProjectExecuteNode(String projectId) {
String resourcePoolId = getProjectApiResourcePoolId(projectId);
TestResourceDTO resourcePoolDTO = getAvailableResourcePoolDTO(projectId, resourcePoolId);
roundRobinService.initializeNodes(resourcePoolId, resourcePoolDTO.getNodesList());
private TestResourceNodeDTO getProjectExecuteNode(TestResourcePoolReturnDTO resourcePoolDTO) {
roundRobinService.initializeNodes(resourcePoolDTO.getId(), resourcePoolDTO.getTestResourceReturnDTO().getNodesList());
try {
return roundRobinService.getNextNode(resourcePoolId);
return roundRobinService.getNextNode(resourcePoolDTO.getId());
} catch (Exception e) {
LogUtils.error(e);
throw new MSException("get execute node error", e);
}
}
private TestResourcePoolReturnDTO getGetResourcePoolNodeDTO(String projectId) {
String resourcePoolId = getProjectApiResourcePoolId(projectId);
return getAvailableResourcePoolDTO(projectId, resourcePoolId);
}
/**
* 设置minio kafka ms 等信息
*
@ -216,9 +221,7 @@ public class ApiExecuteService {
apiRunModeConfig.setRunMode(ApiExecuteRunMode.BACKEND_DEBUG.name());
taskRequest.setRunModeConfig(apiRunModeConfig);
TestResourceNodeDTO testResourceNodeDTO = getProjectExecuteNode(runRequest.getProjectId());
doDebug(reportId, testId, taskRequest, executeScript, testResourceNodeDTO);
doDebug(reportId, testId, taskRequest, executeScript, runRequest.getProjectId());
return reportId;
}
@ -336,7 +339,7 @@ public class ApiExecuteService {
* @param projectId 项目ID
* @param resourcePoolId 资源池ID
*/
public TestResourceDTO getAvailableResourcePoolDTO(String projectId, String resourcePoolId) {
public TestResourcePoolReturnDTO getAvailableResourcePoolDTO(String projectId, String resourcePoolId) {
TestResourcePool testResourcePool = testResourcePoolService.getTestResourcePool(resourcePoolId);
if (testResourcePool == null ||
// 资源池禁用
@ -345,7 +348,7 @@ public class ApiExecuteService {
!commonProjectService.validateProjectResourcePool(testResourcePool, projectId)) {
throw new MSException(ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);
}
return testResourcePoolService.getTestResourceDTO(resourcePoolId);
return testResourcePoolService.getTestResourcePoolDetail(resourcePoolId);
}
private String getProjectApiResourcePoolId(String projectId) {

View File

@ -1,5 +1,6 @@
package io.metersphere.api.service;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.dto.ApiTestPluginOptionRequest;
import io.metersphere.api.dto.request.http.MsHTTPElement;
import io.metersphere.plugin.api.dto.ApiPluginOptionsRequest;
@ -25,7 +26,6 @@ import java.util.List;
@Transactional(rollbackFor = Exception.class)
public class ApiTestService {
private static final String HTTP_PROTOCOL = "HTTP";
@Resource
private ApiPluginService apiPluginService;
@ -33,7 +33,7 @@ public class ApiTestService {
List<ProtocolDTO> protocols = apiPluginService.getProtocols(orgId);
// http 协议放最前面
ProtocolDTO protocolDTO = new ProtocolDTO();
protocolDTO.setProtocol(HTTP_PROTOCOL);
protocolDTO.setProtocol(ApiConstants.HTTP_PROTOCOL);
protocolDTO.setPolymorphicName(MsHTTPElement.class.getSimpleName());
protocols.addFirst(protocolDTO);
return protocols;

View File

@ -197,10 +197,9 @@ public class ApiDebugService {
public String debug(ApiDebugRunRequest request) {
String id = request.getId();
ApiDebug apiDebug = checkResourceExist(id);
ApiResourceRunRequest runRequest = BeanUtils.copyBean(new ApiResourceRunRequest(), request);
runRequest.setProjectId(apiDebug.getProjectId());
runRequest.setProjectId(request.getProjectId());
runRequest.setTestId(id);
runRequest.setReportId(id);
runRequest.setResourceType(ApiResourceType.API_DEBUG.name());

View File

@ -1041,6 +1041,7 @@ public class ApiScenarioService {
MsScenario msScenario = new MsScenario();
msScenario.setRefType(ApiScenarioStepRefType.DIRECT.name());
msScenario.setScenarioConfig(getScenarioConfig(request, hasSave));
msScenario.setProjectId(request.getProjectId());
// 获取场景环境相关配置
ApiScenarioParseEnvInfo scenarioParseEnvInfo = getScenarioParseEnvInfo(refResourceMap, request.getEnvironmentId(), request.getGrouped());
@ -1059,6 +1060,7 @@ public class ApiScenarioService {
ApiScenarioParamConfig parseConfig = new ApiScenarioParamConfig();
parseConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap());
parseConfig.setTestElementClassProtocalMap(apiPluginService.getTestElementProtocolMap());
parseConfig.setGrouped(request.getGrouped());
parseConfig.setReportId(request.getReportId());
scenarioParseEnvInfo.getPluginClassEnvConfigMap();
@ -1156,6 +1158,7 @@ public class ApiScenarioService {
// 将步骤详情解析生成对应的MsTestElement
AbstractMsTestElement msTestElement = stepParser.parseTestElement(step, resourceBlobMap.get(step.getResourceId()), stepDetailMap.get(step.getId()));
if (msTestElement != null) {
msTestElement.setProjectId(step.getProjectId());
setMsScenarioParam(scenarioParseEnvInfo, step, msTestElement);
parentElement.getChildren().add(msTestElement);
}

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.controller.result.ApiResultCode;
import io.metersphere.api.domain.ApiDebug;
import io.metersphere.api.domain.ApiDebugBlob;
@ -60,7 +61,6 @@ public class ApiDebugControllerTests extends BaseTest {
protected static final String DEFAULT_LIST = "list/{0}";
protected static final String UPLOAD_TEMP_FILE = "upload/temp/file";
protected static final String DEBUG = "debug";
protected static final String HTTP_PROTOCOL = "HTTP";
@Resource
private ApiDebugMapper apiDebugMapper;
@ -86,7 +86,7 @@ public class ApiDebugControllerTests extends BaseTest {
@Order(0)
public void listEmpty() throws Exception {
// @@校验没有数据的情况
this.requestGetWithOk(DEFAULT_LIST, HTTP_PROTOCOL);
this.requestGetWithOk(DEFAULT_LIST, ApiConstants.HTTP_PROTOCOL);
// 准备数据上传文件管理文件
uploadFileMetadata();
}
@ -133,7 +133,7 @@ public class ApiDebugControllerTests extends BaseTest {
request.setPath("http://test.com");
request.setMethod("GET");
request.setName("test");
request.setProtocol(HTTP_PROTOCOL);
request.setProtocol(ApiConstants.HTTP_PROTOCOL);
request.setModuleId("default");
request.setProjectId(DEFAULT_PROJECT_ID);
MsHTTPElement msHttpElement = MsHTTPElementTest.getMsHttpElement();
@ -320,7 +320,7 @@ public class ApiDebugControllerTests extends BaseTest {
@Order(4)
public void list() throws Exception {
// @@请求成功
MvcResult mvcResult = this.requestGetWithOk(DEFAULT_LIST, HTTP_PROTOCOL)
MvcResult mvcResult = this.requestGetWithOk(DEFAULT_LIST, ApiConstants.HTTP_PROTOCOL)
.andReturn();
// 校验数据是否正确
List<ApiDebugSimpleDTO> apiDebugList = getResultDataArray(mvcResult, ApiDebugSimpleDTO.class);
@ -331,7 +331,7 @@ public class ApiDebugControllerTests extends BaseTest {
BeanUtils.copyBean(new ApiDebugSimpleDTO(), apiDebugMapper.selectByPrimaryKey(anotherAddApiDebug.getId())));
// @@校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ, DEFAULT_LIST, HTTP_PROTOCOL);
requestGetPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ, DEFAULT_LIST, ApiConstants.HTTP_PROTOCOL);
}
@ -362,6 +362,7 @@ public class ApiDebugControllerTests extends BaseTest {
msHTTPElement.setMethod("GET");
request.setRequest(JSON.parseObject(ApiDataUtils.toJSONString(msHTTPElement)));
request.setReportId(IDGenerator.nextStr());
request.setProjectId(DEFAULT_PROJECT_ID);
// @校验组织没有资源池权限异常
assertErrorCode(this.requestPost(DEBUG, request), ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
@ -114,7 +115,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
apiDebug.setProjectId(project.getId());
apiDebug.setName(StringUtils.join("接口调试", apiDebug.getId()));
apiDebug.setModuleId(moduleId);
apiDebug.setProtocol("HTTP");
apiDebug.setProtocol(ApiConstants.HTTP_PROTOCOL);
apiDebug.setMethod("GET");
apiDebug.setPath(StringUtils.join("api/debug/", apiDebug.getId()));
apiDebug.setCreateTime(System.currentTimeMillis());
@ -748,7 +749,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
public void TestModuleCountSuccess() throws Exception {
this.preliminaryData();
ApiDebugRequest request = new ApiDebugRequest() {{
this.setProtocol("HTTP");
this.setProtocol(ApiConstants.HTTP_PROTOCOL);
}};
MvcResult moduleCountMvcResult = this.requestPostWithOkAndReturn(URL_FILE_MODULE_COUNT, request);
Map<String, Integer> moduleCountResult = JSON.parseObject(JSON.toJSONString(

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.constants.ApiDefinitionDocType;
import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.api.controller.result.ApiResultCode;
@ -238,7 +239,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID);
ApiDefinitionAddRequest request = new ApiDefinitionAddRequest();
request.setName("接口定义test");
request.setProtocol("HTTP");
request.setProtocol(ApiConstants.HTTP_PROTOCOL);
request.setProjectId(DEFAULT_PROJECT_ID);
request.setMethod("POST");
request.setPath("/api/admin/posts");
@ -404,7 +405,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
//校验修改path和method时是否会影响用例
ApiDefinitionAddRequest addRequest = new ApiDefinitionAddRequest();
addRequest.setName("测试修改path和method");
addRequest.setProtocol("HTTP");
addRequest.setProtocol(ApiConstants.HTTP_PROTOCOL);
addRequest.setProjectId(DEFAULT_PROJECT_ID);
addRequest.setMethod("POST");
addRequest.setPath("/api/admin/posts");
@ -1400,7 +1401,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
request.setCoverData(true);
request.setCoverModule(true);
request.setModuleId(apiDefinitionModule.getId());
request.setProtocol("HTTP");
request.setProtocol(ApiConstants.HTTP_PROTOCOL);
request.setUserId("admin");
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("request", JSON.toJSONString(request));

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
@ -134,7 +135,7 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
apiDefinition.setProjectId(project.getId());
apiDefinition.setName(StringUtils.join("接口定义", apiDefinition.getId()));
apiDefinition.setModuleId(moduleId);
apiDefinition.setProtocol("HTTP");
apiDefinition.setProtocol(ApiConstants.HTTP_PROTOCOL);
apiDefinition.setMethod("GET");
apiDefinition.setStatus("未规划");
apiDefinition.setNum(NumGenerator.nextNum(project.getId(), ApplicationNumScope.API_DEFINITION));
@ -811,7 +812,7 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
public void TestModuleCountSuccess() throws Exception {
this.preliminaryData();
ApiModuleRequest request = new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProtocol(ApiConstants.HTTP_PROTOCOL);
this.setProjectId(project.getId());
}};
MvcResult moduleCountMvcResult = this.requestPostWithOkAndReturn(URL_FILE_MODULE_COUNT, request);
@ -876,7 +877,7 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
apiDefinition.setDeleted(true);
apiDefinitionMapper.updateByExampleSelective(apiDefinition, example);
MvcResult result = this.requestPostWithOkAndReturn(URL_MODULE_TRASH_TREE, new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProtocol(ApiConstants.HTTP_PROTOCOL);
this.setProjectId(project.getId());
}});
@ -889,7 +890,7 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
@Order(12)
public void getModuleTrashTreeCount() throws Exception {
ApiModuleRequest request = new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProtocol(ApiConstants.HTTP_PROTOCOL);
this.setProjectId(project.getId());
}};
MvcResult moduleCountMvcResult = this.requestPostWithOkAndReturn(URL_MODULE_TRASH_COUNT, request);
@ -951,11 +952,11 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
private List<BaseTreeNode> getModuleTreeNode() throws Exception {
MvcResult result = this.requestPostWithOkAndReturn(URL_MODULE_TREE, new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProtocol(ApiConstants.HTTP_PROTOCOL);
this.setProjectId(project.getId());
}});
this.requestPostWithOkAndReturn(URL_MODULE_ONLY_TREE, new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProtocol(ApiConstants.HTTP_PROTOCOL);
this.setProjectId(project.getId());
}});
String returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);

View File

@ -1,13 +1,11 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.api.constants.ApiScenarioStatus;
import io.metersphere.api.constants.ApiScenarioStepRefType;
import io.metersphere.api.constants.ApiScenarioStepType;
import io.metersphere.api.constants.*;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.assertion.MsAssertionConfig;
import io.metersphere.api.dto.definition.ApiDefinitionAddRequest;
import io.metersphere.api.dto.definition.ApiTestCaseAddRequest;
import io.metersphere.api.dto.assertion.MsAssertionConfig;
import io.metersphere.project.api.assertion.MsScriptAssertion;
import io.metersphere.api.dto.request.http.MsHTTPElement;
import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
import io.metersphere.api.dto.response.OperationDataInfo;
@ -24,11 +22,15 @@ import io.metersphere.api.utils.JmeterElementConverterRegister;
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
import io.metersphere.plugin.api.spi.JmeterElementConverter;
import io.metersphere.plugin.api.spi.MsTestElement;
import io.metersphere.project.api.assertion.MsScriptAssertion;
import io.metersphere.project.api.processor.MsProcessor;
import io.metersphere.project.api.processor.SQLProcessor;
import io.metersphere.project.dto.environment.EnvironmentConfig;
import io.metersphere.project.dto.environment.EnvironmentGroupProjectDTO;
import io.metersphere.project.dto.environment.EnvironmentGroupRequest;
import io.metersphere.project.dto.environment.EnvironmentRequest;
import io.metersphere.project.dto.environment.processors.EnvProcessorConfig;
import io.metersphere.project.dto.environment.processors.EnvRequestScriptProcessor;
import io.metersphere.project.dto.environment.processors.EnvScenarioScriptProcessor;
import io.metersphere.project.dto.filemanagement.request.FileUploadRequest;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.service.EnvironmentGroupService;
@ -284,8 +286,8 @@ public class ApiScenarioControllerTests extends BaseTest {
@Test
@Order(1)
public void add() throws Exception {
initTestData();
initEnv();
initTestData();
// @@请求成功
ApiScenarioAddRequest request = new ApiScenarioAddRequest();
@ -322,6 +324,7 @@ public class ApiScenarioControllerTests extends BaseTest {
stepRequest.setResourceId(addApiScenario.getId());
stepRequest.setRefType(ApiScenarioStepRefType.REF.name());
stepRequest.setStepType(ApiScenarioStepType.API_SCENARIO.name());
stepRequest.setProjectId(DEFAULT_PROJECT_ID);
ApiScenarioStepRequest stepRequest2 = new ApiScenarioStepRequest();
stepRequest2.setId(IDGenerator.nextStr());
@ -330,6 +333,7 @@ public class ApiScenarioControllerTests extends BaseTest {
stepRequest2.setRefType(ApiScenarioStepRefType.PARTIAL_REF.name());
stepRequest2.setChildren(List.of(stepRequest));
stepRequest2.setStepType(ApiScenarioStepType.API_SCENARIO.name());
stepRequest2.setProjectId(DEFAULT_PROJECT_ID);
steps = List.of(stepRequest, stepRequest2);
request.setSteps(steps);
mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request);
@ -478,7 +482,7 @@ public class ApiScenarioControllerTests extends BaseTest {
private void initTestData() {
ApiDefinitionAddRequest apiDefinitionAddRequest = new ApiDefinitionAddRequest();
apiDefinitionAddRequest.setName("test scenario");
apiDefinitionAddRequest.setProtocol("HTTP");
apiDefinitionAddRequest.setProtocol(ApiConstants.HTTP_PROTOCOL);
apiDefinitionAddRequest.setProjectId(DEFAULT_PROJECT_ID);
apiDefinitionAddRequest.setMethod("POST");
apiDefinitionAddRequest.setPath("/api/admin/posts");
@ -487,7 +491,7 @@ public class ApiScenarioControllerTests extends BaseTest {
apiDefinitionAddRequest.setVersionId(extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID));
apiDefinitionAddRequest.setDescription("描述内容");
apiDefinitionAddRequest.setName("test scenario");
MsHTTPElement msHttpElement = MsHTTPElementTest.getMsHttpElement();
MsHTTPElement msHttpElement = MsHTTPElementTest.getAddProcessorHttpElement();
apiDefinitionAddRequest.setRequest(getMsElementParam(msHttpElement));
apiDefinitionAddRequest.setResponse("{}");
apiDefinition = apiDefinitionService.create(apiDefinitionAddRequest, "admin");
@ -611,6 +615,7 @@ public class ApiScenarioControllerTests extends BaseTest {
stepRequest.setStepType(ApiScenarioStepType.API_SCENARIO.name());
stepRequest.setChildren(getApiScenarioStepRequests());
stepRequest.setConfig(scenarioStepConfig);
stepRequest.setProjectId(DEFAULT_PROJECT_ID);
steps.add(stepRequest);
ApiScenarioStepRequest copyScenarioStep = BeanUtils.copyBean(new ApiScenarioStepRequest(), stepRequest);
copyScenarioStep.setRefType(ApiScenarioStepRefType.COPY.name());
@ -640,6 +645,7 @@ public class ApiScenarioControllerTests extends BaseTest {
pluginStep.setName("plugin step");
pluginStep.setStepType(ApiScenarioStepType.API.name());
pluginStep.setChildren(getApiScenarioStepRequests());
pluginStep.setProjectId(DEFAULT_PROJECT_ID);
request.getSteps().add(pluginStep);
HashMap<Object, Object> pluginStepDetail = new HashMap<>();
pluginStepDetail.put("polymorphicName", "MsTCPSampler");
@ -686,7 +692,44 @@ public class ApiScenarioControllerTests extends BaseTest {
// 添加插件的环境配置供后续测试使用
Map<String, Map<String, Object>> pluginConfigMap = new HashMap<>();
pluginConfigMap.put("tcpp-sampler", new HashMap<>());
EnvScenarioScriptProcessor envScenarioScriptProcessor = new EnvScenarioScriptProcessor();
envScenarioScriptProcessor.setScript("test");
envScenarioScriptProcessor.setEnableCommonScript(false);
envScenarioScriptProcessor.setAssociateScenarioResult(true);
EnvScenarioScriptProcessor envScenarioScriptProcessor1 = BeanUtils.copyBean(new EnvScenarioScriptProcessor(), envScenarioScriptProcessor);
envScenarioScriptProcessor1.setAssociateScenarioResult(false);
SQLProcessor sqlProcessor = new SQLProcessor();
sqlProcessor.setScript("select * from test");
sqlProcessor.setName("select * from test");
EnvironmentConfig environmentConfig = new EnvironmentConfig();
EnvProcessorConfig preProcessorConfig = environmentConfig.getPreProcessorConfig();
EnvProcessorConfig postProcessorConfig = environmentConfig.getPostProcessorConfig();
List<MsProcessor> preProcessors = preProcessorConfig.getApiProcessorConfig().getScenarioProcessorConfig().getProcessors();
preProcessors.add(envScenarioScriptProcessor);
preProcessors.add(envScenarioScriptProcessor1);
preProcessors.add(sqlProcessor);
List<MsProcessor> postProcessors = postProcessorConfig.getApiProcessorConfig().getScenarioProcessorConfig().getProcessors();
postProcessors.add(envScenarioScriptProcessor);
postProcessors.add(envScenarioScriptProcessor1);
postProcessors.add(sqlProcessor);
EnvRequestScriptProcessor envRequestScriptProcessor = new EnvRequestScriptProcessor();
envRequestScriptProcessor.setScript("test");
envRequestScriptProcessor.setBeforeStepScript(true);
envRequestScriptProcessor.setIgnoreProtocols(List.of("TCP"));
EnvRequestScriptProcessor envRequestScriptProcessor1 = new EnvRequestScriptProcessor();
envRequestScriptProcessor1.setScript("test1");
envRequestScriptProcessor1.setBeforeStepScript(false);
envRequestScriptProcessor1.setIgnoreProtocols(List.of());
List<MsProcessor> preRequestProcessors = preProcessorConfig.getApiProcessorConfig().getRequestProcessorConfig().getProcessors();
preRequestProcessors.add(envRequestScriptProcessor);
preRequestProcessors.add(sqlProcessor);
List<MsProcessor> postRequestProcessors = postProcessorConfig.getApiProcessorConfig().getRequestProcessorConfig().getProcessors();
postRequestProcessors.add(envRequestScriptProcessor);
postRequestProcessors.add(sqlProcessor);
environmentConfig.setPluginConfigMap(pluginConfigMap);
envRequest.setConfig(environmentConfig);
Environment environment = environmentService.add(envRequest, "admin", null);

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.controller.param.ApiTestCaseAddRequestDefinition;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.definition.*;
@ -147,7 +148,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
apiDefinition.setProjectId(DEFAULT_PROJECT_ID);
apiDefinition.setName(StringUtils.join("接口定义", apiDefinition.getId()));
apiDefinition.setModuleId("case-moduleId");
apiDefinition.setProtocol("HTTP");
apiDefinition.setProtocol(ApiConstants.HTTP_PROTOCOL);
apiDefinition.setMethod("GET");
apiDefinition.setStatus("未规划");
apiDefinition.setNum(NumGenerator.nextNum(DEFAULT_PROJECT_ID, ApplicationNumScope.API_DEFINITION));

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.dto.request.http.MsHTTPElement;
import io.metersphere.api.service.ApiTestService;
import io.metersphere.system.base.BaseApiPluginTestService;
@ -36,7 +37,7 @@ public class ApiTestServiceTest extends BaseTest {
List<ProtocolDTO> protocols = apiTestService.getProtocols(this.DEFAULT_ORGANIZATION_ID);
List expected = new ArrayList<ProtocolDTO>();
ProtocolDTO httpProtocol = new ProtocolDTO();
httpProtocol.setProtocol("HTTP");
httpProtocol.setProtocol(ApiConstants.HTTP_PROTOCOL);
httpProtocol.setPolymorphicName(MsHTTPElement.class.getSimpleName());
ProtocolDTO jdbcProtocol = new ProtocolDTO();
jdbcProtocol.setProtocol("JDBC");

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiConstants;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.scenario.CsvVariable;
import io.metersphere.api.job.ApiScenarioScheduleJob;
@ -98,7 +99,7 @@ public class CleanupApiTests {
apiDefinition.setModuleId("test-module");
apiDefinition.setName("test");
apiDefinition.setPath("test");
apiDefinition.setProtocol("http");
apiDefinition.setProtocol(ApiConstants.HTTP_PROTOCOL);
apiDefinition.setMethod("test");
apiDefinition.setCreateUser("admin");
apiDefinition.setUpdateUser("admin");

View File

@ -134,6 +134,22 @@ public class MsHTTPElementTest {
@Test
public void processorParseTest() {
MsHTTPElement msHTTPElement = getAddProcessorHttpElement();
// 测试序列化
String json = ApiDataUtils.toJSONString(msHTTPElement);
Assertions.assertNotNull(json);
Assertions.assertEquals(ApiDataUtils.parseObject(json, AbstractMsTestElement.class), msHTTPElement);
// 测试脚本解析
ParameterConfig parameterConfig = new ApiParamConfig();
parameterConfig.setReportId("reportId");
TestElementParser defaultParser = TestElementParserFactory.getDefaultParser();
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(json, AbstractMsTestElement.class);
defaultParser.parse(msTestElement, parameterConfig);
}
public static MsHTTPElement getAddProcessorHttpElement() {
MsHTTPElement msHTTPElement = getMsHttpElement();
List processors = new ArrayList<>();
@ -219,17 +235,7 @@ public class MsHTTPElementTest {
linkedList.add(msCommonElement);
msHTTPElement.setChildren(linkedList);
// 测试序列化
String json = ApiDataUtils.toJSONString(msHTTPElement);
Assertions.assertNotNull(json);
Assertions.assertEquals(ApiDataUtils.parseObject(json, AbstractMsTestElement.class), msHTTPElement);
// 测试脚本解析
ParameterConfig parameterConfig = new ApiParamConfig();
parameterConfig.setReportId("reportId");
TestElementParser defaultParser = TestElementParserFactory.getDefaultParser();
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(json, AbstractMsTestElement.class);
defaultParser.parse(msTestElement, parameterConfig);
return msHTTPElement;
}
@Test

View File

@ -2,8 +2,8 @@ package io.metersphere.project.api.processor;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.metersphere.project.dto.environment.processors.RequestScriptProcessor;
import io.metersphere.project.dto.environment.processors.ScenarioScriptProcessor;
import io.metersphere.project.dto.environment.processors.EnvRequestScriptProcessor;
import io.metersphere.project.dto.environment.processors.EnvScenarioScriptProcessor;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@ -17,8 +17,8 @@ import lombok.Data;
* SQL {@link SQLProcessor}
* TIME_WAITING {@link TimeWaitingProcessor}
* EXTRACT {@link ExtractPostProcessor}
* SCENARIO_SCRIPT {@link ScenarioScriptProcessor}
* REQUEST_SCRIPT {@link RequestScriptProcessor}
* ENV_SCENARIO_SCRIPT {@link EnvScenarioScriptProcessor}
* ENV_REQUEST_SCRIPT {@link EnvRequestScriptProcessor}
* <pre>
* @Author: jianxing
* @CreateTime: 2023-11-07 10:17
@ -27,8 +27,8 @@ import lombok.Data;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "processorType")
@JsonSubTypes({
@JsonSubTypes.Type(value = ScriptProcessor.class),
@JsonSubTypes.Type(value = ScenarioScriptProcessor.class),
@JsonSubTypes.Type(value = RequestScriptProcessor.class),
@JsonSubTypes.Type(value = EnvScenarioScriptProcessor.class),
@JsonSubTypes.Type(value = EnvRequestScriptProcessor.class),
@JsonSubTypes.Type(value = SQLProcessor.class),
@JsonSubTypes.Type(value = TimeWaitingProcessor.class),
@JsonSubTypes.Type(value = ExtractPostProcessor.class),

View File

@ -7,6 +7,8 @@ import io.metersphere.system.valid.EnumValue;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Size;
import lombok.Data;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
@ -32,6 +34,7 @@ public class ScriptProcessor extends MsProcessor {
/**
* 是否启用公共脚本
* 默认为 false
* 环境脚本无须配置
*/
private Boolean enableCommonScript = false;
/**
@ -44,4 +47,11 @@ public class ScriptProcessor extends MsProcessor {
*/
@Valid
private List<KeyValueParam> params;
public boolean isValid() {
if (BooleanUtils.isTrue(enableCommonScript) && StringUtils.isBlank(scriptId)) {
return false;
}
return StringUtils.isNotBlank(script);
}
}

View File

@ -10,47 +10,32 @@ import io.metersphere.project.dto.environment.variables.CommonVariables;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
public class EnvironmentConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
public class EnvironmentConfig {
@Schema(description = "公共参数 请求超时时间、响应超时时间")
private CommonParams commonParams;
private CommonParams commonParams = new CommonParams();
@Schema(description = "环境变量")
private List<CommonVariables> commonVariables;
private List<CommonVariables> commonVariables = new ArrayList<>(0);
@Schema(description = "HTTP配置")
private List<HttpConfig> httpConfig;
private List<HttpConfig> httpConfig = new ArrayList<>(0);
@Schema(description = "数据库配置")
private List<DataSource> dataSources;
private List<DataSource> dataSources = new ArrayList<>(0);
@Schema(description = "Host配置")
private HostConfig hostConfig;
private HostConfig hostConfig = new HostConfig();
@Schema(description = "认证配置")
private AuthConfig authConfig;
private AuthConfig authConfig = new AuthConfig();
@Schema(description = "全局前置脚本")
private EnvProcessorConfig preProcessorConfig;
private EnvProcessorConfig preProcessorConfig = new EnvProcessorConfig();
@Schema(description = "全局后置脚本")
private EnvProcessorConfig postProcessorConfig;
private EnvProcessorConfig postProcessorConfig = new EnvProcessorConfig();
@Schema(description = "全局断言")
private MsEnvAssertionConfig assertionConfig;
private MsEnvAssertionConfig assertionConfig = new MsEnvAssertionConfig();
@Schema(description = "插件自定义的配置项key为插件IDvalue 为对应配置")
private Map<String, Map<String, Object>> pluginConfigMap;
public EnvironmentConfig() {
this.commonParams = new CommonParams();
this.commonVariables = List.of(new CommonVariables());
this.httpConfig = List.of(new HttpConfig());
this.dataSources = List.of(new DataSource());
this.hostConfig = new HostConfig();
this.authConfig = new AuthConfig();
this.preProcessorConfig = new EnvProcessorConfig();
this.postProcessorConfig = new EnvProcessorConfig();
this.assertionConfig = new MsEnvAssertionConfig();
}
private Map<String, Map<String, Object>> pluginConfigMap = HashMap.newHashMap(0);
}

View File

@ -28,7 +28,7 @@ public class EnvironmentInfoDTO implements Serializable {
private String name;
@Schema(description = "环境配置")
@NotNull(message = "{environment_config_is_null}", groups = {Created.class, Updated.class})
private EnvironmentConfig config;
private EnvironmentConfig config = new EnvironmentConfig();
@Schema(description = "是否是mock环境")
private Boolean mock;
@Schema(description = "描述")

View File

@ -3,6 +3,9 @@ package io.metersphere.project.dto.environment;
import io.metersphere.project.api.assertion.MsAssertion;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
@ -11,9 +14,12 @@ import java.util.List;
* @CreateTime: 2023-11-23 17:26
*/
@Data
public class MsEnvAssertionConfig {
public class MsEnvAssertionConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 断言列表
*/
private List<MsAssertion> assertions;
private List<MsAssertion> assertions = new ArrayList<>(0);
}

View File

@ -18,7 +18,7 @@ public class AuthConfig implements Serializable {
private String verification;
@Schema(description = "SSL配置")
private KeyStoreConfig sslConfig;
private KeyStoreConfig sslConfig = new KeyStoreConfig();
@Serial
private static final long serialVersionUID = 1L;

View File

@ -5,6 +5,7 @@ import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
@ -12,7 +13,7 @@ public class HostConfig implements Serializable {
@Schema(description = "启用Host")
private Boolean enable;
@Schema(description = "Host列表")
private List<Host> hosts;
private List<Host> hosts = new ArrayList<>(0);
@Serial
private static final long serialVersionUID = 1L;

View File

@ -4,6 +4,9 @@ import io.metersphere.project.api.processor.MsProcessor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
@ -12,10 +15,12 @@ import java.util.List;
* @CreateTime: 2024-02-01 14:53
*/
@Data
public class ApiEnvPlanProcessorConfig {
public class ApiEnvPlanProcessorConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
// 预留其他配置
@Schema(description = "前后置列表")
private List<MsProcessor> processors;
private List<MsProcessor> processors = new ArrayList<>(0);
}

View File

@ -3,16 +3,22 @@ package io.metersphere.project.dto.environment.processors;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @Author: jianxing
* @CreateTime: 2024-02-01 14:49
*/
@Data
public class ApiEnvProcessorConfig {
public class ApiEnvProcessorConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "测试计划级前后置配置")
private ApiEnvPlanProcessorConfig planProcessorConfig;
private ApiEnvPlanProcessorConfig planProcessorConfig = new ApiEnvPlanProcessorConfig();
@Schema(description = "场景级前后置配置")
private ApiEnvScenarioProcessorConfig scenarioProcessorConfig;
private ApiEnvScenarioProcessorConfig scenarioProcessorConfig = new ApiEnvScenarioProcessorConfig();
@Schema(description = "请求级前后置配置")
private ApiEnvRequestProcessorConfig requestProcessorConfig;
private ApiEnvRequestProcessorConfig requestProcessorConfig = new ApiEnvRequestProcessorConfig();
}

View File

@ -4,6 +4,9 @@ import io.metersphere.project.api.processor.MsProcessor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
@ -12,10 +15,12 @@ import java.util.List;
* @CreateTime: 2024-02-01 14:53
*/
@Data
public class ApiEnvRequestProcessorConfig {
public class ApiEnvRequestProcessorConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
// 预留其他配置
@Schema(description = "前后置列表")
private List<MsProcessor> processors;
private List<MsProcessor> processors = new ArrayList<>(0);
}

View File

@ -4,6 +4,9 @@ import io.metersphere.project.api.processor.MsProcessor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
@ -12,10 +15,12 @@ import java.util.List;
* @CreateTime: 2024-02-01 14:53
*/
@Data
public class ApiEnvScenarioProcessorConfig {
public class ApiEnvScenarioProcessorConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
// 预留其他配置
@Schema(description = "前后置列表")
private List<MsProcessor> processors;
private List<MsProcessor> processors = new ArrayList<>(0);
}

View File

@ -3,11 +3,17 @@ package io.metersphere.project.dto.environment.processors;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 环境的前后置配置
*/
@Data
public class EnvProcessorConfig {
public class EnvProcessorConfig implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "接口测试前后置配置")
private ApiEnvProcessorConfig apiProcessorConfig;
private ApiEnvProcessorConfig apiProcessorConfig = new ApiEnvProcessorConfig();
}

View File

@ -6,17 +6,18 @@ import io.metersphere.project.api.processor.ScriptProcessor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@JsonTypeName("REQUEST_SCRIPT")
public class RequestScriptProcessor extends ScriptProcessor {
@JsonTypeName("ENV_REQUEST_SCRIPT")
public class EnvRequestScriptProcessor extends ScriptProcessor {
/**
* 忽略的请求协议列表
*/
@Schema(description = "忽略请求")
private List<String> ignoreProtocols;
private List<String> ignoreProtocols = new ArrayList<>(0);
/**
* 是否是步骤内前置脚本前
*/

View File

@ -7,8 +7,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@JsonTypeName("SCENARIO_SCRIPT")
public class ScenarioScriptProcessor extends ScriptProcessor {
@JsonTypeName("ENV_SCENARIO_SCRIPT")
public class EnvScenarioScriptProcessor extends ScriptProcessor {
/**
* 是否关联场景结果默认否

View File

@ -5,6 +5,7 @@ import io.metersphere.project.domain.Project;
import io.metersphere.project.domain.ProjectExample;
import io.metersphere.project.dto.environment.*;
import io.metersphere.project.dto.environment.datasource.DataSource;
import io.metersphere.project.dto.environment.http.HttpConfig;
import io.metersphere.project.mapper.ExtEnvironmentMapper;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
@ -191,7 +192,12 @@ public class EnvironmentService {
String baseUrl = baseSystemConfigDTO.getUrl();
if (StringUtils.isNotEmpty(baseUrl)) {
Project project = projectMapper.selectByPrimaryKey(environment.getProjectId());
environmentInfoDTO.getConfig().getHttpConfig().getFirst().setUrl(StringUtils.join(baseUrl, MOCK_EVN_SOCKET, project.getNum()));
List<HttpConfig> httpConfigs = environmentInfoDTO.getConfig().getHttpConfig();
if (CollectionUtils.isEmpty(httpConfigs)) {
HttpConfig httpConfig = new HttpConfig();
httpConfig.setUrl(StringUtils.join(baseUrl, MOCK_EVN_SOCKET, project.getNum()));
httpConfigs.add(new HttpConfig());
}
}
}

View File

@ -317,18 +317,18 @@ public class EnvironmentControllerTests extends BaseTest {
ApiEnvPlanProcessorConfig apiEnvPlanProcessorConfig = new ApiEnvPlanProcessorConfig();
apiEnvPlanProcessorConfig.setProcessors(List.of(scriptProcessor, sqlProcessor));
apiScript.setPlanProcessorConfig(apiEnvPlanProcessorConfig);
ScenarioScriptProcessor scenarioScript = new ScenarioScriptProcessor();
EnvScenarioScriptProcessor scenarioScript = new EnvScenarioScriptProcessor();
scenarioScript.setScript("script");
scenarioScript.setName("场景级别脚本");
ApiEnvScenarioProcessorConfig apiEnvScenarioProcessorConfig = new ApiEnvScenarioProcessorConfig();
apiEnvScenarioProcessorConfig.setProcessors(List.of(scenarioScript, sqlProcessor));
apiScript.setScenarioProcessorConfig(apiEnvScenarioProcessorConfig);
RequestScriptProcessor stepScript = new RequestScriptProcessor();
EnvRequestScriptProcessor stepScript = new EnvRequestScriptProcessor();
stepScript.setScript("script");
stepScript.setName("步骤级别前置脚本前");
stepScript.setBeforeStepScript(true);
stepScript.setIgnoreProtocols(List.of("HTTP"));
RequestScriptProcessor stepScriptAfter = new RequestScriptProcessor();
EnvRequestScriptProcessor stepScriptAfter = new EnvRequestScriptProcessor();
stepScriptAfter.setScript("script");
stepScriptAfter.setName("步骤级别前置脚本后");
stepScriptAfter.setBeforeStepScript(false);

View File

@ -94,4 +94,24 @@ public class ApiPluginService {
}
return testElementPluginMap;
}
/**
* 返回 MsTestElement 实现类与接口协议的映射
* @return
*/
public Map<Class<? extends AbstractMsTestElement>, String> getTestElementProtocolMap() {
// 过滤协议插件
List<PluginWrapper> protocolPlugins = pluginLoadService.getMsPluginManager()
.getPlugins()
.stream()
.filter(plugin -> plugin.getPlugin() instanceof AbstractProtocolPlugin)
.toList();
Map<Class<? extends AbstractMsTestElement>, String> testElementProtocolMap = new HashMap<>();
for (PluginWrapper plugin : protocolPlugins) {
List<Class<? extends MsTestElement>> extensionClasses = plugin.getPluginManager().getExtensionClasses(MsTestElement.class);
extensionClasses.forEach(clazz -> testElementProtocolMap.put((Class<? extends AbstractMsTestElement>) clazz, ((AbstractProtocolPlugin) plugin.getPlugin()).getProtocol()));
}
return testElementProtocolMap;
}
}