From 3354520179d8278ce359224def107a5d2e0fbbeb Mon Sep 17 00:00:00 2001 From: song-tianyang Date: Mon, 13 Jun 2022 16:51:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=89=A7=E8=A1=8C=E6=B5=8B=E8=AF=95=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E6=97=B6=E5=90=AB=E6=9C=89=E5=A4=B1=E8=B4=A5=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E4=B8=8D=E4=BC=9A=E5=8F=91=E9=80=81=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1013981 --user=宋天阳 【消息设置】测试计划的“执行成功”和“执行完成”是一个逻辑都是指测试计划执行完成就会收到消息通知 https://www.tapd.cn/55049933/s/1179702 --- .../track/service/TestPlanMessageService.java | 43 +++++- .../track/service/TestPlanReportService.java | 145 ++++++++++++------ 2 files changed, 137 insertions(+), 51 deletions(-) diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanMessageService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanMessageService.java index 8750c2d20d..71bb1bdb1a 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanMessageService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanMessageService.java @@ -3,11 +3,13 @@ package io.metersphere.track.service; import io.metersphere.api.service.ShareInfoService; import io.metersphere.base.domain.TestPlan; import io.metersphere.base.domain.TestPlanReport; -import io.metersphere.commons.constants.NoticeConstants; -import io.metersphere.commons.constants.ReportTriggerMode; -import io.metersphere.commons.constants.TestPlanReportStatus; +import io.metersphere.base.domain.TestPlanReportContentWithBLOBs; +import io.metersphere.base.domain.TestPlanWithBLOBs; +import io.metersphere.base.mapper.TestPlanMapper; +import io.metersphere.commons.constants.*; import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.CommonBeanFactory; +import io.metersphere.commons.utils.LogUtil; import io.metersphere.dto.BaseSystemConfigDTO; import io.metersphere.dto.UserDTO; import io.metersphere.i18n.Translator; @@ -36,11 +38,44 @@ public class TestPlanMessageService { private ProjectService projectService; @Lazy @Resource - private TestPlanService testPlanService; + private TestPlanService testPlanService; @Resource private UserService userService; @Resource private ShareInfoService shareInfoService; + @Resource + private TestPlanMapper testPlanMapper; + @Lazy + @Resource + private TestPlanReportService testPlanReportService; + + + @Async + public void checkTestPlanStatusAndSendMessage(TestPlanReport report, TestPlanReportContentWithBLOBs testPlanReportContent, boolean sendMessage) { + if (testPlanReportContent != null) { + report = testPlanReportService.checkTestPlanReportHasErrorCase(report, testPlanReportContent); + } + if (!report.getIsApiCaseExecuting() && !report.getIsPerformanceExecuting() && !report.getIsScenarioExecuting()) { + //更新TestPlan状态为完成 + TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(report.getTestPlanId()); + if (testPlan != null && !StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Completed.name())) { + testPlan.setStatus(TestPlanStatus.Completed.name()); + testPlanService.editTestPlan(testPlan); + } + try { + if (sendMessage && testPlan != null && StringUtils.equalsAny(report.getTriggerMode(), + ReportTriggerMode.MANUAL.name(), + ReportTriggerMode.API.name(), + ReportTriggerMode.SCHEDULE.name()) && !StringUtils.equalsIgnoreCase(report.getStatus(), ExecuteResult.TEST_PLAN_RUNNING.toString()) + ) { + //发送通知 + this.sendMessage(testPlan, report, testPlan.getProjectId()); + } + } catch (Exception e) { + LogUtil.error(e); + } + } + } @Async public void sendMessage(TestPlan testPlan, TestPlanReport testPlanReport, String projectId) { diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java index fa9a0dbffe..75f02b669d 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java @@ -3,7 +3,6 @@ package io.metersphere.track.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.esotericsoftware.minlog.Log; import io.metersphere.api.dto.automation.TestPlanFailureApiDTO; import io.metersphere.api.dto.automation.TestPlanFailureScenarioDTO; import io.metersphere.api.service.ApiDefinitionExecResultService; @@ -15,15 +14,9 @@ import io.metersphere.base.mapper.ext.*; import io.metersphere.commons.constants.*; import io.metersphere.commons.utils.*; import io.metersphere.constants.RunModeConstants; -import io.metersphere.dto.BaseSystemConfigDTO; import io.metersphere.dto.TestPlanExecuteReportDTO; -import io.metersphere.dto.UserDTO; -import io.metersphere.i18n.Translator; import io.metersphere.log.vo.OperatingLogDetails; -import io.metersphere.notice.sender.NoticeModel; -import io.metersphere.notice.service.NoticeSendService; import io.metersphere.service.ProjectService; -import io.metersphere.service.SystemParameterService; import io.metersphere.service.UserService; import io.metersphere.track.dto.*; import io.metersphere.track.request.report.QueryTestPlanReportRequest; @@ -31,7 +24,6 @@ import io.metersphere.track.request.report.TestPlanReportSaveRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testplan.LoadCaseRequest; import io.metersphere.track.request.testplan.TestplanRunRequest; -import org.apache.commons.beanutils.BeanMap; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -439,9 +431,10 @@ public class TestPlanReportService { if (testPlanReport != null && StringUtils.equalsIgnoreCase(testPlanReport.getStatus(), "stopped")) { return testPlanReport; } + boolean isSendMessage = false; + TestPlanReportContentWithBLOBs content = null; if (testPlanReport != null) { - boolean isSendMessage = false; - if(StringUtils.equalsIgnoreCase(testPlanReport.getStatus(),ExecuteResult.TEST_PLAN_RUNNING.toString())){ + if (StringUtils.equalsIgnoreCase(testPlanReport.getStatus(), ExecuteResult.TEST_PLAN_RUNNING.toString())) { isSendMessage = true; } //初始化测试计划包含组件信息 @@ -462,11 +455,9 @@ public class TestPlanReportService { TestPlanReportContentExample contentExample = new TestPlanReportContentExample(); contentExample.createCriteria().andTestPlanReportIdEqualTo(testPlanReportId); List contents = testPlanReportContentMapper.selectByExampleWithBLOBs(contentExample); - TestPlanReportContentWithBLOBs content = null; if (CollectionUtils.isNotEmpty(contents)) { content = contents.get(0); } - boolean hasErrorCase = false; if (content != null) { //更新content表对结束日期 content.setStartTime(testPlanReport.getStartTime()); @@ -475,11 +466,7 @@ public class TestPlanReportService { } //计算测试计划状态 if (StringUtils.equalsIgnoreCase(status, TestPlanReportStatus.COMPLETED.name())) { - if (hasErrorCase) { - testPlanReport.setStatus(TestPlanReportStatus.FAILED.name()); - } else { - testPlanReport.setStatus(TestPlanReportStatus.SUCCESS.name()); - } + testPlanReport.setStatus(TestPlanReportStatus.SUCCESS.name()); } else { testPlanReport.setStatus(status); } @@ -514,9 +501,9 @@ public class TestPlanReportService { testPlanService.runPlan(runRequest); } testPlanReportMapper.updateByPrimaryKey(testPlanReport); - //发送通知 - this.checkTestPlanStatusAndSendMessage(testPlanReport, isSendMessage); } + //发送通知 + testPlanMessageService.checkTestPlanStatusAndSendMessage(testPlanReport, content, isSendMessage); return testPlanReport; } @@ -573,7 +560,7 @@ public class TestPlanReportService { String testPlanStatus = this.getTestPlanReportStatus(testPlanReport, reportDTO); testPlanReport.setStatus(testPlanStatus); testPlanReportMapper.updateByPrimaryKey(testPlanReport); - this.checkTestPlanStatusAndSendMessage(testPlanReport, false); + testPlanMessageService.checkTestPlanStatusAndSendMessage(testPlanReport, null, false); } public TestPlanReportContentWithBLOBs parseReportDaoToReportContent(TestPlanSimpleReportDTO reportDTO, TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs) { @@ -677,29 +664,6 @@ public class TestPlanReportService { return status; } - public void checkTestPlanStatusAndSendMessage(TestPlanReport report, boolean sendMessage) { - if (!report.getIsApiCaseExecuting() && !report.getIsPerformanceExecuting() && !report.getIsScenarioExecuting()) { - //更新TestPlan状态为完成 - TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(report.getTestPlanId()); - if (testPlan != null && !StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Completed.name())) { - testPlan.setStatus(TestPlanStatus.Completed.name()); - testPlanService.editTestPlan(testPlan); - } - try { - if (sendMessage && testPlan != null && StringUtils.equalsAny(report.getTriggerMode(), - ReportTriggerMode.MANUAL.name(), - ReportTriggerMode.API.name(), - ReportTriggerMode.SCHEDULE.name()) && !StringUtils.equalsIgnoreCase(report.getStatus(), ExecuteResult.TEST_PLAN_RUNNING.toString()) - ) { - //发送通知 - testPlanMessageService.sendMessage(testPlan, report, testPlan.getProjectId()); - } - } catch (Exception e) { - LogUtil.error(e); - } - } - } - public TestPlanReport getTestPlanReport(String planId) { return testPlanReportMapper.selectByPrimaryKey(planId); } @@ -964,8 +928,8 @@ public class TestPlanReportService { Map testPlanApiCaseIdAndReportIdMap = new LinkedHashMap<>(); Map testPlanScenarioIdAndReportIdMap = new LinkedHashMap<>(); Map testPlanLoadCaseIdAndReportIdMap = new LinkedHashMap<>(); - Map apiCaseInfoDTOMap = new LinkedHashMap<>(); - Map scenarioInfoDTOMap = new LinkedHashMap<>(); + Map apiCaseInfoDTOMap = new LinkedHashMap<>(); + Map scenarioInfoDTOMap = new LinkedHashMap<>(); if (testPlanReportContentWithBLOBs != null) { if (StringUtils.isNotEmpty(testPlanReportContentWithBLOBs.getPlanApiCaseReportStruct())) { @@ -982,7 +946,7 @@ public class TestPlanReportService { } else { for (TestPlanFailureApiDTO item : apiCaseInfoDTOList) { testPlanApiCaseIdAndReportIdMap.put(item.getId(), item.getReportId()); - apiCaseInfoDTOMap.put(item.getId(),item); + apiCaseInfoDTOMap.put(item.getId(), item); } } } @@ -1000,7 +964,7 @@ public class TestPlanReportService { } else { for (TestPlanFailureScenarioDTO item : scenarioInfoDTOList) { testPlanScenarioIdAndReportIdMap.put(item.getId(), item.getReportId()); - scenarioInfoDTOMap.put(item.getId(),item); + scenarioInfoDTOMap.put(item.getId(), item); } } } @@ -1038,4 +1002,91 @@ public class TestPlanReportService { testPlanReportMapper.updateByPrimaryKey(testPlanReport); } } + + public TestPlanReport checkTestPlanReportHasErrorCase(TestPlanReport report, TestPlanReportContentWithBLOBs testPlanReportContent) { + if (testPlanReportContent != null) { + boolean hasErrorCase = this.isTestPlanReportHasErrorCase(testPlanReportContent); + if (hasErrorCase) { + report.setStatus(TestPlanReportStatus.FAILED.name()); + } else { + report.setStatus(TestPlanReportStatus.SUCCESS.name()); + } + testPlanReportMapper.updateByPrimaryKeySelective(report); + } + return report; + } + + private boolean isTestPlanReportHasErrorCase(TestPlanReportContentWithBLOBs content) { + //更新测试计划里用例的执行结果,并检查是否有错误用例。 + boolean hasErrorCase = false; + if (content != null) { + //更新接口用例、场景用例的最终执行状态 + if (!hasErrorCase && StringUtils.isNotEmpty(content.getPlanApiCaseReportStruct())) { + try { + List apiTestCases = JSONArray.parseArray(content.getPlanApiCaseReportStruct(), TestPlanFailureApiDTO.class); + List reportIdList = new ArrayList<>(); + apiTestCases.forEach(item -> { + if (StringUtils.isNotEmpty(item.getReportId())) { + reportIdList.add(item.getReportId()); + } + }); + Map reportResult = apiDefinitionExecResultService.selectReportResultByReportIds(reportIdList); + String defaultStatus = "error"; + for (TestPlanFailureApiDTO dto : apiTestCases) { + String reportId = dto.getReportId(); + if (StringUtils.isEmpty(reportId)) { + dto.setExecResult(defaultStatus); + } else { + String execStatus = reportResult.get(reportId); + if (execStatus == null) { + execStatus = defaultStatus; + } + dto.setExecResult(execStatus); + } + if (!StringUtils.equalsAnyIgnoreCase(dto.getExecResult(), "success")) { + hasErrorCase = true; + } + } + } catch (Exception e) { + LogUtil.error("Parse test plan report api case error! ", e); + } + } + + if (!hasErrorCase && StringUtils.isNotEmpty(content.getPlanScenarioReportStruct())) { + try { + List scenarioCases = JSONArray.parseArray(content.getPlanScenarioReportStruct(), TestPlanFailureScenarioDTO.class); + List reportIdList = new ArrayList<>(); + scenarioCases.forEach(item -> { + if (StringUtils.isNotEmpty(item.getReportId())) { + reportIdList.add(item.getReportId()); + } + }); + String defaultStatus = "Fail"; + Map reportStatus = apiScenarioReportService.getReportStatusByReportIds(reportIdList); + + for (TestPlanFailureScenarioDTO dto : scenarioCases) { + String reportId = dto.getReportId(); + if (StringUtils.isNotEmpty(reportId)) { + String execStatus = reportStatus.get(reportId); + if (execStatus == null) { + execStatus = defaultStatus; + } else { + if (StringUtils.equalsIgnoreCase(execStatus, "Error")) { + execStatus = "Fail"; + } + } + dto.setLastResult(execStatus); + dto.setStatus(execStatus); + if (!StringUtils.equalsAnyIgnoreCase(execStatus, "success")) { + hasErrorCase = true; + } + } + } + } catch (Exception e) { + LogUtil.error("Parse test plan report cenario case error!", e); + } + } + } + return hasErrorCase; + } }