feat(接口测试): 接口导入其他协议的处理

--user=郭雨琦
This commit is contained in:
guoyuqi 2022-07-01 16:35:12 +08:00 committed by xiaomeinvG
parent 384f085872
commit d50e1c0ee9
5 changed files with 229 additions and 90 deletions

View File

@ -924,7 +924,11 @@ public class ApiDefinitionService {
if (!apiOp.isPresent()) {
apiDefinition.setId(UUID.randomUUID().toString());
apiDefinition.setRefId(sameRequest.get(0).getRefId());
if (sameRequest.get(0).getRefId() != null) {
apiDefinition.setRefId(sameRequest.get(0).getRefId());
} else {
apiDefinition.setRefId(apiDefinition.getId());
}
apiDefinition.setVersionId(apiTestImportRequest.getUpdateVersionId());
apiDefinition.setNum(sameRequest.get(0).getNum()); // 使用第一个num当作本次的num
apiDefinition.setOrder(sameRequest.get(0).getOrder());
@ -939,6 +943,11 @@ public class ApiDefinitionService {
apiDefinition.setCaseStatus(existApi.getCaseStatus());
apiDefinition.setNum(existApi.getNum()); //id 不变
apiDefinition.setRefId(existApi.getRefId());
if (existApi.getRefId() != null) {
apiDefinition.setRefId(existApi.getRefId());
} else {
apiDefinition.setRefId(apiDefinition.getId());
}
apiDefinition.setVersionId(apiTestImportRequest.getUpdateVersionId());
if (existApi.getUserId() != null) {
apiDefinition.setUserId(existApi.getUserId());
@ -963,7 +972,7 @@ public class ApiDefinitionService {
apiDefinition.setId(existApi.getId());
String request = setImportHashTree(apiDefinition);
apiDefinition.setOrder(existApi.getOrder());
apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
batchMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
apiDefinition.setRequest(request);
reSetImportCasesApiId(cases, originId, apiDefinition.getId());
reSetImportMocksApiId(mocks, originId, apiDefinition.getId(), apiDefinition.getNum());
@ -976,7 +985,7 @@ public class ApiDefinitionService {
apiDefinition.setOrder(existApi.getOrder());
reSetImportCasesApiId(cases, originId, apiDefinition.getId());
reSetImportMocksApiId(mocks, originId, apiDefinition.getId(), apiDefinition.getNum());
apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
batchMapper.updateByPrimaryKeyWithBLOBs(apiDefinition);
}
}
extApiDefinitionMapper.clearLatestVersion(apiDefinition.getRefId());
@ -1387,8 +1396,12 @@ public class ApiDefinitionService {
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
ProjectConfig config = projectApplicationService.getSpecificTypeValue(project.getId(), ProjectApplicationType.URL_REPEATABLE.name());
boolean urlRepeat = config.getUrlRepeatable();
UpdateApiModuleDTO updateApiModuleDTO = apiModuleService.checkApiModule(request, apiImport, initData, StringUtils.equals("fullCoverage", request.getModeId()), urlRepeat);
//过滤(一次只导入一个协议)
List<ApiDefinitionWithBLOBs> filterData = initData.stream().filter(t -> t.getProtocol().equals(request.getProtocol())).collect(toList());
if (filterData.isEmpty()) {
return;
}
UpdateApiModuleDTO updateApiModuleDTO = apiModuleService.checkApiModule(request, apiImport, filterData, StringUtils.equals("fullCoverage", request.getModeId()), urlRepeat);
List<ApiDefinitionWithBLOBs> updateList = updateApiModuleDTO.getNeedUpdateList();
List<ApiDefinitionWithBLOBs> data = updateApiModuleDTO.getDefinitionWithBLOBs();
List<ApiModule> moduleList = updateApiModuleDTO.getModuleList();
@ -1408,7 +1421,7 @@ public class ApiDefinitionService {
apiModuleMapper.insert(apiModule);
}
}
for (int i = 0; i < data.size(); i++) {
ApiDefinitionWithBLOBs item = data.get(i);
this.setModule(item);

View File

@ -467,7 +467,6 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
}
}
public List<ApiModule> getMListByProAndProtocol(String projectId, String protocol) {
ApiModuleExample example = new ApiModuleExample();
example.createCriteria().andProjectIdEqualTo(projectId).andProtocolEqualTo(protocol);
@ -593,7 +592,6 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
});
returnMap.put(protocol, idLIst);
}
}
}
}
@ -656,7 +654,6 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
initParentModulePathMap.put("root", initParentModulePath);
buildProcessData(nodeTreeByProjectId, pidChildrenMap, idPathMap, initParentModulePathMap);
//获取选中的模块
ApiModuleDTO chooseModule = null;
if (chooseModuleId != null) {
@ -665,92 +662,54 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
List<ApiDefinitionWithBLOBs> optionData = new ArrayList<>();
//去重 如果url可重复 则模块+名称+请求方式+路径 唯一否则 请求方式+路径唯一
//覆盖模式留重复的最后一个不覆盖留第一个
removeRepeat(data, fullCoverage, urlRepeat, optionData);
if (protocol.equals("HTTP")) {
//去重 如果url可重复 则模块+名称+请求方式+路径 唯一否则 请求方式+路径唯一
//覆盖模式留重复的最后一个不覆盖留第一个
removeHTTPRepeat(data, fullCoverage, urlRepeat, optionData);
//处理模块
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
//系统内重复的数据
List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs;
if (chooseModule != null) {
repeatApiDefinitionWithBLOBs = extApiDefinitionMapper.selectRepeatByBLOBsSameUrl(optionData, projectId, chooseModule.getId(), versionSet);
} else {
repeatApiDefinitionWithBLOBs = extApiDefinitionMapper.selectRepeatByBLOBs(optionData, projectId, versionSet);
}
//处理数据
if (urlRepeat) {
Map<String, ApiDefinitionWithBLOBs> methodPathMap;
//按照原来的顺序
if (chooseModule != null) {
String chooseModuleParentId = getChooseModuleParentId(chooseModule);
String chooseModulePath = getChooseModulePath(idPathMap, chooseModule, chooseModuleParentId);
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getName() + t.getMethod() + t.getPath() + chooseModulePath, api -> api));
//处理模块
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
//系统内重复的数据
List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs = getRepeatBLOBsList(projectId, versionSet, chooseModule, optionData);
//处理数据
if (urlRepeat) {
moduleMap = getRepeatApiModuleMap(fullCoverage, fullCoverageApi, moduleMap, toUpdateList, idPathMap, chooseModule, optionData, repeatApiDefinitionWithBLOBs);
} else {
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getName() + t.getMethod() + t.getPath() + (t.getModulePath() == null ? "" : t.getModulePath()), api -> api));
}
Map<String, List<ApiDefinitionWithBLOBs>> repeatDataMap = repeatApiDefinitionWithBLOBs.stream().collect(Collectors.groupingBy(t -> t.getName() + t.getMethod() + t.getPath() + t.getModulePath()));
//覆盖接口
if (fullCoverage) {
//允许覆盖模块用导入的重复数据的最后一条覆盖查询的所有重复数据
if (fullCoverageApi) {
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
startCoverModule(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
} else {
//覆盖但不覆盖模块
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
moduleMap = judgeModuleMap(moduleMap, methodPathMap, repeatDataMap);
startCover(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
}
} else {
//不覆盖,同一接口不做更新
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
removeSameData(repeatDataMap, methodPathMap, optionData);
}
moduleMap = getOnlyApiModuleMap(fullCoverage, fullCoverageApi, moduleMap, toUpdateList, idPathMap, chooseModule, optionData, repeatApiDefinitionWithBLOBs);
}
} else {
Map<String, ApiDefinitionWithBLOBs> methodPathMap;
Map<String, List<ApiDefinitionWithBLOBs>> repeatDataMap = repeatApiDefinitionWithBLOBs.stream().collect(Collectors.groupingBy(t -> t.getMethod() + t.getPath()));
//去重TCP,SQL,DUBBO 模块下名称唯一
removeRepeat(data, fullCoverage, optionData);
//按照原来的顺序
if (chooseModule != null) {
String chooseModuleParentId = getChooseModuleParentId(chooseModule);
String chooseModulePath = getChooseModulePath(idPathMap, chooseModule, chooseModuleParentId);
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getMethod() + chooseModulePath, api -> api));
} else {
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getMethod() + t.getPath(), api -> api));
}
//处理模块
setModule(moduleMap, pidChildrenMap, idPathMap, idModuleMap, optionData, chooseModule);
//处理数据
List<String> nameList = optionData.stream().map(ApiDefinitionWithBLOBs::getName).collect(Collectors.toList());
//获取系统内重复数据
List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs = extApiDefinitionMapper.selectRepeatByProtocol(nameList, protocol, versionSet);
Map<String, ApiDefinitionWithBLOBs> repeatDataMap = repeatApiDefinitionWithBLOBs.stream().collect(Collectors.toMap(t -> t.getName() + t.getModulePath(), api -> api));
Map<String, ApiDefinitionWithBLOBs> nameModuleMap = getNameApiMap(idPathMap, chooseModule, optionData, repeatApiDefinitionWithBLOBs);
//处理数据
if (fullCoverage) {
if (fullCoverageApi) {
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
startCoverModule(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
coverModule(toUpdateList, nameModuleMap, repeatDataMap);
} else {
//不覆盖模块
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
if (repeatDataMap.size() >= methodPathMap.size()) {
//导入文件没有新增接口无需创建接口模块
moduleMap = new HashMap<>();
}
startCover(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
moduleMap = cover(moduleMap, toUpdateList, nameModuleMap, repeatDataMap);
}
} else {
//不覆盖,同一接口不做更新
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
removeSameData(repeatDataMap, methodPathMap, optionData);
}
//不覆盖
removeRepeat(optionData, nameModuleMap, repeatDataMap);
}
}
return getUpdateApiModuleDTO(moduleMap, toUpdateList, optionData);
}
private UpdateApiModuleDTO getUpdateApiModuleDTO(Map<String, ApiModule> moduleMap, List<ApiDefinitionWithBLOBs> toUpdateList, List<ApiDefinitionWithBLOBs> optionData) {
UpdateApiModuleDTO updateApiModuleDTO = new UpdateApiModuleDTO();
updateApiModuleDTO.setModuleList(new ArrayList<>(moduleMap.values()));
updateApiModuleDTO.setNeedUpdateList(toUpdateList);
@ -758,7 +717,166 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
return updateApiModuleDTO;
}
private void removeRepeat(List<ApiDefinitionWithBLOBs> data, Boolean fullCoverage, boolean urlRepeat, List<ApiDefinitionWithBLOBs> optionData) {
private Map<String, ApiDefinitionWithBLOBs> getNameApiMap(Map<String, String> idPathMap, ApiModuleDTO chooseModule, List<ApiDefinitionWithBLOBs> optionData, List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs) {
Map<String, ApiDefinitionWithBLOBs> nameModuleMap = null;
if (chooseModule != null) {
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
String chooseModuleParentId = getChooseModuleParentId(chooseModule);
String chooseModulePath = getChooseModulePath(idPathMap, chooseModule, chooseModuleParentId);
nameModuleMap = optionData.stream().collect(Collectors.toMap(t -> t.getName() + chooseModulePath, api -> api));
}
} else {
nameModuleMap = optionData.stream().collect(Collectors.toMap(t -> t.getName() + (t.getModulePath() == null ? "" : t.getModulePath()), api -> api));
}
return nameModuleMap;
}
private List<ApiDefinitionWithBLOBs> getRepeatBLOBsList(String projectId, Set<String> versionSet, ApiModuleDTO chooseModule, List<ApiDefinitionWithBLOBs> optionData) {
List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs;
if (chooseModule != null) {
repeatApiDefinitionWithBLOBs = extApiDefinitionMapper.selectRepeatByBLOBsSameUrl(optionData, projectId, chooseModule.getId(), versionSet);
} else {
repeatApiDefinitionWithBLOBs = extApiDefinitionMapper.selectRepeatByBLOBs(optionData, projectId, versionSet);
}
return repeatApiDefinitionWithBLOBs;
}
private void removeRepeat(List<ApiDefinitionWithBLOBs> optionData, Map<String, ApiDefinitionWithBLOBs> nameModuleMap, Map<String, ApiDefinitionWithBLOBs> repeatDataMap) {
if (nameModuleMap != null) {
Map<String, ApiDefinitionWithBLOBs> finalNameModuleMap = nameModuleMap;
repeatDataMap.forEach((k, v) -> {
ApiDefinitionWithBLOBs apiDefinitionWithBLOBs = finalNameModuleMap.get(k);
if (apiDefinitionWithBLOBs != null) {
optionData.remove(apiDefinitionWithBLOBs);
}
});
}
}
private Map<String, ApiModule> cover(Map<String, ApiModule> moduleMap, List<ApiDefinitionWithBLOBs> toUpdateList, Map<String, ApiDefinitionWithBLOBs> nameModuleMap, Map<String, ApiDefinitionWithBLOBs> repeatDataMap) {
//覆盖但不覆盖模块
if (nameModuleMap != null) {
//导入文件没有新增场景无需创建接口模块
if (repeatDataMap.size() >= nameModuleMap.size()) {
moduleMap = new HashMap<>();
}
Map<String, ApiDefinitionWithBLOBs> finalNameModuleMap = nameModuleMap;
repeatDataMap.forEach((k, v) -> {
ApiDefinitionWithBLOBs apiDefinitionWithBLOBs = finalNameModuleMap.get(k);
if (apiDefinitionWithBLOBs != null) {
apiDefinitionWithBLOBs.setId(v.getId());
apiDefinitionWithBLOBs.setVersionId(v.getVersionId());
apiDefinitionWithBLOBs.setModuleId(v.getModuleId());
apiDefinitionWithBLOBs.setModulePath(v.getModulePath());
toUpdateList.add(apiDefinitionWithBLOBs);
}
});
}
return moduleMap;
}
private void coverModule(List<ApiDefinitionWithBLOBs> toUpdateList, Map<String, ApiDefinitionWithBLOBs> nameModuleMap, Map<String, ApiDefinitionWithBLOBs> repeatDataMap) {
if (nameModuleMap != null) {
Map<String, ApiDefinitionWithBLOBs> finalNameModuleMap = nameModuleMap;
repeatDataMap.forEach((k, v) -> {
ApiDefinitionWithBLOBs apiDefinitionWithBLOBs = finalNameModuleMap.get(k);
if (apiDefinitionWithBLOBs != null) {
apiDefinitionWithBLOBs.setId(v.getId());
apiDefinitionWithBLOBs.setVersionId(v.getVersionId());
toUpdateList.add(apiDefinitionWithBLOBs);
}
});
}
}
private void removeRepeat(List<ApiDefinitionWithBLOBs> data, Boolean fullCoverage, List<ApiDefinitionWithBLOBs> optionData) {
LinkedHashMap<String, List<ApiDefinitionWithBLOBs>> methodPathMap = data.stream().collect(Collectors.groupingBy(t -> t.getName() + (t.getModulePath() == null ? "" : t.getModulePath()), LinkedHashMap::new, Collectors.toList()));
if (fullCoverage) {
methodPathMap.forEach((k, v) -> {
optionData.add(v.get(v.size() - 1));
});
} else {
methodPathMap.forEach((k, v) -> {
optionData.add(v.get(0));
});
}
}
private Map<String, ApiModule> getOnlyApiModuleMap(Boolean fullCoverage, Boolean fullCoverageApi, Map<String, ApiModule> moduleMap, List<ApiDefinitionWithBLOBs> toUpdateList, Map<String, String> idPathMap, ApiModuleDTO chooseModule, List<ApiDefinitionWithBLOBs> optionData, List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs) {
Map<String, ApiDefinitionWithBLOBs> methodPathMap;
Map<String, List<ApiDefinitionWithBLOBs>> repeatDataMap = repeatApiDefinitionWithBLOBs.stream().collect(Collectors.groupingBy(t -> t.getMethod() + t.getPath()));
//按照原来的顺序
if (chooseModule != null) {
String chooseModuleParentId = getChooseModuleParentId(chooseModule);
String chooseModulePath = getChooseModulePath(idPathMap, chooseModule, chooseModuleParentId);
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getMethod() + chooseModulePath, api -> api));
} else {
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getMethod() + t.getPath(), api -> api));
}
if (fullCoverage) {
if (fullCoverageApi) {
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
startCoverModule(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
} else {
//不覆盖模块
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
if (repeatDataMap.size() >= methodPathMap.size()) {
//导入文件没有新增接口无需创建接口模块
moduleMap = new HashMap<>();
}
startCover(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
}
} else {
//不覆盖,同一接口不做更新
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
removeSameData(repeatDataMap, methodPathMap, optionData);
}
}
return moduleMap;
}
private Map<String, ApiModule> getRepeatApiModuleMap(Boolean fullCoverage, Boolean fullCoverageApi, Map<String, ApiModule> moduleMap, List<ApiDefinitionWithBLOBs> toUpdateList, Map<String, String> idPathMap, ApiModuleDTO chooseModule, List<ApiDefinitionWithBLOBs> optionData, List<ApiDefinitionWithBLOBs> repeatApiDefinitionWithBLOBs) {
Map<String, ApiDefinitionWithBLOBs> methodPathMap;
//按照原来的顺序
if (chooseModule != null) {
String chooseModuleParentId = getChooseModuleParentId(chooseModule);
String chooseModulePath = getChooseModulePath(idPathMap, chooseModule, chooseModuleParentId);
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getName() + t.getMethod() + t.getPath() + chooseModulePath, api -> api));
} else {
methodPathMap = optionData.stream().collect(Collectors.toMap(t -> t.getName() + t.getMethod() + t.getPath() + (t.getModulePath() == null ? "" : t.getModulePath()), api -> api));
}
Map<String, List<ApiDefinitionWithBLOBs>> repeatDataMap = repeatApiDefinitionWithBLOBs.stream().collect(Collectors.groupingBy(t -> t.getName() + t.getMethod() + t.getPath() + t.getModulePath()));
//覆盖接口
if (fullCoverage) {
//允许覆盖模块用导入的重复数据的最后一条覆盖查询的所有重复数据
if (fullCoverageApi) {
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
startCoverModule(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
} else {
//覆盖但不覆盖模块
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
moduleMap = judgeModuleMap(moduleMap, methodPathMap, repeatDataMap);
startCover(toUpdateList, optionData, methodPathMap, repeatDataMap);
}
}
} else {
//不覆盖,同一接口不做更新
if (!repeatApiDefinitionWithBLOBs.isEmpty()) {
removeSameData(repeatDataMap, methodPathMap, optionData);
}
}
return moduleMap;
}
private void removeHTTPRepeat(List<ApiDefinitionWithBLOBs> data, Boolean fullCoverage, boolean urlRepeat, List<ApiDefinitionWithBLOBs> optionData) {
if (urlRepeat) {
LinkedHashMap<String, List<ApiDefinitionWithBLOBs>> methodPathMap = data.stream().collect(Collectors.groupingBy(t -> t.getName() + t.getMethod() + t.getPath() + (t.getModulePath() == null ? "" : t.getModulePath()), LinkedHashMap::new, Collectors.toList()));
if (fullCoverage) {

View File

@ -491,7 +491,6 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
fullCoverageScenario = false;
}
//获取当前项目的当前协议下的所有模块的Tree
List<ApiScenarioModuleDTO> scenarioModules = extApiScenarioModuleMapper.getNodeTreeByProjectId(projectId);
List<ApiScenarioModuleDTO> nodeTreeByProjectId = this.getNodeTrees(scenarioModules);
@ -552,7 +551,6 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
//处理数据
if (fullCoverage) {
if (fullCoverageScenario) {
startCoverModule(toUpdateList, nameModuleMap, repeatDataMap);
} else {
//覆盖但不覆盖模块

View File

@ -97,6 +97,7 @@ public interface ExtApiDefinitionMapper {
List<ApiDefinitionWithBLOBs> selectRepeatByBLOBsSameUrl(@Param("blobs") List<ApiDefinitionWithBLOBs> blobs, @Param("projectId") String projectId, @Param("moduleId") String moduleId, @Param("versionIds") Set<String> versionIds);
List<ApiDefinitionWithBLOBs> selectRepeatByProtocol(@Param("names") List<String> names, @Param("protocol") String protocol, @Param("versionIds") Set<String> versionIds);
int countById(String id);
}

View File

@ -949,11 +949,7 @@
<update id="clearLatestVersion">
UPDATE api_definition
SET latest = 0
<where>
<if test="refId != null">
and ref_id = #{refId}
</if>
</where>
and ref_id = #{refId}
</update>
<update id="addLatestVersion">
@ -1038,6 +1034,18 @@
#{versionId}
</foreach>
</select>
<select id="selectRepeatByProtocol" resultType="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
SELECT * from api_definition
where name in
<foreach collection="names" item="name" separator="," open="(" close=")">
#{name}
</foreach>
and version_id in
<foreach collection="versionIds" item="versionId" separator="," open="(" close=")">
#{versionId}
</foreach>
and protocol = #{protocol}
</select>
<sql id="Same_Where_Clause">
<where>
<if test="blobs">
@ -1056,4 +1064,5 @@
</if>
</where>
</sql>
</mapper>