From 6db9f9d08558fd9b6a6c13ddb3fa0afa6a4b3f18 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Thu, 13 Jan 2022 11:06:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=B2=E8=A1=8C=E9=A1=BA=E5=BA=8F=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1009552 --user=赵勇 【接口测试】测试用例批量执行,串行,执行顺序不对 https://www.tapd.cn/55049933/s/1091257 --- .../api/exec/api/ApiCaseExecuteService.java | 19 +++- .../automation/scenario/EditApiScenario.vue | 105 ++++++------------ .../component/ApiScenarioComponent.vue | 33 +++++- .../scenario/component/ComponentConfig.vue | 4 - .../scenario/component/IfController.vue | 3 - .../scenario/component/LoopController.vue | 3 - 6 files changed, 78 insertions(+), 89 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseExecuteService.java b/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseExecuteService.java index aefea80e15..fd756bd785 100644 --- a/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseExecuteService.java +++ b/backend/src/main/java/io/metersphere/api/exec/api/ApiCaseExecuteService.java @@ -22,7 +22,9 @@ import io.metersphere.dto.MsExecResponseDTO; import io.metersphere.dto.RunModeConfigDTO; import io.metersphere.service.EnvironmentGroupProjectService; import io.metersphere.utils.LoggerUtil; +import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.comparators.FixedOrderComparator; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; @@ -32,10 +34,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; @Service @Transactional(rollbackFor = Exception.class) @@ -145,6 +144,16 @@ public class ApiCaseExecuteService { List list = apiTestCaseMapper.selectByExampleWithBLOBs(example); LoggerUtil.debug("查询到执行数据:" + list.size()); + if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { + if (request.getCondition() == null || !request.getCondition().isSelectAll()) { + // 按照id指定顺序排序 + FixedOrderComparator fixedOrderComparator = new FixedOrderComparator(request.getIds()); + fixedOrderComparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE); + BeanComparator beanComparator = new BeanComparator("id", fixedOrderComparator); + Collections.sort(list, beanComparator); + } + } + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); ApiDefinitionExecResultMapper batchMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class); if (StringUtils.isEmpty(request.getTriggerMode())) { @@ -152,7 +161,7 @@ public class ApiCaseExecuteService { } List responseDTOS = new LinkedList<>(); - Map executeQueue = new HashMap<>(); + Map executeQueue = new LinkedHashMap<>(); String status = request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString()) ? APITestStatus.Waiting.name() : APITestStatus.Running.name(); list.forEach(caseWithBLOBs -> { ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.initBase(caseWithBLOBs.getId(), APITestStatus.Running.name(), null, request.getConfig()); diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 087a604d48..774002255a 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -213,7 +213,6 @@ @runScenario="runDebug" @stopScenario="stop" @setDomain="setDomain" - @reloadResult="reloadResult" @openScenario="openScenario"/> @@ -468,7 +467,6 @@ export default { showFollow: false, envGroupId: "", environmentType: ENV_TYPE.JSON, - debugResults: [], } }, watch: { @@ -641,7 +639,6 @@ export default { this.reqTotalTime = 0; this.reqTotal = 0; this.reqSuccess = 0; - this.debugResults = []; }, clearResult(arr) { if (arr) { @@ -723,83 +720,49 @@ export default { }, runningNodeChild(arr, resultData) { arr.forEach(item => { - if (resultData && resultData.startsWith("result_")) { - let data = JSON.parse(resultData.substring(7)); - if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) { - data.subRequestResults.forEach(subItem => { - if (item.data && item.data.id + "_" + item.data.parentIndex === subItem.resourceId) { - subItem.requestResult.console = data.responseResult.console; - item.data.requestResult.push(subItem); - // 更新父节点状态 - this.resultEvaluation(subItem.resourceId, subItem.success); - item.data.testing = false; - item.data.debug = true; - } - }) - } else if ((item.data && item.data.id + "_" + item.data.parentIndex === data.resourceId) - || (item.data && item.data.resourceId + "_" + item.data.parentIndex === data.resourceId)) { - if (item.data.requestResult) { - item.data.requestResult.push(data); - } else { - item.data.requestResult = [data]; - } - // 更新父节点状态 - this.resultEvaluation(data.resourceId, data.success); - item.data.testing = false; - item.data.debug = true; - } - } else if (item.data && item.data.id + "_" + item.data.parentIndex === resultData) { - item.data.testing = true; - this.runningEditParent(item.parent); - } + this.setResults(resultData, item); if (item.childNodes && item.childNodes.length > 0) { this.runningNodeChild(item.childNodes, resultData); } }) }, - setParentIndex(stepArray, fullPath) { - for (let i in stepArray) { - // 添加debug结果 - stepArray[i].data.parentIndex = fullPath ? fullPath + "_" + stepArray[i].data.index : stepArray[i].data.index; - if (stepArray[i].childNodes && stepArray[i].childNodes.length > 0) { - this.setParentIndex(stepArray[i].childNodes, stepArray[i].data.parentIndex); + setResults(resultData, item) { + if (resultData && resultData.startsWith("result_")) { + let data = JSON.parse(resultData.substring(7)); + if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) { + data.subRequestResults.forEach(subItem => { + if (item.data && item.data.id + "_" + item.data.parentIndex === subItem.resourceId) { + subItem.requestResult.console = data.responseResult.console; + if (!item.data.requestResult) { + item.data.requestResult = []; + } + item.data.requestResult.push(subItem); + // 更新父节点状态 + this.resultEvaluation(subItem.resourceId, subItem.success); + item.data.testing = false; + item.data.debug = true; + } + }) + } else if ((item.data && item.data.id + "_" + item.data.parentIndex === data.resourceId) + || (item.data && item.data.resourceId + "_" + item.data.parentIndex === data.resourceId)) { + if (!item.data.requestResult) { + item.data.requestResult = []; + } + item.data.requestResult.push(data); + // 更新父节点状态 + this.resultEvaluation(data.resourceId, data.success); + item.data.testing = false; + item.data.debug = true; } - } - }, - reloadResult() { - if (this.debugResults && this.debugResults.length > 0) { - this.setParentIndex(this.$refs.stepTree.root.childNodes); - this.debugResults.forEach(item => { - this.runningEvaluation(item); - }) + } else if (item.data && item.data.id + "_" + item.data.parentIndex === resultData) { + item.data.testing = true; + this.runningEditParent(item.parent); } }, runningEvaluation(resultData) { if (this.$refs.stepTree && this.$refs.stepTree.root) { this.$refs.stepTree.root.childNodes.forEach(item => { - if (item.data && item.data.id + "_" + item.data.parentIndex === resultData) { - item.data.testing = true; - } else if (resultData && resultData.startsWith("result_")) { - let data = JSON.parse(resultData.substring(7)); - if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) { - data.subRequestResults.forEach(subItem => { - if (item.data && item.data.id + "_" + item.data.parentIndex === subItem.resourceId) { - item.data.requestResult.push(subItem); - // 更新父节点状态 - this.resultEvaluation(subItem.resourceId, subItem.success); - item.data.testing = false; - item.data.debug = true; - } - }) - } else if (item.data && item.data.id + "_" + item.data.parentIndex === data.resourceId - || (item.data && item.data.resourceId + "_" + item.data.parentIndex === data.resourceId)) { - item.data.requestResult.push(data); - // 更新父节点状态 - this.resultEvaluation(data.resourceId, data.success); - item.data.testing = false; - item.data.debug = true; - } - } + this.setResults(resultData, item); if (item.childNodes && item.childNodes.length > 0) { this.runningNodeChild(item.childNodes, resultData); } @@ -818,16 +781,12 @@ export default { } } this.runningEvaluation(e.data); - if (e.data && e.data.startsWith("result_")) { - this.debugResults.push(e.data); - } this.message = getUUID(); if (e.data && e.data.indexOf("MS_TEST_END") !== -1) { this.runScenario = undefined; this.debugLoading = false; this.message = "stop"; this.stopDebug = "stop"; - this.currentScenario.debugResults = this.debugResults; this.reload(); } }, diff --git a/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue b/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue index ff68ab8f69..03969dfe47 100644 --- a/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue +++ b/frontend/src/business/components/api/automation/scenario/component/ApiScenarioComponent.vue @@ -113,6 +113,9 @@ export default { this.scenario.projectId = getCurrentProjectID(); } if (this.scenario.id && this.scenario.referenced === 'REF' && !this.scenario.loaded) { + let scenarios = JSON.parse(JSON.stringify(this.scenario.hashTree)); + let map = new Map(); + this.formatResult(map, scenarios); this.result = this.$get("/api/automation/getApiScenario/" + this.scenario.id, response => { if (response.data) { this.scenario.loaded = true; @@ -137,7 +140,7 @@ export default { this.scenario.headers = obj.headers; this.scenario.variables = obj.variables; this.scenario.environmentMap = obj.environmentMap; - this.$emit('reloadResult'); + this.setResult(this.scenario.hashTree, map); this.$emit('refReload'); } }) @@ -178,6 +181,34 @@ export default { }, }, methods: { + formatResult(map, scenarios) { + scenarios.forEach(item => { + if (this.stepFilter.get("AllSamplerProxy").indexOf(item.type) !== -1 && item.requestResult) { + let key = (item.id ? item.id : item.resourceId) + "_" + item.index; + if (map.has(key)) { + map.get(key).push(...item.requestResult); + } else { + map.set(key, item.requestResult); + } + } + if (item.hashTree && item.hashTree.length > 0) { + this.formatResult(map, item.hashTree); + } + }) + }, + setResult(array, scenarios) { + if (array && scenarios) { + array.forEach(item => { + let key = (item.id ? item.id : item.resourceId) + "_" + item.index; + if (scenarios.has(key)) { + item.requestResult = scenarios.get(key); + } + if (item.hashTree && item.hashTree.length > 0) { + this.setResult(item.hashTree, scenarios); + } + }) + } + }, run() { this.scenario.run = true; let runScenario = JSON.parse(JSON.stringify(this.scenario)); diff --git a/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue b/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue index cf4541b798..24c85081fd 100644 --- a/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue +++ b/frontend/src/business/components/api/automation/scenario/component/ComponentConfig.vue @@ -35,7 +35,6 @@ @refReload="refReload" @openScenario="openScenario" @setDomain="setDomain" - @reloadResult="reloadResult" /> @@ -236,9 +235,6 @@ export default { setDomain() { this.$emit("setDomain"); }, - reloadResult() { - this.$emit('reloadResult'); - } } } diff --git a/frontend/src/business/components/api/automation/scenario/component/IfController.vue b/frontend/src/business/components/api/automation/scenario/component/IfController.vue index 169a3a2d4a..4d95fa7c1d 100644 --- a/frontend/src/business/components/api/automation/scenario/component/IfController.vue +++ b/frontend/src/business/components/api/automation/scenario/component/IfController.vue @@ -106,9 +106,6 @@ this.reload(); }, }, - created() { - this.$emit('reloadResult'); - }, methods: { reload() { this.loading = true diff --git a/frontend/src/business/components/api/automation/scenario/component/LoopController.vue b/frontend/src/business/components/api/automation/scenario/component/LoopController.vue index 3a4af53e6f..aee3d10d34 100644 --- a/frontend/src/business/components/api/automation/scenario/component/LoopController.vue +++ b/frontend/src/business/components/api/automation/scenario/component/LoopController.vue @@ -161,9 +161,6 @@ export default { }, }; }, - created() { - this.$emit('reloadResult'); - }, watch: { message() { this.reload();