refactor(接口测试): 接口测试创建新版时支持附带 case 和 mock

--story=1006600 --user=刘瑞斌 【接口测试】接口定义创建新版本时支持复制CASE和MOCK https://www.tapd.cn/55049933/s/1127054
This commit is contained in:
CaptainB 2022-03-29 11:05:41 +08:00 committed by 刘瑞斌
parent 325d3c753f
commit d5cb56f21d
7 changed files with 116 additions and 49 deletions

View File

@ -64,6 +64,8 @@ public class SaveApiDefinitionRequest {
// 创建新版本时用到的 // 创建新版本时用到的
private boolean newVersionRemark; private boolean newVersionRemark;
private boolean newVersionDeps; private boolean newVersionDeps;
private boolean newVersionCase;
private boolean newVersionMock;
// 复制的请求Id // 复制的请求Id
private String sourceId; private String sourceId;
} }

View File

@ -117,6 +117,10 @@ public class ApiDefinitionService {
@Resource @Resource
private ExtApiTestCaseMapper extApiTestCaseMapper; private ExtApiTestCaseMapper extApiTestCaseMapper;
@Resource @Resource
private MockConfigMapper mockConfigMapper;
@Resource
private MockExpectConfigMapper mockExpectConfigMapper;
@Resource
private RelationshipEdgeService relationshipEdgeService; private RelationshipEdgeService relationshipEdgeService;
@Resource @Resource
private ApiDefinitionFollowMapper apiDefinitionFollowMapper; private ApiDefinitionFollowMapper apiDefinitionFollowMapper;
@ -611,30 +615,10 @@ public class ApiDefinitionService {
test.setCreateUser(SessionUtils.getUserId()); test.setCreateUser(SessionUtils.getUserId());
test.setOrder(oldApi.getOrder()); test.setOrder(oldApi.getOrder());
test.setRefId(oldApi.getRefId()); test.setRefId(oldApi.getRefId());
// 创建新版是否关联备注 // 保存扩展信息
if (!request.isNewVersionRemark()) { saveExtendInfo(request, test, oldApi);
test.setRemark(null);
}
apiDefinitionMapper.insertSelective(test); apiDefinitionMapper.insertSelective(test);
// 创建新版是否关联依赖关系
if (request.isNewVersionDeps()) {
List<RelationshipEdgeDTO> pre = this.getRelationshipApi(oldApi.getId(), "PRE");
List<String> targetIds = pre.stream().map(RelationshipEdgeKey::getTargetId).collect(Collectors.toList());
RelationshipEdgeRequest req = new RelationshipEdgeRequest();
req.setTargetIds(targetIds);
req.setType("API");
req.setId(test.getId());
relationshipEdgeService.saveBatch(req);
List<RelationshipEdgeDTO> post = this.getRelationshipApi(oldApi.getId(), "POST");
List<String> sourceIds = post.stream().map(RelationshipEdgeKey::getSourceId).collect(Collectors.toList());
RelationshipEdgeRequest req2 = new RelationshipEdgeRequest();
req2.setSourceIds(sourceIds);
req2.setType("API");
req2.setId(test.getId());
relationshipEdgeService.saveBatch(req2);
}
} }
// 同步修改用例路径 // 同步修改用例路径
@ -649,6 +633,58 @@ public class ApiDefinitionService {
return result; return result;
} }
private void saveExtendInfo(SaveApiDefinitionRequest request, ApiDefinitionWithBLOBs test, ApiDefinitionWithBLOBs oldApi) {
// 创建新版是否关联备注
if (!request.isNewVersionRemark()) {
test.setRemark(null);
}
if (request.isNewVersionCase()) {
test.setCaseTotal(oldApi.getCaseTotal());
extApiTestCaseMapper.insertNewVersionCases(test, oldApi);
}
if (request.isNewVersionMock()) {
MockConfigExample mockConfigExample = new MockConfigExample();
mockConfigExample.createCriteria().andApiIdEqualTo(oldApi.getId());
List<MockConfig> mockConfigs = mockConfigMapper.selectByExample(mockConfigExample);
mockConfigs.forEach(config -> {
String newMockConfigId = UUID.randomUUID().toString();
// 1
MockExpectConfigExample expectConfigExample = new MockExpectConfigExample();
expectConfigExample.createCriteria().andMockConfigIdEqualTo(config.getId());
List<MockExpectConfigWithBLOBs> mockExpectConfigWithBLOBs = mockExpectConfigMapper.selectByExampleWithBLOBs(expectConfigExample);
mockExpectConfigWithBLOBs.forEach(expectConfig -> {
expectConfig.setId(UUID.randomUUID().toString());
expectConfig.setMockConfigId(newMockConfigId);
mockExpectConfigMapper.insert(expectConfig);
});
// 2
config.setId(newMockConfigId);
config.setApiId(test.getId());
mockConfigMapper.insert(config);
});
}
// 创建新版是否关联依赖关系
if (request.isNewVersionDeps()) {
List<RelationshipEdgeDTO> pre = this.getRelationshipApi(oldApi.getId(), "PRE");
List<String> targetIds = pre.stream().map(RelationshipEdgeKey::getTargetId).collect(Collectors.toList());
RelationshipEdgeRequest req = new RelationshipEdgeRequest();
req.setTargetIds(targetIds);
req.setType("API");
req.setId(test.getId());
relationshipEdgeService.saveBatch(req);
List<RelationshipEdgeDTO> post = this.getRelationshipApi(oldApi.getId(), "POST");
List<String> sourceIds = post.stream().map(RelationshipEdgeKey::getSourceId).collect(Collectors.toList());
RelationshipEdgeRequest req2 = new RelationshipEdgeRequest();
req2.setSourceIds(sourceIds);
req2.setType("API");
req2.setId(test.getId());
relationshipEdgeService.saveBatch(req2);
}
}
/** /**
* 检查设置最新版本 * 检查设置最新版本
*/ */
@ -746,7 +782,7 @@ public class ApiDefinitionService {
} else { } else {
apiDefinition.setUserId(apiDefinition.getUserId()); apiDefinition.setUserId(apiDefinition.getUserId());
} }
if(apiDefinition.getModuleId()==null){ if (apiDefinition.getModuleId() == null) {
if (StringUtils.isEmpty(apiDefinition.getModuleId()) || "default-module".equals(apiDefinition.getModuleId())) { if (StringUtils.isEmpty(apiDefinition.getModuleId()) || "default-module".equals(apiDefinition.getModuleId())) {
initModulePathAndId(apiDefinition.getProjectId(), apiDefinition); initModulePathAndId(apiDefinition.getProjectId(), apiDefinition);
} }
@ -867,7 +903,7 @@ public class ApiDefinitionService {
apiDefinition.setVersionId(apiTestImportRequest.getUpdateVersionId()); apiDefinition.setVersionId(apiTestImportRequest.getUpdateVersionId());
apiDefinition.setNum(sameRequest.get(0).getNum()); // 使用第一个num当作本次的num apiDefinition.setNum(sameRequest.get(0).getNum()); // 使用第一个num当作本次的num
apiDefinition.setOrder(sameRequest.get(0).getOrder()); apiDefinition.setOrder(sameRequest.get(0).getOrder());
if(sameRequest.get(0).getUserId()!=null){ if (sameRequest.get(0).getUserId() != null) {
apiDefinition.setUserId(sameRequest.get(0).getUserId()); apiDefinition.setUserId(sameRequest.get(0).getUserId());
} }
batchMapper.insert(apiDefinition); batchMapper.insert(apiDefinition);
@ -879,7 +915,7 @@ public class ApiDefinitionService {
apiDefinition.setNum(existApi.getNum()); //id 不变 apiDefinition.setNum(existApi.getNum()); //id 不变
apiDefinition.setRefId(existApi.getRefId()); apiDefinition.setRefId(existApi.getRefId());
apiDefinition.setVersionId(apiTestImportRequest.getUpdateVersionId()); apiDefinition.setVersionId(apiTestImportRequest.getUpdateVersionId());
if(existApi.getUserId()!=null){ if (existApi.getUserId() != null) {
apiDefinition.setUserId(existApi.getUserId()); apiDefinition.setUserId(existApi.getUserId());
} }
// case 设置版本 // case 设置版本
@ -1671,9 +1707,9 @@ public class ApiDefinitionService {
urlParams[urlParams.length - 1] = ""; urlParams[urlParams.length - 1] = "";
} }
for (ApiDefinition api : apiList) { for (ApiDefinition api : apiList) {
if(StringUtils.equalsAny(api.getPath(),baseUrlSuffix,"/"+baseUrlSuffix)){ if (StringUtils.equalsAny(api.getPath(), baseUrlSuffix, "/" + baseUrlSuffix)) {
apiIdList.add(api.getId()); apiIdList.add(api.getId());
}else { } else {
String path = api.getPath(); String path = api.getPath();
if (StringUtils.isEmpty(path)) { if (StringUtils.isEmpty(path)) {
continue; continue;
@ -2024,7 +2060,7 @@ public class ApiDefinitionService {
public ApiDefinition getApiDefinition(ApiDefinitionExample apiDefinitionExample) { public ApiDefinition getApiDefinition(ApiDefinitionExample apiDefinitionExample) {
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(apiDefinitionExample); List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(apiDefinitionExample);
if(apiDefinitions==null||apiDefinitions.size()==0){ if (apiDefinitions == null || apiDefinitions.size() == 0) {
return null; return null;
} }
return apiDefinitions.get(0); return apiDefinitions.get(0);

View File

@ -72,4 +72,6 @@ public interface ExtApiTestCaseMapper {
List<ParamsDTO> findPassRateByIds(@Param("ids") List<String> ids); List<ParamsDTO> findPassRateByIds(@Param("ids") List<String> ids);
List<ParamsDTO> getApiCaseEnvironments(@Param("caseIds") List<String> caseIds); List<ParamsDTO> getApiCaseEnvironments(@Param("caseIds") List<String> caseIds);
void insertNewVersionCases(@Param("api") ApiDefinition apiDefinition, @Param("old") ApiDefinition old);
} }

View File

@ -809,4 +809,15 @@
AND a.latest = 1 AND a.latest = 1
</if> </if>
</sql> </sql>
<insert id="insertNewVersionCases">
INSERT INTO api_test_case(id, project_id, name, priority, api_definition_id, description, request, create_user_id,
update_user_id, create_time, update_time, num, tags, last_result_id, status, original_status,
delete_time, delete_user_id, version, `order`, case_status, version_id)
SELECT UUID(), project_id, name, priority, #{api.id}, description, request, #{api.createUser}, update_user_id,
create_time, update_time, num, tags, last_result_id, status, original_status, delete_time, delete_user_id,
version, `order`, case_status, #{api.versionId}
FROM api_test_case
WHERE api_definition_id = #{old.id};
</insert>
</mapper> </mapper>

View File

@ -16,4 +16,5 @@ public interface ExtMockExpectConfigMapper {
List<String> selectExlectNumByMockConfigId(String mockConfigId); List<String> selectExlectNumByMockConfigId(String mockConfigId);
String selectApiNumberByMockConfigId(String mockConfigId); String selectApiNumberByMockConfigId(String mockConfigId);
} }

View File

@ -169,6 +169,8 @@
<div> <div>
<el-checkbox v-model="httpForm.newVersionRemark">{{ $t('commons.remark') }}</el-checkbox> <el-checkbox v-model="httpForm.newVersionRemark">{{ $t('commons.remark') }}</el-checkbox>
<el-checkbox v-model="httpForm.newVersionDeps">{{ $t('commons.relationship.name') }}</el-checkbox> <el-checkbox v-model="httpForm.newVersionDeps">{{ $t('commons.relationship.name') }}</el-checkbox>
<el-checkbox v-model="httpForm.newVersionCase">CASE</el-checkbox>
<el-checkbox v-model="httpForm.newVersionMock">MOCK</el-checkbox>
</div> </div>
<template v-slot:footer> <template v-slot:footer>
@ -238,11 +240,11 @@ export default {
status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}], status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
}, },
httpForm: {environmentId: "", path: "", tags: []}, httpForm: {environmentId: "", path: "", tags: []},
newData:{environmentId: "", path: "", tags: []}, newData: {environmentId: "", path: "", tags: []},
dialogVisible:false, dialogVisible: false,
isShowEnable: true, isShowEnable: true,
showFollow: false, showFollow: false,
newShowFollow:false, newShowFollow: false,
maintainerOptions: [], maintainerOptions: [],
currentModule: {}, currentModule: {},
reqOptions: REQ_METHOD, reqOptions: REQ_METHOD,
@ -256,8 +258,8 @@ export default {
newMockBaseUrl: "", newMockBaseUrl: "",
count: 0, count: 0,
versionData: [], versionData: [],
oldRequest:Sampler, oldRequest: Sampler,
oldResponse:{}, oldResponse: {},
createNewVersionVisible: false, createNewVersionVisible: false,
}; };
}, },
@ -563,17 +565,17 @@ export default {
}); });
}, },
compare(row) { compare(row) {
this.$get('/api/definition/get/' + row.id+"/"+this.httpForm.refId, response => { this.$get('/api/definition/get/' + row.id + "/" + this.httpForm.refId, response => {
this.$get('/api/definition/get/' + response.data.id, res => { this.$get('/api/definition/get/' + response.data.id, res => {
if (res.data) { if (res.data) {
this.newData = res.data; this.newData = res.data;
this.dealWithTag(res.data); this.dealWithTag(res.data);
this.setRequest(res.data) this.setRequest(res.data);
if (!this.setRequest(res.data)) { if (!this.setRequest(res.data)) {
this.oldRequest = createComponent("HTTPSamplerProxy"); this.oldRequest = createComponent("HTTPSamplerProxy");
this.dialogVisible = true; this.dialogVisible = true;
} }
this.formatApi(res.data) this.formatApi(res.data);
} }
}); });
}); });
@ -593,14 +595,14 @@ export default {
} }
return false; return false;
}, },
dealWithTag(api){ dealWithTag(api) {
if(api.tags){ if (api.tags) {
if(Object.prototype.toString.call(api.tags)==="[object String]"){ if (Object.prototype.toString.call(api.tags) === "[object String]") {
api.tags = JSON.parse(api.tags); api.tags = JSON.parse(api.tags);
} }
} }
if(this.httpForm.tags){ if (this.httpForm.tags) {
if(Object.prototype.toString.call(this.httpForm.tags)==="[object String]"){ if (Object.prototype.toString.call(this.httpForm.tags) === "[object String]") {
this.httpForm.tags = JSON.parse(this.httpForm.tags); this.httpForm.tags = JSON.parse(this.httpForm.tags);
} }
} }
@ -647,7 +649,10 @@ export default {
stepArray[i].clazzName = TYPE_TO_C.get(stepArray[i].type); stepArray[i].clazzName = TYPE_TO_C.get(stepArray[i].type);
} }
if (stepArray[i].type === "Assertions" && !stepArray[i].document) { if (stepArray[i].type === "Assertions" && !stepArray[i].document) {
stepArray[i].document = {type: "JSON", data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}}; stepArray[i].document = {
type: "JSON",
data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}
};
} }
if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) { if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) {
this.sort(stepArray[i].hashTree); this.sort(stepArray[i].hashTree);
@ -657,6 +662,8 @@ export default {
}, },
cancelCreateNewVersion() { cancelCreateNewVersion() {
this.createNewVersionVisible = false; this.createNewVersionVisible = false;
// this.httpForm.versionId = row.id;
// this.httpForm.versionName = row.name;
this.getVersionHistory(); this.getVersionHistory();
}, },
checkout(row) { checkout(row) {
@ -670,13 +677,21 @@ export default {
// //
this.httpForm.versionId = row.id; this.httpForm.versionId = row.id;
this.httpForm.versionName = row.name; this.httpForm.versionName = row.name;
this.$set(this.httpForm, 'newVersionRemark', !!this.httpForm.remark); this.$set(this.httpForm, 'newVersionRemark', !!this.httpForm.remark);
this.$set(this.httpForm, 'newVersionDeps', this.$refs.apiOtherInfo.relationshipCount > 0); this.$set(this.httpForm, 'newVersionDeps', this.$refs.apiOtherInfo.relationshipCount > 0);
if (this.$refs.apiOtherInfo.relationshipCount > 0 || this.httpForm.remark) { this.$set(this.httpForm, 'newVersionCase', this.httpForm.caseTotal > 0);
this.createNewVersionVisible = true;
} else { this.$post('/mockConfig/genMockConfig', {projectId: this.projectId, apiId: this.httpForm.id}, response => {
this.saveApi(); this.$set(this.httpForm, 'newVersionMock', response.data.mockExpectConfigList.length > 0);
}
if (this.$refs.apiOtherInfo.relationshipCount > 0 || this.httpForm.remark ||
this.httpForm.newVersionCase || this.httpForm.newVersionMock) {
this.createNewVersionVisible = true;
} else {
this.saveApi();
}
});
}, },
del(row) { del(row) {
this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', { this.$alert(this.$t('api_test.definition.request.delete_confirm') + ' ' + row.name + " ", '', {

View File

@ -31,7 +31,7 @@
pageSizes: { pageSizes: {
type: Array, type: Array,
default: function () { default: function () {
return [5, 10, 20, 50, 100] return [5, 10, 20, 50]
} }
}, },
total: { total: {