fix(接口测试): 场景引用csv,文件管理更新文件版本后,不生效
--bug=1045399 --user=陈建星 【接口测试】-场景CSV参数中使用文件库中的csv,在文件更换后,执行场景,场景无法读取到csv文件中的参数 https://www.tapd.cn/55049933/s/1581080
This commit is contained in:
parent
b5a506438b
commit
e2e4d9b1d8
|
@ -42,6 +42,9 @@ public class ApiFileAssociationUpdateService implements FileAssociationUpdateSer
|
||||||
case FileAssociationSourceUtil.SOURCE_TYPE_API_SCENARIO_STEP ->
|
case FileAssociationSourceUtil.SOURCE_TYPE_API_SCENARIO_STEP ->
|
||||||
Objects.requireNonNull(CommonBeanFactory.getBean(ApiScenarioService.class))
|
Objects.requireNonNull(CommonBeanFactory.getBean(ApiScenarioService.class))
|
||||||
.handleStepFileAssociationUpgrade(originFileAssociation, newFileMetadata);
|
.handleStepFileAssociationUpgrade(originFileAssociation, newFileMetadata);
|
||||||
|
case FileAssociationSourceUtil.SOURCE_TYPE_API_SCENARIO ->
|
||||||
|
Objects.requireNonNull(CommonBeanFactory.getBean(ApiScenarioService.class))
|
||||||
|
.handleScenarioFileAssociationUpgrade(originFileAssociation, newFileMetadata);
|
||||||
default -> {
|
default -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,10 @@ public class ApiScenarioRunService {
|
||||||
msScenario.setScenarioConfig(getScenarioConfig(request, true));
|
msScenario.setScenarioConfig(getScenarioConfig(request, true));
|
||||||
msScenario.setProjectId(request.getProjectId());
|
msScenario.setProjectId(request.getProjectId());
|
||||||
|
|
||||||
|
List<ApiScenarioCsv> dbCsv = apiScenarioService.getApiScenarioCsv(apiScenario.getId());
|
||||||
|
List<CsvVariable> csvVariables = apiScenarioService.getCsvVariables(msScenario.getScenarioConfig());
|
||||||
|
apiScenarioService.handleRefUpgradeFile(csvVariables, dbCsv);
|
||||||
|
|
||||||
// 处理特殊的步骤详情
|
// 处理特殊的步骤详情
|
||||||
apiScenarioService.addSpecialStepDetails(request.getSteps(), request.getStepDetails());
|
apiScenarioService.addSpecialStepDetails(request.getSteps(), request.getStepDetails());
|
||||||
|
|
||||||
|
@ -376,6 +380,10 @@ public class ApiScenarioRunService {
|
||||||
msScenario.setProjectId(request.getProjectId());
|
msScenario.setProjectId(request.getProjectId());
|
||||||
msScenario.setResourceId(request.getId());
|
msScenario.setResourceId(request.getId());
|
||||||
|
|
||||||
|
List<ApiScenarioCsv> dbCsv = apiScenarioService.getApiScenarioCsv(apiScenario.getId());
|
||||||
|
List<CsvVariable> csvVariables = apiScenarioService.getCsvVariables(msScenario.getScenarioConfig());
|
||||||
|
apiScenarioService.handleRefUpgradeFile(csvVariables, dbCsv);
|
||||||
|
|
||||||
// 处理特殊的步骤详情
|
// 处理特殊的步骤详情
|
||||||
apiScenarioService.addSpecialStepDetails(request.getSteps(), request.getStepDetails());
|
apiScenarioService.addSpecialStepDetails(request.getSteps(), request.getStepDetails());
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,10 @@ import io.metersphere.api.utils.ApiScenarioBatchOperationUtils;
|
||||||
import io.metersphere.functional.domain.FunctionalCaseTestExample;
|
import io.metersphere.functional.domain.FunctionalCaseTestExample;
|
||||||
import io.metersphere.functional.mapper.FunctionalCaseTestMapper;
|
import io.metersphere.functional.mapper.FunctionalCaseTestMapper;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
import io.metersphere.project.domain.FileAssociation;
|
import io.metersphere.project.domain.*;
|
||||||
import io.metersphere.project.domain.FileMetadata;
|
|
||||||
import io.metersphere.project.domain.Project;
|
|
||||||
import io.metersphere.project.domain.ProjectExample;
|
|
||||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||||
|
import io.metersphere.project.mapper.FileMetadataMapper;
|
||||||
import io.metersphere.project.mapper.ProjectMapper;
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.project.service.MoveNodeService;
|
import io.metersphere.project.service.MoveNodeService;
|
||||||
import io.metersphere.sdk.constants.*;
|
import io.metersphere.sdk.constants.*;
|
||||||
|
@ -138,6 +136,8 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiScenarioCsvMapper apiScenarioCsvMapper;
|
private ApiScenarioCsvMapper apiScenarioCsvMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
private FileMetadataMapper fileMetadataMapper;
|
||||||
|
@Resource
|
||||||
private ApiScenarioCsvStepMapper apiScenarioCsvStepMapper;
|
private ApiScenarioCsvStepMapper apiScenarioCsvStepMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ScheduleService scheduleService;
|
private ScheduleService scheduleService;
|
||||||
|
@ -508,10 +508,10 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
handleCsvDataUpdate(csvVariables, scenario, List.of());
|
handleCsvDataUpdate(csvVariables, scenario, List.of());
|
||||||
|
|
||||||
// 处理文件的上传
|
// 处理文件的上传
|
||||||
handleCsvFileUpdate(csvVariables, List.of(), scenario, creator);
|
handleCsvFileAdd(csvVariables, List.of(), scenario, creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<CsvVariable> getCsvVariables(ScenarioConfig scenarioConfig) {
|
public List<CsvVariable> getCsvVariables(ScenarioConfig scenarioConfig) {
|
||||||
if (scenarioConfig == null || scenarioConfig.getVariable() == null || scenarioConfig.getVariable().getCsvVariables() == null) {
|
if (scenarioConfig == null || scenarioConfig.getVariable() == null || scenarioConfig.getVariable().getCsvVariables() == null) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
@ -569,18 +569,90 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
|
|
||||||
List<CsvVariable> csvVariables = getCsvVariables(scenarioConfig);
|
List<CsvVariable> csvVariables = getCsvVariables(scenarioConfig);
|
||||||
List<ApiScenarioCsv> dbCsv = getApiScenarioCsv(scenario.getId());
|
List<ApiScenarioCsv> dbCsv = getApiScenarioCsv(scenario.getId());
|
||||||
|
List<String> dbCsvIds = dbCsv.stream()
|
||||||
|
.map(ApiScenarioCsv::getId)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
handleRefUpgradeFile(csvVariables, dbCsv);
|
||||||
|
|
||||||
// 更新 csv 相关数据表
|
// 更新 csv 相关数据表
|
||||||
handleCsvDataUpdate(csvVariables, scenario, dbCsv);
|
handleCsvDataUpdate(csvVariables, scenario, dbCsvIds);
|
||||||
|
|
||||||
// 处理文件的上传和删除
|
// 处理文件的上传和删除
|
||||||
handleCsvFileUpdate(csvVariables, dbCsv, scenario, userId);
|
handleCsvFileUpdate(csvVariables, dbCsv, scenario, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCsvDataUpdate(List<CsvVariable> csvVariables, ApiScenario scenario, List<ApiScenarioCsv> dbCsv) {
|
/**
|
||||||
List<String> dbCsvIds = dbCsv.stream()
|
* 当文件管理更新了关联资源的 csv 文件版本时
|
||||||
.map(ApiScenarioCsv::getId)
|
* 前端文件并未更新,这里使用时,进行对比,使用较新的文件版本
|
||||||
.toList();
|
* @param csvVariables
|
||||||
|
* @param dbCsv
|
||||||
|
*/
|
||||||
|
public void handleRefUpgradeFile(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv) {
|
||||||
|
try {
|
||||||
|
// 获取数据库中关联的 csv 文件
|
||||||
|
List<ApiScenarioCsv> dbAssociationCsvList = dbCsv.stream().filter(ApiScenarioCsv::getAssociation).toList();
|
||||||
|
Map<String, ApiScenarioCsv> dbAssociationCsvIdMap = dbAssociationCsvList.stream()
|
||||||
|
.collect(Collectors.toMap(ApiScenarioCsv::getId, Function.identity()));
|
||||||
|
|
||||||
|
// 获取与数据库中数据 fileId 不一致的 csv
|
||||||
|
List<CsvVariable> changeAssociationCsvList = csvVariables.stream().filter(csvVariable -> {
|
||||||
|
ApiScenarioCsv apiScenarioCsv = dbAssociationCsvIdMap.get(csvVariable.getId());
|
||||||
|
if (apiScenarioCsv != null && csvVariable.getFile() != null && StringUtils.isNotBlank(csvVariable.getFile().getFileId())
|
||||||
|
&& !StringUtils.equals(apiScenarioCsv.getFileId(), csvVariable.getFile().getFileId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(changeAssociationCsvList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询关联的csv文件信息
|
||||||
|
List<String> dbAssociationCsvFileIds = changeAssociationCsvList.stream().map(csvVariable -> csvVariable.getFile().getFileId()).toList();
|
||||||
|
FileMetadataExample fileMetadataExample = new FileMetadataExample();
|
||||||
|
fileMetadataExample.createCriteria().andIdIn(dbAssociationCsvFileIds);
|
||||||
|
List<FileMetadata> dbAssociationCsvFiles = fileMetadataMapper.selectByExample(fileMetadataExample);
|
||||||
|
Map<String, FileMetadata> dbAssociationCsvFileMap = dbAssociationCsvFiles.stream()
|
||||||
|
.collect(Collectors.toMap(FileMetadata::getId, Function.identity()));
|
||||||
|
|
||||||
|
// 查询csv文件的版本信息
|
||||||
|
List<String> refIds = dbAssociationCsvFiles.stream().map(FileMetadata::getRefId).toList();
|
||||||
|
FileMetadataExample example = new FileMetadataExample();
|
||||||
|
example.createCriteria().andRefIdIn(refIds);
|
||||||
|
List<FileMetadata> fileMetadataList = fileMetadataMapper.selectByExample(example)
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(FileMetadata::getUpdateTime).reversed())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Map<String, List<FileMetadata>> refFileMap = fileMetadataList.stream().collect(Collectors.groupingBy(FileMetadata::getRefId));
|
||||||
|
|
||||||
|
for (CsvVariable changeAssociation : changeAssociationCsvList) {
|
||||||
|
String fileId = changeAssociation.getFile().getFileId();
|
||||||
|
FileMetadata fileMetadata = dbAssociationCsvFileMap.get(fileId);
|
||||||
|
ApiScenarioCsv dbAssociationCsv = dbAssociationCsvIdMap.get(changeAssociation.getId());
|
||||||
|
// 遍历同一文件的不同版本
|
||||||
|
List<FileMetadata> refFileList = refFileMap.get(fileMetadata.getRefId());
|
||||||
|
if (refFileList != null) {
|
||||||
|
for (FileMetadata refFile : refFileList) {
|
||||||
|
if (StringUtils.equals(refFile.getId(), fileId)) {
|
||||||
|
// 如果前端参数的版本较新,则不处理
|
||||||
|
break;
|
||||||
|
} else if (StringUtils.equals(refFile.getId(), dbAssociationCsv.getFileId())) {
|
||||||
|
// 如果数据库中的文件版本较新,则说明文件管理中更新了当前引用的文件版本,使用数据库中的文件信息
|
||||||
|
changeAssociation.getFile().setFileId(dbAssociationCsv.getFileId());
|
||||||
|
changeAssociation.getFile().setFileName(dbAssociationCsv.getFileName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleCsvDataUpdate(List<CsvVariable> csvVariables, ApiScenario scenario, List<String> dbCsvIds) {
|
||||||
|
|
||||||
List<String> csvIds = csvVariables.stream()
|
List<String> csvIds = csvVariables.stream()
|
||||||
.map(CsvVariable::getId)
|
.map(CsvVariable::getId)
|
||||||
|
@ -616,7 +688,7 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCsvFileUpdate(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiScenario scenario, String userId) {
|
private void handleCsvFileAdd(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiScenario scenario, String userId) {
|
||||||
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), userId);
|
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), userId);
|
||||||
// 设置本地文件相关参数
|
// 设置本地文件相关参数
|
||||||
setCsvLocalFileParam(csvVariables, dbCsv, resourceUpdateRequest);
|
setCsvLocalFileParam(csvVariables, dbCsv, resourceUpdateRequest);
|
||||||
|
@ -625,17 +697,26 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
apiFileResourceService.addFileResource(resourceUpdateRequest);
|
apiFileResourceService.addFileResource(resourceUpdateRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleCsvFileUpdate(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiScenario scenario, String userId) {
|
||||||
|
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), userId);
|
||||||
|
// 设置本地文件相关参数
|
||||||
|
setCsvLocalFileParam(csvVariables, dbCsv, resourceUpdateRequest);
|
||||||
|
// 设置关联文件相关参数
|
||||||
|
setCsvLinkFileParam(csvVariables, dbCsv, resourceUpdateRequest);
|
||||||
|
apiFileResourceService.updateFileResource(resourceUpdateRequest);
|
||||||
|
}
|
||||||
|
|
||||||
private void setCsvLinkFileParam(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiFileResourceUpdateRequest resourceUpdateRequest) {
|
private void setCsvLinkFileParam(List<CsvVariable> csvVariables, List<ApiScenarioCsv> dbCsv, ApiFileResourceUpdateRequest resourceUpdateRequest) {
|
||||||
// 获取数据库中关联的文件id
|
// 获取数据库中关联的文件id
|
||||||
List<String> dbRefFileIds = dbCsv.stream()
|
List<String> dbRefFileIds = dbCsv.stream()
|
||||||
.filter(c -> BooleanUtils.isTrue(c.getAssociation()))
|
.filter(c -> BooleanUtils.isTrue(c.getAssociation()) && StringUtils.isNotBlank(c.getFileId()))
|
||||||
.map(ApiScenarioCsv::getFileId)
|
.map(ApiScenarioCsv::getFileId)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// 获取请求中关联的文件id
|
// 获取请求中关联的文件id
|
||||||
List<String> refFileIds = csvVariables.stream()
|
List<String> refFileIds = csvVariables.stream()
|
||||||
.map(CsvVariable::getFile)
|
.map(CsvVariable::getFile)
|
||||||
.filter(c -> BooleanUtils.isFalse(c.getLocal()))
|
.filter(c -> BooleanUtils.isFalse(c.getLocal()) && StringUtils.isNotBlank(c.getFileId()))
|
||||||
.map(ApiFile::getFileId).toList();
|
.map(ApiFile::getFileId).toList();
|
||||||
|
|
||||||
List<String> unlinkFileIds = ListUtils.subtract(dbRefFileIds, refFileIds);
|
List<String> unlinkFileIds = ListUtils.subtract(dbRefFileIds, refFileIds);
|
||||||
|
@ -665,7 +746,7 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
resourceUpdateRequest.setUploadFileIds(addLocal);
|
resourceUpdateRequest.setUploadFileIds(addLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ApiScenarioCsv> getApiScenarioCsv(String scenarioId) {
|
public List<ApiScenarioCsv> getApiScenarioCsv(String scenarioId) {
|
||||||
ApiScenarioCsvExample apiScenarioCsvExample = new ApiScenarioCsvExample();
|
ApiScenarioCsvExample apiScenarioCsvExample = new ApiScenarioCsvExample();
|
||||||
apiScenarioCsvExample.createCriteria().andScenarioIdEqualTo(scenarioId);
|
apiScenarioCsvExample.createCriteria().andScenarioIdEqualTo(scenarioId);
|
||||||
return apiScenarioCsvMapper.selectByExample(apiScenarioCsvExample);
|
return apiScenarioCsvMapper.selectByExample(apiScenarioCsvExample);
|
||||||
|
@ -2284,7 +2365,7 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e);
|
LogUtils.error(e);
|
||||||
}
|
}
|
||||||
if (msTestElement instanceof MsHTTPElement msHTTPElement) {
|
if (msTestElement != null && msTestElement instanceof MsHTTPElement msHTTPElement) {
|
||||||
List<ApiFile> updateFiles = apiCommonService.getApiFilesByFileId(originFileAssociation.getFileId(), msHTTPElement);
|
List<ApiFile> updateFiles = apiCommonService.getApiFilesByFileId(originFileAssociation.getFileId(), msHTTPElement);
|
||||||
// 替换文件的Id和name
|
// 替换文件的Id和name
|
||||||
apiCommonService.replaceApiFileInfo(updateFiles, newFileMetadata);
|
apiCommonService.replaceApiFileInfo(updateFiles, newFileMetadata);
|
||||||
|
@ -2296,6 +2377,31 @@ public class ApiScenarioService extends MoveNodeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handleScenarioFileAssociationUpgrade(FileAssociation originFileAssociation, FileMetadata newFileMetadata) {
|
||||||
|
String scenarioId = originFileAssociation.getSourceId();
|
||||||
|
// 查询步骤详情
|
||||||
|
ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(originFileAssociation.getSourceId());
|
||||||
|
|
||||||
|
if (apiScenarioBlob == null || apiScenarioBlob.getConfig() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CsvVariable> csvVariables = getCsvVariables(scenarioId);
|
||||||
|
List<ApiFile> updateFiles = new ArrayList<>(csvVariables.size());
|
||||||
|
for (CsvVariable csvVariable : csvVariables) {
|
||||||
|
ApiFile apiFile = csvVariable.getFile();
|
||||||
|
if (apiFile != null && StringUtils.equals(originFileAssociation.getFileId(), apiFile.getFileId())) {
|
||||||
|
updateFiles.add(apiFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(updateFiles)) {
|
||||||
|
// 替换文件的Id和name
|
||||||
|
apiCommonService.replaceApiFileInfo(updateFiles, newFileMetadata);
|
||||||
|
List<String> dbCsvIds = csvVariables.stream().map(CsvVariable::getId).toList();
|
||||||
|
handleCsvDataUpdate(csvVariables, apiScenarioMapper.selectByPrimaryKey(originFileAssociation.getSourceId()), dbCsvIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String scenarioTransfer(ApiTransferRequest request, String userId) {
|
public String scenarioTransfer(ApiTransferRequest request, String userId) {
|
||||||
String apiScenarioStepDir = DefaultRepositoryDir.getApiScenarioDir(request.getProjectId(), request.getSourceId());
|
String apiScenarioStepDir = DefaultRepositoryDir.getApiScenarioDir(request.getProjectId(), request.getSourceId());
|
||||||
return apiFileResourceService.transfer(request, userId, apiScenarioStepDir);
|
return apiFileResourceService.transfer(request, userId, apiScenarioStepDir);
|
||||||
|
|
|
@ -643,6 +643,8 @@ public class ApiScenarioControllerTests extends BaseTest {
|
||||||
request.setPriority("P0 update");
|
request.setPriority("P0 update");
|
||||||
request.setStatus(ApiScenarioStatus.DEPRECATED.name());
|
request.setStatus(ApiScenarioStatus.DEPRECATED.name());
|
||||||
List<ApiScenarioStepRequest> steps = getApiScenarioStepRequests();
|
List<ApiScenarioStepRequest> steps = getApiScenarioStepRequests();
|
||||||
|
ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(addApiScenario.getId());
|
||||||
|
request.setScenarioConfig(JSON.parseObject(new String(apiScenarioBlob.getConfig()), ScenarioConfig.class));
|
||||||
|
|
||||||
// 验证修改基础信息
|
// 验证修改基础信息
|
||||||
this.requestPostWithOk(DEFAULT_UPDATE, request);
|
this.requestPostWithOk(DEFAULT_UPDATE, request);
|
||||||
|
|
Loading…
Reference in New Issue