fix(接口测试): Import api scenario with wrong module

This commit is contained in:
Jianguo-Genius 2024-10-25 14:48:19 +08:00 committed by 建国
parent ba9c4afc76
commit 892917346d
3 changed files with 98 additions and 27 deletions

View File

@ -759,7 +759,7 @@
</foreach> </foreach>
</select> </select>
<select id="selectBaseInfoByModuleIdAndProjectId" resultType="io.metersphere.api.domain.ApiScenario"> <select id="selectBaseInfoByModuleIdAndProjectId" resultType="io.metersphere.api.domain.ApiScenario">
SELECT id, name SELECT id, name, project_id
FROM api_scenario FROM api_scenario
WHERE module_id = #{moduleId} WHERE module_id = #{moduleId}
AND project_id = #{projectId} AND project_id = #{projectId}

View File

@ -10,6 +10,7 @@ import io.metersphere.api.dto.converter.ApiDefinitionDetail;
import io.metersphere.api.dto.converter.ApiDefinitionExportDetail; import io.metersphere.api.dto.converter.ApiDefinitionExportDetail;
import io.metersphere.api.dto.converter.ApiScenarioImportParseResult; import io.metersphere.api.dto.converter.ApiScenarioImportParseResult;
import io.metersphere.api.dto.converter.ApiScenarioPreImportAnalysisResult; import io.metersphere.api.dto.converter.ApiScenarioPreImportAnalysisResult;
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.export.ApiScenarioExportResponse; import io.metersphere.api.dto.export.ApiScenarioExportResponse;
import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse; import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse;
@ -30,7 +31,9 @@ import io.metersphere.api.utils.ApiScenarioImportUtils;
import io.metersphere.functional.domain.ExportTask; import io.metersphere.functional.domain.ExportTask;
import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.filemanagement.FileAssociationSource;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper; import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ExtFileAssociationMapper;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.service.PermissionCheckService; import io.metersphere.project.service.PermissionCheckService;
import io.metersphere.project.utils.FileDownloadUtils; import io.metersphere.project.utils.FileDownloadUtils;
@ -113,6 +116,8 @@ public class ApiScenarioDataTransferService {
private ExtApiDefinitionMapper extApiDefinitionMapper; private ExtApiDefinitionMapper extApiDefinitionMapper;
@Resource @Resource
private ExtApiTestCaseMapper extApiTestCaseMapper; private ExtApiTestCaseMapper extApiTestCaseMapper;
@Resource
private ExtFileAssociationMapper extFileAssociationMapper;
@Resource @Resource
private FileService fileService; private FileService fileService;
@ -309,12 +314,14 @@ public class ApiScenarioDataTransferService {
operationLogs.add(ApiScenarioImportUtils.genImportLog(project, t.getId(), t.getName(), scenarioImportDetail, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO, operator, OperationLogType.IMPORT.name())); operationLogs.add(ApiScenarioImportUtils.genImportLog(project, t.getId(), t.getName(), scenarioImportDetail, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO, operator, OperationLogType.IMPORT.name()));
}); });
preImportAnalysisResult.getUpdateApiScenarioData().forEach(t -> { if (isCoverData) {
ApiScenarioImportDetail scenarioImportDetail = new ApiScenarioImportDetail(); preImportAnalysisResult.getUpdateApiScenarioData().forEach(t -> {
BeanUtils.copyBean(scenarioImportDetail, t); ApiScenarioImportDetail scenarioImportDetail = new ApiScenarioImportDetail();
noticeUpdateLists.add(scenarioImportDetail); BeanUtils.copyBean(scenarioImportDetail, t);
operationLogs.add(ApiScenarioImportUtils.genImportLog(project, t.getId(), t.getName(), scenarioImportDetail, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO, operator, OperationLogType.UPDATE.name())); noticeUpdateLists.add(scenarioImportDetail);
}); operationLogs.add(ApiScenarioImportUtils.genImportLog(project, t.getId(), t.getName(), scenarioImportDetail, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO, operator, OperationLogType.UPDATE.name()));
});
}
//发送通知 //发送通知
User user = userMapper.selectByPrimaryKey(operator); User user = userMapper.selectByPrimaryKey(operator);
@ -361,6 +368,7 @@ public class ApiScenarioDataTransferService {
ApiScenario scenario = new ApiScenario(); ApiScenario scenario = new ApiScenario();
scenario.setId(request.getId()); scenario.setId(request.getId());
scenario.setUpdateUser(operator); scenario.setUpdateUser(operator);
scenario.setProjectId(request.getProjectId());
scenario.setUpdateTime(System.currentTimeMillis()); scenario.setUpdateTime(System.currentTimeMillis());
scenario.setStepTotal(CollectionUtils.isNotEmpty(request.getSteps()) ? request.getSteps().size() : 0); scenario.setStepTotal(CollectionUtils.isNotEmpty(request.getSteps()) ? request.getSteps().size() : 0);
scenarioBatchMapper.updateByPrimaryKeySelective(scenario); scenarioBatchMapper.updateByPrimaryKeySelective(scenario);
@ -531,7 +539,7 @@ public class ApiScenarioDataTransferService {
} }
apiScenarioBlobBatchMapper.insert(apiScenarioBlob); apiScenarioBlobBatchMapper.insert(apiScenarioBlob);
// 处理csv文件 // 处理csv文件
this.handCsvFilesAdd(t, operator, scenario, csvBatchMapper, csvStepBatchMapper); this.importCsvFilesAdd(t, operator, scenario, csvBatchMapper, csvStepBatchMapper);
// 处理添加的步骤 // 处理添加的步骤
this.handleStepAdd(t, scenario, csvStepBatchMapper, stepBatchMapper, stepBlobBatchMapper); this.handleStepAdd(t, scenario, csvStepBatchMapper, stepBatchMapper, stepBlobBatchMapper);
}); });
@ -581,8 +589,8 @@ public class ApiScenarioDataTransferService {
} }
} }
private void handCsvFilesAdd(ApiScenarioImportDetail t, String operator, ApiScenario scenario, private void importCsvFilesAdd(ApiScenarioImportDetail t, String operator, ApiScenario scenario,
ApiScenarioCsvMapper batchCsvMapper, ApiScenarioCsvStepMapper batchCsvStepMapper) { ApiScenarioCsvMapper batchCsvMapper, ApiScenarioCsvStepMapper batchCsvStepMapper) {
List<CsvVariable> csvVariables = apiScenarioService.getCsvVariables(t.getScenarioConfig()); List<CsvVariable> csvVariables = apiScenarioService.getCsvVariables(t.getScenarioConfig());
if (CollectionUtils.isEmpty(csvVariables)) { if (CollectionUtils.isEmpty(csvVariables)) {
@ -590,8 +598,19 @@ public class ApiScenarioDataTransferService {
} }
// 处理 csv 相关数据表 // 处理 csv 相关数据表
this.handleCsvDataUpdate(csvVariables, scenario, List.of(), batchCsvMapper, batchCsvStepMapper); this.handleCsvDataUpdate(csvVariables, scenario, List.of(), batchCsvMapper, batchCsvStepMapper);
// 处理文件的上传 调用流程很长目前没想到有好的批量处理方法暂时直接调用Service // 处理文件的上传 因为是导入调用的有些文件可能不存在所以要进行判断
apiScenarioService.handleCsvFileAdd(csvVariables, List.of(), scenario, operator); ApiFileResourceUpdateRequest resourceUpdateRequest = apiScenarioService.getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), operator);
// 设置本地文件相关参数
apiScenarioService.setCsvLocalFileParam(csvVariables, List.of(), resourceUpdateRequest);
// 设置关联文件相关参数
apiScenarioService.setCsvLinkFileParam(csvVariables, List.of(), resourceUpdateRequest);
FileAssociationSource source = extFileAssociationMapper.selectNameBySourceTableAndId(
FileAssociationSourceUtil.getQuerySql(ApiFileResourceType.API_SCENARIO.name()), resourceUpdateRequest.getResourceId());
if (source != null) {
apiFileResourceService.addFileResource(resourceUpdateRequest);
}
} }
private void handleCsvDataUpdate(List<CsvVariable> csvVariables, ApiScenario scenario, List<String> dbCsvIds, private void handleCsvDataUpdate(List<CsvVariable> csvVariables, ApiScenario scenario, List<String> dbCsvIds,
@ -653,21 +672,26 @@ public class ApiScenarioDataTransferService {
Map<String, String> moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath)); Map<String, String> moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
Map<String, BaseTreeNode> modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1)); Map<String, BaseTreeNode> modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1));
ReplaceScenarioResource replaceScenarioResource = this.parseRelatedDataToAnalysisResult(operator, projectId, parseResult, analysisResult); ReplaceScenarioResource replaceScenarioResource = this.parseRelatedDataToAnalysisResult(operator, projectId, parseResult, analysisResult, moduleIdPathMap, modulePathMap);
List<ApiScenarioImportDetail> importScenarios = parseResult.getImportScenarioList(); List<ApiScenarioImportDetail> importScenarios = parseResult.getImportScenarioList();
for (ApiScenarioImportDetail importScenario : importScenarios) { for (ApiScenarioImportDetail importScenario : importScenarios) {
//处理模块 //处理模块
if (StringUtils.isBlank(moduleId) || StringUtils.equalsIgnoreCase(moduleId, ModuleConstants.DEFAULT_NODE_ID) || !moduleIdPathMap.containsKey(moduleId)) { if (StringUtils.equalsIgnoreCase(moduleId, ModuleConstants.DEFAULT_NODE_ID)) {
importScenario.setModuleId(ModuleConstants.DEFAULT_NODE_ID); importScenario.setModuleId(ModuleConstants.DEFAULT_NODE_ID);
importScenario.setModulePath(moduleIdPathMap.get(ModuleConstants.DEFAULT_NODE_ID)); importScenario.setModulePath(moduleIdPathMap.get(ModuleConstants.DEFAULT_NODE_ID));
} else { } else {
if (StringUtils.isBlank(importScenario.getModulePath())) { if (StringUtils.isBlank(moduleId)) {
importScenario.setModulePath(moduleIdPathMap.get(moduleId)); if (StringUtils.isBlank(importScenario.getModulePath())) {
} else if (StringUtils.startsWith(importScenario.getModulePath(), "/")) { importScenario.setModuleId(ModuleConstants.DEFAULT_NODE_ID);
importScenario.setModulePath(moduleIdPathMap.get(moduleId) + importScenario.getModulePath()); importScenario.setModulePath(moduleIdPathMap.get(ModuleConstants.DEFAULT_NODE_ID));
}
} else { } else {
importScenario.setModulePath(moduleIdPathMap.get(moduleId) + "/" + importScenario.getModulePath()); if (StringUtils.isBlank(importScenario.getModulePath())) {
importScenario.setModulePath(moduleIdPathMap.get(moduleId));
} else {
importScenario.setModulePath(moduleIdPathMap.get(moduleId) + importScenario.getModulePath());
}
} }
} }
} }
@ -781,7 +805,8 @@ public class ApiScenarioDataTransferService {
return analysisResult; return analysisResult;
} }
private ReplaceScenarioResource parseRelatedDataToAnalysisResult(String operator, String projectId, ApiScenarioImportParseResult parseResult, ApiScenarioPreImportAnalysisResult analysisResult) { private ReplaceScenarioResource parseRelatedDataToAnalysisResult(String operator, String projectId, ApiScenarioImportParseResult parseResult, ApiScenarioPreImportAnalysisResult analysisResult
, Map<String, String> projectModuleIdPathMap, Map<String, BaseTreeNode> projectModulePathMap) {
/* /*
1.判断接口定义中要创建的部分然后进行新旧ID映射 1.判断接口定义中要创建的部分然后进行新旧ID映射
2.判断用例中的接口定义是否在上一步中创建如果没有则进行筛选判断符合条件的接口定义若没有则新建并关联到其下面 2.判断用例中的接口定义是否在上一步中创建如果没有则进行筛选判断符合条件的接口定义若没有则新建并关联到其下面
@ -867,10 +892,22 @@ public class ApiScenarioDataTransferService {
List<BaseTreeNode> apiModules = apiDefinitionImportService.buildTreeData(targetProjectId, null); List<BaseTreeNode> apiModules = apiDefinitionImportService.buildTreeData(targetProjectId, null);
Map<String, BaseTreeNode> modulePathMap = apiModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1)); Map<String, BaseTreeNode> modulePathMap = apiModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1));
for (ApiDefinitionDetail apiDefinitionDetail : analysisResult.getInsertApiDefinitions()) { for (ApiDefinitionDetail apiDefinitionDetail : analysisResult.getInsertApiDefinitions()) {
List<BaseTreeNode> insertModuleList = TreeNodeParseUtils.getInsertNodeByPath(modulePathMap, apiDefinitionDetail.getModulePath());
apiDefinitionDetail.setModuleId(modulePathMap.get(apiDefinitionDetail.getModulePath()).getId()); if (StringUtils.isBlank(apiDefinitionDetail.getModulePath()) || StringUtils.equals(apiDefinitionDetail.getModulePath().trim(), "/")) {
insertModuleList.forEach(item -> item.setProjectId(targetProjectId)); apiDefinitionDetail.setModuleId(ModuleConstants.DEFAULT_NODE_ID);
analysisResult.getInsertApiModuleList().addAll(insertModuleList); apiDefinitionDetail.setModulePath(Translator.get("api_unplanned_request"));
} else {
if (!StringUtils.startsWith(apiDefinitionDetail.getModulePath(), "/")) {
apiDefinitionDetail.setModulePath("/" + apiDefinitionDetail.getModulePath());
}
if (StringUtils.endsWith(apiDefinitionDetail.getModulePath(), "/")) {
apiDefinitionDetail.setModulePath(apiDefinitionDetail.getModulePath().substring(0, apiDefinitionDetail.getModulePath().length() - 1));
}
List<BaseTreeNode> insertModuleList = TreeNodeParseUtils.getInsertNodeByPath(modulePathMap, apiDefinitionDetail.getModulePath());
apiDefinitionDetail.setModuleId(modulePathMap.get(apiDefinitionDetail.getModulePath()).getId());
insertModuleList.forEach(item -> item.setProjectId(targetProjectId));
analysisResult.getInsertApiModuleList().addAll(insertModuleList);
}
} }
} }
} }
@ -963,10 +1000,18 @@ public class ApiScenarioDataTransferService {
{ {
for (Map.Entry<String, List<ApiScenarioImportDetail>> entry : projectScenarioMap.entrySet()) { for (Map.Entry<String, List<ApiScenarioImportDetail>> entry : projectScenarioMap.entrySet()) {
String targetProjectId = entry.getKey(); String targetProjectId = entry.getKey();
List<BaseTreeNode> apiScenarioModules = apiScenarioModuleService.getImportTreeNodeList(targetProjectId); Map<String, BaseTreeNode> modulePathMap;
Map<String, String> moduleIdPathMap;
if (!StringUtils.equalsIgnoreCase(targetProjectId, projectId)) {
List<BaseTreeNode> apiScenarioModules = apiScenarioModuleService.getImportTreeNodeList(targetProjectId);
moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1));
} else {
// 当前项目下的场景模块采用传参进来的数据这样不影响后续在当前项目下的模块补充逻辑
moduleIdPathMap = projectModuleIdPathMap;
modulePathMap = projectModulePathMap;
}
Map<String, String> moduleIdPathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getPath));
Map<String, BaseTreeNode> modulePathMap = apiScenarioModules.stream().collect(Collectors.toMap(BaseTreeNode::getPath, k -> k, (k1, k2) -> k1));
List<ApiScenarioImportDetail> importScenarios = parseResult.getRelatedScenarioList(); List<ApiScenarioImportDetail> importScenarios = parseResult.getRelatedScenarioList();

View File

@ -3,6 +3,7 @@ package io.metersphere.api.controller;
import io.metersphere.api.dto.definition.ApiScenarioBatchExportRequest; import io.metersphere.api.dto.definition.ApiScenarioBatchExportRequest;
import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse; import io.metersphere.api.dto.export.MetersphereApiScenarioExportResponse;
import io.metersphere.api.dto.scenario.ApiScenarioImportRequest; import io.metersphere.api.dto.scenario.ApiScenarioImportRequest;
import io.metersphere.api.service.ApiScenarioDataTransferService;
import io.metersphere.api.utils.ApiDataUtils; import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.functional.domain.ExportTask; import io.metersphere.functional.domain.ExportTask;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
@ -51,6 +52,8 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest {
@Resource @Resource
private CommonProjectService commonProjectService; private CommonProjectService commonProjectService;
@Resource
private ApiScenarioDataTransferService apiScenarioDataTransferService;
@BeforeEach @BeforeEach
public void initTestData() { public void initTestData() {
@ -66,6 +69,15 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest {
} }
} }
@Test
@Order(0)
public void baseTest() throws Exception {
try {
apiScenarioDataTransferService.exportScenario(null, null, null);
} catch (Exception ignore) {
}
}
@Test @Test
@Order(1) @Order(1)
public void testImport() throws Exception { public void testImport() throws Exception {
@ -87,6 +99,20 @@ public class ApiScenarioControllerImportAndExportTests extends BaseTest {
paramMap.add("request", JSON.toJSONString(request)); paramMap.add("request", JSON.toJSONString(request));
paramMap.add("file", file); paramMap.add("file", file);
this.requestMultipartWithOkAndReturn(URL_POST_IMPORT, paramMap); this.requestMultipartWithOkAndReturn(URL_POST_IMPORT, paramMap);
request.setCoverData(true);
paramMap = new LinkedMultiValueMap<>();
paramMap.add("request", JSON.toJSONString(request));
paramMap.add("file", file);
this.requestMultipartWithOkAndReturn(URL_POST_IMPORT, paramMap);
inputStream = new FileInputStream(new File(Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/file_update_upload.JPG")).getPath()));
file = new MockMultipartFile("file", "simple.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
paramMap = new LinkedMultiValueMap<>();
paramMap.add("request", JSON.toJSONString(request));
paramMap.add("file", file);
this.requestMultipart(URL_POST_IMPORT, paramMap);
} }
@Resource @Resource