feat(接口测试): 解析场景时设置环境参数

This commit is contained in:
AgAngle 2024-01-31 17:43:22 +08:00 committed by Craftsman
parent e5471f9c17
commit de3d90f420
24 changed files with 676 additions and 64 deletions

View File

@ -1,5 +1,6 @@
package io.metersphere.plugin.api.dto;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import lombok.Data;
/**
@ -7,11 +8,18 @@ import lombok.Data;
* @CreateTime: 2023-10-27 17:30
*/
@Data
public class ParameterConfig {
public abstract class ParameterConfig {
private String reportId;
/**
* 解析时是否解析 enable false 的组件
* 导出时需要解析
*/
private Boolean parseDisabledElement = false;
/**
* 获取当前插件对应的环境配置
* 调用示例 getProtocolEnvConfig(msTestElement);
* @param msTestElement 当前 AbstractMsTestElement 的实现类对象
* @return
*/
public abstract Object getProtocolEnvConfig(AbstractMsTestElement msTestElement);
}

View File

@ -14,7 +14,7 @@ import java.util.function.Function;
* @createTime 2021-10-30 10:07
* MsTestElement 具体实现类转换为 HashTree
*/
public abstract class AbstractJmeterElementConverter<T extends MsTestElement> {
public abstract class AbstractJmeterElementConverter<T extends MsTestElement> implements JmeterElementConverter {
public Class<? extends MsTestElement> testElementClass;

View File

@ -14,7 +14,6 @@ import java.util.LinkedList;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "polymorphicName")
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class AbstractMsTestElement implements MsTestElement {
/**
* 步骤ID唯一
*/
@ -23,11 +22,14 @@ public abstract class AbstractMsTestElement implements MsTestElement {
* 关联的资源ID用例ID/接口ID/场景ID)
*/
private String resourceId;
/**
* 当前的项目ID
*/
private String projectId;
/**
* 组件标签名称
*/
private String name;
/**
* 是否启用
*/

View File

@ -0,0 +1,12 @@
package io.metersphere.plugin.api.spi;
import org.pf4j.ExtensionPoint;
/**
* @author jianxing
* @createTime 2021-10-30 10:07
* MsTestElement 具体实现类转换为 HashTree
*/
public interface JmeterElementConverter extends ExtensionPoint {
}

View File

@ -0,0 +1,57 @@
package io.metersphere.api.dto;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import lombok.Data;
import java.util.Map;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 17:30
*/
@Data
public class ApiParamConfig extends ParameterConfig {
/**
* 报告ID
*/
private String reportId;
/**
* 环境配置信息
*/
private EnvironmentInfoDTO envConfig;
/**
* AbstractMsTestElement 实现类与插件 ID 的映射
* key AbstractMsTestElement 实现类对象
* value 为对应的插件 ID
*/
private Map<Class<? extends AbstractMsTestElement>, String> testElementClassPluginIdMap;
@Override
public Object getProtocolEnvConfig(AbstractMsTestElement msTestElement) {
return getProtocolEnvConfig(msTestElement, getEnvConfig());
}
/**
* 获取当前插件对应的环境配置
* @param msTestElement 当前的 AbstractMsTestElement 实现类
* @param envConfig 当前的环境配置信息
* @return
*/
public Object getProtocolEnvConfig(AbstractMsTestElement msTestElement,
EnvironmentInfoDTO envConfig) {
if (envConfig == null
|| envConfig.getConfig() == null
|| envConfig.getConfig().getPluginConfigMap() == null
|| testElementClassPluginIdMap == null
|| testElementClassPluginIdMap.get(msTestElement.getClass()) == null) {
return null;
}
Map<String, Object> pluginConfigMap = envConfig.getConfig().getPluginConfigMap();
String pluginId = testElementClassPluginIdMap.get(msTestElement.getClass());
return pluginConfigMap.get(pluginId);
}
}

View File

@ -0,0 +1,37 @@
package io.metersphere.api.dto;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import lombok.Data;
import org.apache.commons.lang3.BooleanUtils;
import java.util.Map;
/**
* @Author: jianxing
* @CreateTime: 2024-01-29 15:09
*/
@Data
public class ApiScenarioParamConfig extends ApiParamConfig {
/**
* 环境 Map
* key 为项目ID
* value 为环境信息
*/
private Map<String, EnvironmentInfoDTO> projectEnvMap;
/**
* 是否为环境组
* 是则使用 projectEnvMap
* 否则使用 envInfo
*/
private Boolean grouped;
@Override
public Object getProtocolEnvConfig(AbstractMsTestElement msTestElement) {
if (BooleanUtils.isTrue(grouped)) {
return getProtocolEnvConfig(msTestElement, projectEnvMap.get(msTestElement.getProjectId()));
} else {
return super.getProtocolEnvConfig(msTestElement);
}
}
}

View File

@ -0,0 +1,39 @@
package io.metersphere.api.dto;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @Author: jianxing
* @CreateTime: 2024-01-30 10:25
*/
@Data
public class ApiScenarioParseEnvInfo {
/**
* 引用的场景的环境信息
* key 为场景ID
* value 为环境ID信息
*/
private Map<String, EnvironmentModeDTO> refScenarioEnvMap;
/**
* 环境组信息
* key 为环境组ID
* value 为环境组下环境ID列表
*/
private Map<String, List<String>> envGroupMap;
/**
* 环境信息
* key 为环境ID
* value 环境信息
*/
Map<String, EnvironmentInfoDTO> envMap;
/**
* 环境配置信息
* key MsTestElement 实现类
* value 对应插件的环境配置
*/
private Map<Class<?>, Object> pluginClassEnvConfigMap;
}

View File

@ -0,0 +1,18 @@
package io.metersphere.api.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 选择的环境类型
* @Author: jianxing
* @CreateTime: 2024-01-29 15:30
*/
@Data
public class EnvironmentModeDTO {
@Schema(description = "是否为环境组")
private Boolean grouped;
@Schema(description = "环境或者环境组ID")
private String environmentId;
}

View File

@ -12,6 +12,9 @@ public class ApiDebugRunRequest {
@Schema(description = "接口ID")
@NotNull
private String id;
@Schema(description = "报告ID")
@NotNull
private String reportId;
@Schema(description = "环境ID")
private String environmentId;
@Schema(description = "点击调试时尚未保存的文件ID列表")

View File

@ -71,7 +71,7 @@ public class ApiDefinitionAddRequest implements Serializable {
@NotNull
private Object request;
@Schema(description = "请求内容")
@Schema(description = "响应内容")
@NotNull
private Object response;

View File

@ -1,12 +1,39 @@
package io.metersphere.api.dto.request;
import io.metersphere.api.dto.scenario.ScenarioConfig;
import io.metersphere.api.dto.scenario.ScenarioStepConfig;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Map;
@Data
@EqualsAndHashCode(callSuper = true)
public class MsScenario extends AbstractMsTestElement {
/**
* 场景配置
*/
private ScenarioConfig scenarioConfig;
/**
* 场景步骤的配置
*/
private ScenarioStepConfig scenarioStepConfig;
/**
* 环境 Map
* key 为项目ID
* value 为环境信息
*/
private Map<String, EnvironmentInfoDTO> projectEnvMap;
/**
* 环境信息
*/
private EnvironmentInfoDTO environmentInfo;
/**
* 是否为环境组
* 是则使用 projectEnvMap
* 否则使用 envInfo
*/
private Boolean grouped;
}

View File

@ -20,6 +20,11 @@ public class ApiScenarioDebugRequest {
@Size(max = 50, message = "{api_scenario.id.length_range}")
private String id;
@Schema(description = "报告ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
@Size(max = 50)
private String reportId;
@Schema(description = "是否为环境组")
private Boolean grouped = false;

View File

@ -0,0 +1,22 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.api.domain.ApiScenario;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class ScenarioStepConfig extends ApiScenario {
@Schema(description = "是否使用源场景环境")
private Boolean enableScenarioEnv;
@Schema(description = "是否使用当前场景参数如果为false则使用源场景参数")
private Boolean useCurrentScenarioParam = false;
/**
* 是否当前场景和源场景都应用
* 如果为 true则当前场景和源场景的参数都应用
* 如果为 false则根据 useCurrentScenarioParam 参数使用当前或者源场景的参数
*/
@Schema(description = "是否当前场景和源场景都应用")
private Boolean useBothScenarioParam = false;
}

View File

@ -1,11 +1,18 @@
package io.metersphere.api.parser.jmeter;
import io.metersphere.api.dto.ApiScenarioParamConfig;
import io.metersphere.api.dto.request.MsScenario;
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
import io.metersphere.api.dto.scenario.ScenarioStepConfig;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import io.metersphere.sdk.util.BeanUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.jorphan.collections.HashTree;
import java.util.Map;
/**
* @Author: jianxing
* @CreateTime: 2023-10-27 10:07
@ -16,8 +23,40 @@ public class MsScenarioConverter extends AbstractJmeterElementConverter<MsScenar
@Override
public void toHashTree(HashTree tree, MsScenario msScenario, ParameterConfig msParameter) {
ParameterConfig config = msParameter;
ApiScenarioParamConfig config = (ApiScenarioParamConfig) msParameter;
parseChild(tree, msScenario, config);
ApiScenarioParamConfig chileConfig = getChileConfig(msScenario, config);
parseChild(tree, msScenario, chileConfig);
}
/**
* 获取子步骤的配置信息
* 如果使用源场景环境则使用当前场景的环境信息
* @param msScenario
* @param config
* @return
*/
private ApiScenarioParamConfig getChileConfig(MsScenario msScenario, ApiScenarioParamConfig 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())) {
// 环境组设置环境Map
Map<String, EnvironmentInfoDTO> projectEnvMap = msScenario.getProjectEnvMap();
chileConfig.setProjectEnvMap(projectEnvMap);
} else {
// 设置环境信息
EnvironmentInfoDTO environmentInfo = msScenario.getEnvironmentInfo();
chileConfig.setEnvConfig(environmentInfo);
}
return chileConfig;
}
return config;
}
}

View File

@ -3,19 +3,16 @@ package io.metersphere.api.service;
import io.metersphere.api.config.JmeterProperties;
import io.metersphere.api.config.KafkaConfig;
import io.metersphere.api.controller.result.ApiResultCode;
import io.metersphere.api.dto.ApiParamConfig;
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
import io.metersphere.api.dto.request.controller.MsCommentScriptElement;
import io.metersphere.api.parser.TestElementParser;
import io.metersphere.api.parser.TestElementParserFactory;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.dto.customfunction.request.CustomFunctionRunRequest;
import io.metersphere.project.service.FileAssociationService;
import io.metersphere.project.service.FileManagementService;
import io.metersphere.project.service.FileMetadataService;
import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.project.service.*;
import io.metersphere.sdk.constants.ApiExecuteResourceType;
import io.metersphere.sdk.constants.ApiExecuteRunMode;
import io.metersphere.sdk.constants.ProjectApplicationType;
@ -32,7 +29,6 @@ import io.metersphere.system.dto.pool.TestResourceNodeDTO;
import io.metersphere.system.service.CommonProjectService;
import io.metersphere.system.service.SystemParameterService;
import io.metersphere.system.service.TestResourcePoolService;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.TaskRunnerClient;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
@ -110,7 +106,7 @@ public class ApiExecuteService {
return reportId + "_" + testId;
}
public void debug(ApiResourceRunRequest request) {
public void debug(ApiResourceRunRequest request, ApiParamConfig parameterConfig) {
String reportId = request.getReportId();
String testId = request.getTestId();
@ -124,14 +120,10 @@ public class ApiExecuteService {
// 设置执行文件参数
setTaskFileParam(request, taskRequest);
// todo 环境配置
// EnvironmentInfoDTO environmentInfoDTO = environmentService.get(request.getEnvironmentId());
// todo 误报
// todo 获取接口插件和jar包
// todo 处理公共脚本
// todo 接口用例 method 获取定义中的数据库字段
ParameterConfig parameterConfig = new ParameterConfig();
parameterConfig.setReportId(reportId);
String executeScript = parseExecuteScript(request.getTestElement(), parameterConfig);
TestResourceNodeDTO testResourceNodeDTO = getProjectExecuteNode(request.getProjectId());
@ -201,7 +193,7 @@ public class ApiExecuteService {
String testId = runRequest.getProjectId();
// 生成执行脚本
MsCommentScriptElement msCommentScriptElement = BeanUtils.copyBean(new MsCommentScriptElement(), runRequest);
String executeScript = parseExecuteScript(msCommentScriptElement, new ParameterConfig());
String executeScript = parseExecuteScript(msCommentScriptElement, new ApiParamConfig());
// 设置执行参数
TaskRequestDTO taskRequest = new TaskRequestDTO();
setServerInfoParam(taskRequest);

View File

@ -4,6 +4,7 @@ import io.metersphere.api.constants.ApiResourceType;
import io.metersphere.api.domain.ApiDebug;
import io.metersphere.api.domain.ApiDebugBlob;
import io.metersphere.api.domain.ApiDebugExample;
import io.metersphere.api.dto.ApiParamConfig;
import io.metersphere.api.dto.debug.*;
import io.metersphere.api.mapper.ApiDebugBlobMapper;
import io.metersphere.api.mapper.ApiDebugMapper;
@ -12,6 +13,8 @@ import io.metersphere.api.service.ApiExecuteService;
import io.metersphere.api.service.ApiFileResourceService;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import io.metersphere.project.service.EnvironmentService;
import io.metersphere.project.service.ProjectService;
import io.metersphere.sdk.constants.ApiExecuteRunMode;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
@ -20,6 +23,7 @@ import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.FileAssociationSourceUtil;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.service.ApiPluginService;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
@ -50,6 +54,10 @@ public class ApiDebugService {
private ApiFileResourceService apiFileResourceService;
@Resource
private ApiExecuteService apiExecuteService;
@Resource
private ApiPluginService apiPluginService;
@Resource
private EnvironmentService environmentService;
public static final Long ORDER_STEP = 5000L;
@ -200,7 +208,14 @@ public class ApiDebugService {
runRequest.setEnvironmentId(request.getEnvironmentId());
runRequest.setTestElement(ApiDataUtils.parseObject(JSON.toJSONString(request.getRequest()), AbstractMsTestElement.class));
apiExecuteService.debug(runRequest);
ApiParamConfig paramConfig = new ApiParamConfig();
paramConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap());
paramConfig.setReportId(request.getReportId());
EnvironmentInfoDTO environmentInfoDTO = environmentService.get(request.getEnvironmentId());
// 设置环境
paramConfig.setEnvConfig(environmentInfoDTO);
apiExecuteService.debug(runRequest, paramConfig);
return runRequest.getReportId();
}

View File

@ -4,6 +4,9 @@ import io.metersphere.api.constants.ApiResourceType;
import io.metersphere.api.constants.ApiScenarioStepRefType;
import io.metersphere.api.constants.ApiScenarioStepType;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.ApiScenarioParamConfig;
import io.metersphere.api.dto.ApiScenarioParseEnvInfo;
import io.metersphere.api.dto.EnvironmentModeDTO;
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
import io.metersphere.api.dto.request.MsScenario;
@ -20,10 +23,9 @@ import io.metersphere.api.service.definition.ApiTestCaseService;
import io.metersphere.api.utils.ApiScenarioBatchOperationUtils;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.domain.FileMetadata;
import io.metersphere.project.dto.environment.EnvironmentInfoDTO;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.service.FileAssociationService;
import io.metersphere.project.service.FileMetadataService;
import io.metersphere.project.service.ProjectService;
import io.metersphere.project.service.*;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.domain.Environment;
import io.metersphere.sdk.domain.EnvironmentExample;
@ -45,6 +47,7 @@ import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.mapper.ScheduleMapper;
import io.metersphere.system.schedule.ScheduleService;
import io.metersphere.system.service.ApiPluginService;
import io.metersphere.system.service.UserLoginService;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
@ -132,6 +135,12 @@ public class ApiScenarioService {
private ScheduleService scheduleService;
@Resource
private ScheduleMapper scheduleMapper;
@Resource
private EnvironmentService environmentService;
@Resource
private EnvironmentGroupService environmentGroupService;
@Resource
private ApiPluginService apiPluginService;
public static final String PRIORITY = "Priority";
public static final String STATUS = "Status";
@ -1000,7 +1009,6 @@ public class ApiScenarioService {
public String debug(ApiScenarioDebugRequest request) {
ApiScenario apiScenario = apiScenarioMapper.selectByPrimaryKey(request.getId());
boolean hasSave = apiScenario != null;
String reportId = IDGenerator.nextStr();
List<ApiScenarioStepRequest> steps = request.getSteps();
@ -1017,12 +1025,15 @@ public class ApiScenarioService {
// 解析生成待执行的场景树
MsScenario msScenario = new MsScenario();
msScenario.setScenarioConfig(getScenarioConfig(request, hasSave));
parseStep2MsElement(msScenario, steps, resourceBlobMap, detailMap);
// 获取场景环境相关配置
ApiScenarioParseEnvInfo scenarioParseEnvInfo = getScenarioParseEnvInfo(refResourceMap, request.getEnvironmentId(), request.getGrouped());
parseStep2MsElement(msScenario, steps, resourceBlobMap, detailMap, scenarioParseEnvInfo);
ApiResourceRunRequest runRequest = BeanUtils.copyBean(new ApiResourceRunRequest(), request);
runRequest.setProjectId(request.getProjectId());
runRequest.setTestId(request.getId());
runRequest.setReportId(reportId);
runRequest.setReportId(request.getReportId());
runRequest.setResourceType(ApiResourceType.API_SCENARIO.name());
runRequest.setRunMode(ApiExecuteRunMode.BACKEND_DEBUG.name());
runRequest.setTempFileIds(request.getTempFileIds());
@ -1030,9 +1041,85 @@ public class ApiScenarioService {
runRequest.setEnvironmentId(request.getEnvironmentId());
runRequest.setTestElement(msScenario);
apiExecuteService.debug(runRequest);
ApiScenarioParamConfig parseConfig = new ApiScenarioParamConfig();
parseConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap());
parseConfig.setGrouped(request.getGrouped());
parseConfig.setReportId(request.getReportId());
scenarioParseEnvInfo.getPluginClassEnvConfigMap();
if (BooleanUtils.isTrue(request.getGrouped())) {
// 设置环境组 map
parseConfig.setProjectEnvMap(getProjectEnvMap(scenarioParseEnvInfo, request.getEnvironmentId()));
} else {
// 设置环境
parseConfig.setEnvConfig(scenarioParseEnvInfo.getEnvMap().get(request.getEnvironmentId()));
}
return reportId;
apiExecuteService.debug(runRequest, parseConfig);
return request.getReportId();
}
/**
* 设置脚本解析-环境相关参数
*
* @param refResourceMap
* @return
*/
private ApiScenarioParseEnvInfo getScenarioParseEnvInfo(Map<String, List<String>> refResourceMap, String currentEnvId, Boolean isCurrentEnvGrouped) {
List<String> apiScenarioIds = refResourceMap.get(ApiScenarioStepType.API_SCENARIO.name());
List<String> envIds = new ArrayList<>();
List<String> envGroupIds = new ArrayList<>();
ApiScenarioParseEnvInfo envInfo = new ApiScenarioParseEnvInfo();
if (BooleanUtils.isTrue(isCurrentEnvGrouped)) {
envGroupIds.add(currentEnvId);
} else {
envIds.add(currentEnvId);
}
if (CollectionUtils.isNotEmpty(apiScenarioIds)) {
Map<String, EnvironmentModeDTO> refScenarioEnvMap = new HashMap<>();
List<ApiScenario> apiScenarios = getApiScenarioByIds(apiScenarioIds);
for (ApiScenario scenario : apiScenarios) {
EnvironmentModeDTO envMode = new EnvironmentModeDTO();
envMode.setEnvironmentId(scenario.getEnvironmentId());
envMode.setGrouped(scenario.getGrouped());
if (BooleanUtils.isTrue(scenario.getGrouped())) {
// 记录环境组ID
envGroupIds.add(scenario.getEnvironmentId());
} else {
// 记录环境ID
envIds.add(scenario.getEnvironmentId());
}
// 保存场景的环境配置信息
refScenarioEnvMap.put(scenario.getId(), envMode);
}
envInfo.setRefScenarioEnvMap(refScenarioEnvMap);
}
// 查询环境组中的环境ID列表
Map<String, List<String>> envGroupMap = new HashMap<>();
environmentGroupService.getEnvironmentGroupRelations(envGroupIds).forEach(environmentGroupRelation -> {
envGroupMap.putIfAbsent(environmentGroupRelation.getEnvironmentGroupId(), new ArrayList<>());
envGroupMap.get(environmentGroupRelation.getEnvironmentGroupId()).add(environmentGroupRelation.getEnvironmentId());
envIds.add(environmentGroupRelation.getEnvironmentId());
});
// 获取环境的配置信息
List<String> distinctEnvIds = envIds.stream().distinct().toList();
Map<String, EnvironmentInfoDTO> envMap = environmentService.getByIds(distinctEnvIds)
.stream()
.collect(Collectors.toMap(EnvironmentInfoDTO::getId, Function.identity()));
envInfo.setEnvGroupMap(envGroupMap);
envInfo.setEnvMap(envMap);
return envInfo;
}
private List<ApiScenario> getApiScenarioByIds(List<String> apiScenarioIds) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andIdIn(apiScenarioIds);
return apiScenarioMapper.selectByExample(example);
}
/**
@ -1041,7 +1128,8 @@ public class ApiScenarioService {
private void parseStep2MsElement(AbstractMsTestElement parentElement,
List<? extends ApiScenarioStepCommonDTO> steps,
Map<String, String> resourceBlobMap,
Map<String, String> stepDetailMap) {
Map<String, String> stepDetailMap,
ApiScenarioParseEnvInfo scenarioParseEnvInfo) {
if (CollectionUtils.isNotEmpty(steps)) {
parentElement.setChildren(new LinkedList<>());
}
@ -1055,14 +1143,68 @@ public class ApiScenarioService {
// 将步骤详情解析生成对应的MsTestElement
AbstractMsTestElement msTestElement = stepParser.parseTestElement(step, resourceBlobMap.get(step.getResourceId()), stepDetailMap.get(step.getId()));
if (msTestElement != null) {
setMsScenarioParam(scenarioParseEnvInfo, step, msTestElement);
parentElement.getChildren().add(msTestElement);
}
if (CollectionUtils.isNotEmpty(step.getChildren())) {
parseStep2MsElement(msTestElement, step.getChildren(), resourceBlobMap, stepDetailMap);
parseStep2MsElement(msTestElement, step.getChildren(), resourceBlobMap, stepDetailMap, scenarioParseEnvInfo);
}
}
}
private void setMsScenarioParam(ApiScenarioParseEnvInfo scenarioParseEnvInfo,
ApiScenarioStepCommonDTO step,
AbstractMsTestElement msTestElement) {
// 引用的场景设置场景参数
if (!isScenarioStep(step.getStepType()) || !isRef(step.getRefType()) || !(msTestElement instanceof MsScenario)) {
return;
}
MsScenario msScenario = (MsScenario) msTestElement;
if (step.getConfig() != null) {
// 设置场景步骤的运行参数
msScenario.setScenarioStepConfig(JSON.parseObject(JSON.toJSONString(step.getConfig()), ScenarioStepConfig.class));
}
// 获取当前场景配置的环境信息
EnvironmentModeDTO environmentModeDTO = scenarioParseEnvInfo.getRefScenarioEnvMap().get(step.getResourceId());
String environmentId = environmentModeDTO.getEnvironmentId();
// 设置是否是环境组
Boolean isGrouped = environmentModeDTO.getGrouped();
msScenario.setGrouped(isGrouped);
Map<String, EnvironmentInfoDTO> envMap = scenarioParseEnvInfo.getEnvMap();
if (BooleanUtils.isTrue(isGrouped)) {
// 设置环境组 map
msScenario.setProjectEnvMap(getProjectEnvMap(scenarioParseEnvInfo, environmentId));
} else {
// 设置环境
msScenario.setEnvironmentInfo(envMap.get(environmentId));
}
}
/**
* scenarioParseEnvInfo 获取对应环境组的 projectEnvMap
* @param scenarioParseEnvInfo
* @param environmentId
* @return
*/
private Map<String, EnvironmentInfoDTO> getProjectEnvMap(ApiScenarioParseEnvInfo scenarioParseEnvInfo, String environmentId) {
Map<String, List<String>> envGroupMap = scenarioParseEnvInfo.getEnvGroupMap();
List<String> envIds = envGroupMap.get(environmentId);
Map<String, EnvironmentInfoDTO> projectEnvMap = new HashMap<>();
for (String envId : envIds) {
EnvironmentInfoDTO environmentInfoDTO = scenarioParseEnvInfo.getEnvMap().get(envId);
projectEnvMap.put(environmentInfoDTO.getProjectId(), environmentInfoDTO);
}
return projectEnvMap;
}
private static boolean isScenarioStep(String stepType) {
return StringUtils.equals(stepType, ApiScenarioStepType.API_SCENARIO.name());
}
/**
* 设置单个部分引用的步骤的启用状态
*/
@ -1098,7 +1240,7 @@ public class ApiScenarioService {
}
private boolean isPartialRef(ApiScenarioStepCommonDTO step) {
return StringUtils.equals(step.getStepType(), ApiScenarioStepType.API_SCENARIO.name()) &&
return isScenarioStep(step.getStepType()) &&
StringUtils.equals(step.getRefType(), ApiScenarioStepRefType.PARTIAL_REF.name());
}
@ -1339,7 +1481,7 @@ public class ApiScenarioService {
* 判断步骤是否是引用的场景
*/
private boolean isRefApiScenario(ApiScenarioStepDTO step) {
return isRef(step.getRefType()) && StringUtils.equals(step.getStepType(), ApiScenarioStepType.API_SCENARIO.name());
return isRef(step.getRefType()) && isScenarioStep(step.getStepType());
}
/**

View File

@ -6,7 +6,6 @@ import io.metersphere.api.domain.ApiDebugBlob;
import io.metersphere.api.domain.ApiFileResource;
import io.metersphere.api.dto.debug.*;
import io.metersphere.api.dto.request.MsCommonElement;
import io.metersphere.api.dto.request.MsScenario;
import io.metersphere.api.dto.request.assertion.MsAssertionConfig;
import io.metersphere.api.dto.request.http.MsHTTPElement;
import io.metersphere.api.dto.request.http.body.Body;
@ -14,11 +13,9 @@ import io.metersphere.api.mapper.ApiDebugBlobMapper;
import io.metersphere.api.mapper.ApiDebugMapper;
import io.metersphere.api.parser.ImportParserFactory;
import io.metersphere.api.parser.TestElementParserFactory;
import io.metersphere.api.parser.jmeter.MsScenarioConverter;
import io.metersphere.api.service.ApiFileResourceService;
import io.metersphere.api.service.BaseResourcePoolTestService;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.plugin.api.dto.ParameterConfig;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.dto.filemanagement.FileInfo;
import io.metersphere.project.dto.filemanagement.request.FileUploadRequest;
@ -35,9 +32,9 @@ import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.TestResourcePool;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.jorphan.collections.ListedHashTree;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
@ -364,6 +361,7 @@ public class ApiDebugControllerTests extends BaseTest {
msHTTPElement.setPath("/test");
msHTTPElement.setMethod("GET");
request.setRequest(JSON.parseObject(ApiDataUtils.toJSONString(msHTTPElement)));
request.setReportId(IDGenerator.nextStr());
// @校验组织没有资源池权限异常
assertErrorCode(this.requestPost(DEBUG, request), ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);
@ -416,8 +414,6 @@ public class ApiDebugControllerTests extends BaseTest {
// 增加覆盖率
new TestElementParserFactory();
new ImportParserFactory();
MsScenarioConverter msScenarioConverter = new MsScenarioConverter();
msScenarioConverter.toHashTree(new ListedHashTree(), new MsScenario(), new ParameterConfig());
// @@校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_EXECUTE, DEBUG, request);

View File

@ -21,8 +21,18 @@ import io.metersphere.api.service.definition.ApiDefinitionService;
import io.metersphere.api.service.definition.ApiTestCaseService;
import io.metersphere.api.service.scenario.ApiScenarioService;
import io.metersphere.api.utils.ApiDataUtils;
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.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.filemanagement.request.FileUploadRequest;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.service.EnvironmentGroupService;
import io.metersphere.project.service.EnvironmentService;
import io.metersphere.project.service.FileMetadataService;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.domain.Environment;
@ -37,9 +47,13 @@ import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.domain.Schedule;
import io.metersphere.system.dto.request.PluginUpdateRequest;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.mapper.ScheduleMapper;
import io.metersphere.system.service.PluginLoadService;
import io.metersphere.system.service.PluginService;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.CheckLogModel;
@ -55,11 +69,14 @@ import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultMatcher;
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import static io.metersphere.api.controller.result.ApiResultCode.API_SCENARIO_EXIST;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -120,6 +137,14 @@ public class ApiScenarioControllerTests extends BaseTest {
private ApiScenarioService apiScenarioService;
@Resource
private ScheduleMapper scheduleMapper;
@Resource
private EnvironmentService environmentService;
@Resource
private EnvironmentGroupService environmentGroupService;
@Resource
private PluginService pluginService;
@Resource
private PluginLoadService pluginLoadService;
private static String fileMetadataId;
private static String localFileId;
private static ApiScenario addApiScenario;
@ -128,6 +153,8 @@ public class ApiScenarioControllerTests extends BaseTest {
private static List<ApiScenarioStepRequest> anOtherAddApiScenarioSteps;
private static ApiDefinition apiDefinition;
private static ApiTestCase apiTestCase;
private static String envId;
private static String envGroupId;
private static final List<CheckLogModel> LOG_CHECK_LIST = new ArrayList<>();
@ -254,6 +281,7 @@ public class ApiScenarioControllerTests extends BaseTest {
@Order(1)
public void add() throws Exception {
initTestData();
initEnv();
// @@请求成功
ApiScenarioAddRequest request = new ApiScenarioAddRequest();
@ -262,7 +290,7 @@ public class ApiScenarioControllerTests extends BaseTest {
request.setName("test name");
request.setModuleId("default");
request.setGrouped(false);
request.setEnvironmentId("environmentId");
request.setEnvironmentId(envId);
request.setTags(List.of("tag1", "tag2"));
request.setPriority("P0");
request.setStatus(ApiScenarioStatus.COMPLETED.name());
@ -281,6 +309,8 @@ public class ApiScenarioControllerTests extends BaseTest {
assertUpdateSteps(steps, steptDetailMap);
request.setName("anOther name");
request.setGrouped(true);
request.setEnvironmentId(envGroupId);
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
stepRequest.setId(IDGenerator.nextStr());
stepRequest.setEnable(true);
@ -483,7 +513,7 @@ public class ApiScenarioControllerTests extends BaseTest {
request.setName("test name update");
request.setModuleId("default");
request.setGrouped(false);
request.setEnvironmentId("environmentId update");
request.setEnvironmentId(envId);
request.setTags(List.of("tag1 update", "tag2 update"));
request.setPriority("P0 update");
request.setStatus(ApiScenarioStatus.DEPRECATED.name());
@ -555,27 +585,33 @@ public class ApiScenarioControllerTests extends BaseTest {
public void debug() throws Exception {
mockPost("/api/debug", "");
baseResourcePoolTestService.initProjectResourcePool();
// @@请求成功
ApiScenarioDebugRequest request = new ApiScenarioDebugRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setScenarioConfig(new ScenarioConfig());
request.setEnvironmentId("environmentId");
request.setEnvironmentId(envId);
request.setGrouped(false);
ScenarioStepConfig scenarioStepConfig = new ScenarioStepConfig();
scenarioStepConfig.setEnableScenarioEnv(true);
List<ApiScenarioStepRequest> steps = getApiScenarioStepRequests();
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();
stepRequest.setName("test step");
stepRequest.setId(IDGenerator.nextStr());
stepRequest.setId(IDGenerator.nextStr());
stepRequest.setRefType(ApiScenarioStepRefType.REF.name());
stepRequest.setResourceId(addApiScenario.getId());
stepRequest.setResourceNum(addApiScenario.getNum().toString());
stepRequest.setName(addApiScenario.getName());
stepRequest.setStepType(ApiScenarioStepType.API_SCENARIO.name());
stepRequest.setChildren(getApiScenarioStepRequests());
stepRequest.setConfig(scenarioStepConfig);
steps.add(stepRequest);
ApiScenarioStepRequest copyScenarioStep = BeanUtils.copyBean(new ApiScenarioStepRequest(), stepRequest);
copyScenarioStep.setRefType(ApiScenarioStepRefType.COPY.name());
copyScenarioStep.setChildren(getApiScenarioStepRequests());
steps.add(stepRequest);
steps.add(copyScenarioStep);
ApiScenarioStepRequest partialScenarioStep = BeanUtils.copyBean(new ApiScenarioStepRequest(), stepRequest);
partialScenarioStep.setRefType(ApiScenarioStepRefType.PARTIAL_REF.name());
partialScenarioStep.setChildren(getApiScenarioStepRequests());
@ -583,12 +619,85 @@ public class ApiScenarioControllerTests extends BaseTest {
request.setId(addApiScenario.getId());
request.setSteps(steps);
request.setStepDetails(new HashMap<>());
request.setReportId(IDGenerator.nextStr());
this.requestPostWithOk(DEBUG, request);
request.setEnvironmentId(envGroupId);
request.setGrouped(true);
this.requestPostWithOk(DEBUG, request);
ApiScenarioStepRequest pluginStep = new ApiScenarioStepRequest();
pluginStep.setName("plugin step");
pluginStep.setId(IDGenerator.nextStr());
pluginStep.setRefType(ApiScenarioStepRefType.COPY.name());
pluginStep.setRefType(ApiScenarioStepRefType.COPY.name());
pluginStep.setResourceId("");
pluginStep.setResourceNum("11111");
pluginStep.setName("plugin step");
pluginStep.setStepType(ApiScenarioStepType.API.name());
pluginStep.setChildren(getApiScenarioStepRequests());
request.getSteps().add(pluginStep);
HashMap<Object, Object> pluginStepDetail = new HashMap<>();
pluginStepDetail.put("polymorphicName", "MsTCPSampler");
pluginStepDetail.put("port", "port");
pluginStepDetail.put("projectId", DEFAULT_PROJECT_ID);
request.getStepDetails().put(pluginStep.getId(), pluginStepDetail);
Plugin plugin = addEnvTestPlugin();
List<Class<? extends MsTestElement>> msTestElementClasses =
pluginLoadService.getMsPluginManager().getExtensionClasses(MsTestElement.class);
// 注册序列化类
msTestElementClasses.forEach(ApiDataUtils::setResolver);
// 注册转换器
List<Class<? extends JmeterElementConverter>> converterClasses =
pluginLoadService.getMsPluginManager().getExtensionClasses(JmeterElementConverter.class);
converterClasses.forEach(item -> JmeterElementConverterRegister.register((Class<? extends AbstractJmeterElementConverter<? extends MsTestElement>>) item));
this.requestPostWithOk(DEBUG, request);
pluginService.delete(plugin.getId());
// @@校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE, DEBUG, request);
}
public Plugin addEnvTestPlugin() throws Exception {
PluginUpdateRequest request = new PluginUpdateRequest();
File jarFile = new File(
this.getClass().getClassLoader().getResource("file/tcpp-sampler-env-test.jar")
.getPath()
);
FileInputStream inputStream = new FileInputStream(jarFile);
MockMultipartFile mockMultipartFile = new MockMultipartFile(jarFile.getName(), jarFile.getName(), "jar", inputStream);
request.setName("env_test");
request.setGlobal(true);
request.setEnable(true);
request.setCreateUser(ADMIN.name());
return pluginService.add(request, mockMultipartFile);
}
private void initEnv() {
EnvironmentRequest envRequest = new EnvironmentRequest();
envRequest.setProjectId(DEFAULT_PROJECT_ID);
envRequest.setName("test scenario debug");
// 添加插件的环境配置供后续测试使用
Map<String, Object> pluginConfigMap = new HashMap<>();
pluginConfigMap.put("tcpp-sampler", new HashMap<>());
EnvironmentConfig environmentConfig = new EnvironmentConfig();
environmentConfig.setPluginConfigMap(pluginConfigMap);
envRequest.setConfig(environmentConfig);
Environment environment = environmentService.add(envRequest, "admin", null);
envId = environment.getId();
EnvironmentGroupRequest groupRequest = new EnvironmentGroupRequest();
groupRequest.setProjectId(DEFAULT_PROJECT_ID);
groupRequest.setName("test scenario debug");
EnvironmentGroupProjectDTO environmentGroupProjectDTO = new EnvironmentGroupProjectDTO();
environmentGroupProjectDTO.setEnvironmentId(environment.getId());
environmentGroupProjectDTO.setProjectId(DEFAULT_PROJECT_ID);
groupRequest.setEnvGroupProject(List.of(environmentGroupProjectDTO));
envGroupId = environmentGroupService.add(groupRequest, "admin").getId();
}
@Test
@Order(7)
public void get() throws Exception {

View File

@ -1,6 +1,7 @@
package io.metersphere.api.controller;
import io.metersphere.api.dto.ApiFile;
import io.metersphere.api.dto.ApiParamConfig;
import io.metersphere.api.dto.definition.HttpResponse;
import io.metersphere.api.dto.request.MsCommonElement;
import io.metersphere.api.dto.request.assertion.*;
@ -218,7 +219,7 @@ public class MsHTTPElementTest {
Assertions.assertEquals(ApiDataUtils.parseObject(json, AbstractMsTestElement.class), msHTTPElement);
// 测试脚本解析
ParameterConfig parameterConfig = new ParameterConfig();
ParameterConfig parameterConfig = new ApiParamConfig();
parameterConfig.setReportId("reportId");
TestElementParser defaultParser = TestElementParserFactory.getDefaultParser();
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(json, AbstractMsTestElement.class);
@ -247,7 +248,7 @@ public class MsHTTPElementTest {
Assertions.assertEquals(ApiDataUtils.parseObject(json, AbstractMsTestElement.class), msHTTPElement);
// 测试脚本解析
ParameterConfig parameterConfig = new ParameterConfig();
ParameterConfig parameterConfig = new ApiParamConfig();
parameterConfig.setReportId("reportId");
TestElementParser defaultParser = TestElementParserFactory.getDefaultParser();
AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(json, AbstractMsTestElement.class);

View File

@ -10,7 +10,6 @@ import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.InternalUserRole;
import io.metersphere.sdk.domain.*;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.mapper.EnvironmentBlobMapper;
import io.metersphere.sdk.mapper.EnvironmentGroupMapper;
import io.metersphere.sdk.mapper.EnvironmentGroupRelationMapper;
import io.metersphere.sdk.mapper.EnvironmentMapper;
@ -26,6 +25,7 @@ import io.metersphere.system.mapper.UserRoleRelationMapper;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
@ -35,10 +35,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -58,13 +55,13 @@ public class EnvironmentGroupService {
@Resource
private EnvironmentMapper environmentMapper;
@Resource
private EnvironmentBlobMapper environmentBlobMapper;
@Resource
private UserRoleRelationMapper userRoleRelationMapper;
@Resource
private ExtProjectMapper extProjectMapper;
@Resource
private OrganizationMapper organizationMapper;
@Resource
private EnvironmentService environmentService;
public static final Long ORDER_STEP = 5000L;
@ -185,13 +182,9 @@ public class EnvironmentGroupService {
List<EnvironmentGroupRelation> relations = environmentGroupRelationMapper.selectByExample(example);
//提取环境id
List<String> envIds = relations.stream().map(EnvironmentGroupRelation::getEnvironmentId).distinct().toList();
EnvironmentExample environmentExample = new EnvironmentExample();
environmentExample.createCriteria().andIdIn(envIds);
List<Environment> environments = environmentMapper.selectByExample(environmentExample);
List<Environment> environments = environmentService.getEnvironmentsByIds(envIds);
Map<String, Environment> envMap = environments.stream().collect(Collectors.toMap(Environment::getId, e -> e));
EnvironmentBlobExample environmentBlobExample = new EnvironmentBlobExample();
environmentBlobExample.createCriteria().andIdIn(envIds);
List<EnvironmentBlob> environmentBlobs = environmentBlobMapper.selectByExampleWithBLOBs(environmentBlobExample);
List<EnvironmentBlob> environmentBlobs = environmentService.getEnvironmentBlobsByIds(envIds);
Map<String, EnvironmentBlob> envBlobMap = environmentBlobs.stream().collect(Collectors.toMap(EnvironmentBlob::getId, e -> e));
List<EnvironmentGroupInfo> result = new ArrayList<>();
relations.forEach(e -> {
@ -250,4 +243,14 @@ public class EnvironmentGroupService {
extEnvironmentMapper::getGroupLastPos,
environmentGroupMapper::updateByPrimaryKeySelective);
}
public List<EnvironmentGroupRelation> getEnvironmentGroupRelations(List<String> envGroupIds) {
if (CollectionUtils.isEmpty(envGroupIds)) {
return Collections.emptyList();
}
EnvironmentGroupRelationExample example = new EnvironmentGroupRelationExample();
example.createCriteria().andEnvironmentGroupIdIn(envGroupIds);
List<EnvironmentGroupRelation> relations = environmentGroupRelationMapper.selectByExample(example);
return relations;
}
}

View File

@ -2,6 +2,7 @@ package io.metersphere.project.service;
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.mapper.ExtEnvironmentMapper;
@ -48,6 +49,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.sql.Driver;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@ -73,6 +75,8 @@ public class EnvironmentService {
private ApiPluginService apiPluginService;
@Resource
private PluginScriptService pluginScriptService;
@Resource
private SystemParameterService systemParameterService;
public static final Long ORDER_STEP = 5000L;
private static final String USERNAME = "user";
@ -223,9 +227,7 @@ public class EnvironmentService {
public List<EnvironmentRequest> exportEnv(TableBatchProcessDTO request, String projectId) {
List<String> environmentIds = this.getEnvironmentIds(request, projectId);
// 查询环境
EnvironmentExample environmentExample = new EnvironmentExample();
environmentExample.createCriteria().andIdIn(environmentIds);
List<Environment> environments = environmentMapper.selectByExample(environmentExample);
List<Environment> environments = getEnvironmentsByIds(environmentIds);
Map<String, Environment> environmentMap = new HashMap<>();
environments.forEach(environment -> environmentMap.put(environment.getId(), environment));
// 查询环境配置
@ -396,4 +398,74 @@ public class EnvironmentService {
return envPluginScript;
}).toList();
}
public List<EnvironmentInfoDTO> getByIds(List<String> envIds) {
if (CollectionUtils.isEmpty(envIds)) {
return Collections.emptyList();
}
List<Environment> environments = getEnvironmentsByIds(envIds);
Map<String, EnvironmentBlob> envBlobMap = getEnvironmentBlobsByIds(envIds).stream().
collect(Collectors.toMap(EnvironmentBlob::getId, Function.identity()));
List<String> projectIds = environments.stream()
.map(Environment::getProjectId)
.distinct()
.collect(Collectors.toList());
Map<String, Project> projectMap = getProjects(projectIds).stream()
.collect(Collectors.toMap(Project::getId, Function.identity()));
String baseUrl = systemParameterService.getBaseInfo().getUrl();
List<EnvironmentInfoDTO> environmentInfos = new ArrayList<>();
for (Environment environment : environments) {
EnvironmentInfoDTO environmentInfo = BeanUtils.copyBean(new EnvironmentInfoDTO(), environment);
EnvironmentBlob environmentBlob = envBlobMap.get(environment.getId());
if (environmentBlob == null) {
environmentInfo.setConfig(new EnvironmentConfig());
} else {
if (environmentBlob.getConfig() != null) {
environmentInfo.setConfig(JSON.parseObject(new String(environmentBlob.getConfig()), EnvironmentConfig.class));
}
}
if (BooleanUtils.isTrue(environment.getMock())) {
if (StringUtils.isNotEmpty(baseUrl)) {
Long projectNum = projectMap.get(environment.getProjectId()).getNum();
environmentInfo.getConfig().getHttpConfig().getFirst().setUrl(StringUtils.join(baseUrl, MOCK_EVN_SOCKET, projectNum));
}
}
environmentInfos.add(environmentInfo);
}
return environmentInfos;
}
private List<Project> getProjects(List<String> projectIds) {
if (CollectionUtils.isEmpty(projectIds)) {
return Collections.emptyList();
}
ProjectExample example = new ProjectExample();
example.createCriteria().andIdIn(projectIds);
List<Project> projects = projectMapper.selectByExample(example);
return projects;
}
public List<Environment> getEnvironmentsByIds(List<String> envIds) {
if (CollectionUtils.isEmpty(envIds)) {
return Collections.emptyList();
}
EnvironmentExample example = new EnvironmentExample();
example.createCriteria().andIdIn(envIds);
return environmentMapper.selectByExample(example);
}
public List<EnvironmentBlob> getEnvironmentBlobsByIds(List<String> envIds) {
if (CollectionUtils.isEmpty(envIds)) {
return Collections.emptyList();
}
EnvironmentBlobExample example = new EnvironmentBlobExample();
example.createCriteria().andIdIn(envIds);
return environmentBlobMapper.selectByExampleWithBLOBs(example);
}
}

View File

@ -1,6 +1,7 @@
package io.metersphere.system.service;
import io.metersphere.plugin.api.spi.AbstractApiPlugin;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.plugin.api.spi.AbstractProtocolPlugin;
import io.metersphere.plugin.api.spi.MsTestElement;
import io.metersphere.sdk.constants.PluginScenarioType;
@ -14,9 +15,7 @@ import org.pf4j.PluginWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -81,4 +80,18 @@ public class ApiPluginService {
.toList();
return pluginWrappers;
}
/**
* 返回 MsTestElement 实现类与插件 ID 的映射
* @return
*/
public Map<Class<? extends AbstractMsTestElement>, String> getTestElementPluginMap() {
Map<Class<? extends AbstractMsTestElement>, String> testElementPluginMap = new HashMap<>();
List<PluginWrapper> plugins = pluginLoadService.getMsPluginManager().getPlugins();
for (PluginWrapper plugin : plugins) {
List<Class<? extends MsTestElement>> extensionClasses = plugin.getPluginManager().getExtensionClasses(MsTestElement.class);
extensionClasses.forEach(clazz -> testElementPluginMap.put((Class<? extends AbstractMsTestElement>) clazz, plugin.getPluginId()));
}
return testElementPluginMap;
}
}