From fb5c5ee04f71079435da71732033276fb8febf18 Mon Sep 17 00:00:00 2001 From: song-tianyang Date: Mon, 17 Jan 2022 16:44:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E6=8A=A5=E5=91=8A):=20=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E6=8A=A5=E5=91=8A=E5=A2=9E=E5=8A=A0=E8=AF=AF=E6=8A=A5=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 测试计划报告增加误报数据配置 --- .../ApiDefinitionExecResultService.java | 10 +- .../api/service/ApiScenarioReportService.java | 23 +-- .../ApiScenarioReportStructureService.java | 1 - .../TestPlanReportContentWithBLOBs.java | 4 + .../mapper/TestPlanReportContentMapper.xml | 42 +++++- .../mapper/ext/ExtTestPlanApiCaseMapper.xml | 2 +- .../ext/ExtTestPlanScenarioCaseMapper.xml | 2 +- .../commons/utils/TestPlanUtils.java | 2 + .../controller/ShareController.java | 12 +- .../controller/TestPlanApiCaseController.java | 5 + .../TestPlanScenarioCaseController.java | 5 + .../dto/TestPlanScenarioStepCountDTO.java | 1 + .../track/dto/TestPlanSimpleReportDTO.java | 2 + .../track/service/TestPlanApiCaseService.java | 6 + .../track/service/TestPlanReportService.java | 12 ++ .../service/TestPlanScenarioCaseService.java | 13 +- .../track/service/TestPlanService.java | 97 ++++++------- .../db/migration/V106__v1.17_release.sql | 3 + .../api/definition/model/JsonData.js | 3 +- .../tableItems/planview/StatusTableItem.vue | 1 + .../comonents/api/TestPlanApiScenarioList.vue | 3 + .../report/detail/TestPlanApiReport.vue | 31 +++- .../report/detail/TestPlanReportContent.vue | 4 + .../detail/component/ApiCaseFailureResult.vue | 105 ++++++++------ .../report/detail/component/ApiCases.vue | 12 +- .../report/detail/component/ApiResult.vue | 1 + .../component/ApiScenarioFailureResult.vue | 135 ++++++++++-------- frontend/src/network/test-plan.js | 16 ++- 28 files changed, 363 insertions(+), 190 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java index 1adbf6c877..ab31b6252d 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java @@ -204,8 +204,16 @@ public class ApiDefinitionExecResultService { for (RequestResult item : requestResults) { if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { - this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst); + ApiDefinitionExecResult reportResult = this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst); String status = item.isSuccess() ? "success" : "error"; + if(reportResult != null){ + status = reportResult.getStatus(); + } + //对响应内容进行进一步解析。如果有附加信息(比如误报库信息),则根据附加信息内的数据进行其他判读 + RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(item); + if(MapUtils.isNotEmpty(expandDTO.getAttachInfoMap())){ + status = expandDTO.getStatus(); + } if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) { TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId()); if (apiCase != null) { diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java index 638bca26be..9dabc11cc7 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java @@ -234,12 +234,18 @@ public class ApiScenarioReportService { public ApiScenarioReport updatePlanCase(List requestResults, ResultDTO dto) { long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count(); + String status = getStatus(requestResults, dto); + ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode()); TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(dto.getTestId()); if (testPlanApiScenario != null) { - if (errorSize > 0) { - testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name()); - } else { - testPlanApiScenario.setLastResult(ScenarioStatus.Success.name()); + if(report != null){ + testPlanApiScenario.setLastResult(report.getStatus()); + }else { + if (errorSize > 0) { + testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name()); + } else { + testPlanApiScenario.setLastResult(ScenarioStatus.Success.name()); + } } long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count(); @@ -263,8 +269,7 @@ public class ApiScenarioReportService { apiScenarioMapper.updateByPrimaryKey(scenario); } } - String status = getStatus(requestResults, dto); - ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode()); + return report; } @@ -284,11 +289,7 @@ public class ApiScenarioReportService { report.setScenarioId(testPlanApiScenario.getApiScenarioId()); report.setEndTime(System.currentTimeMillis()); apiScenarioReportMapper.updateByPrimaryKeySelective(report); - if (errorSize > 0) { - testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name()); - } else { - testPlanApiScenario.setLastResult(ScenarioStatus.Success.name()); - } + testPlanApiScenario.setLastResult(report.getStatus()); long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count(); String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size()); testPlanApiScenario.setPassRate(passRate); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java index 544651a74f..f2c1ea7edd 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java @@ -146,7 +146,6 @@ public class ApiScenarioReportStructureService { } else if (step.getValue().getError() > 0) { isError.set(isError.longValue() + 1); } - break; } else if (CollectionUtils.isNotEmpty(step.getChildren())) { scenarioCalculate(step.getChildren(), isError, isErrorReport); } diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanReportContentWithBLOBs.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportContentWithBLOBs.java index deed357ad0..b9b8aae102 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestPlanReportContentWithBLOBs.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportContentWithBLOBs.java @@ -43,5 +43,9 @@ public class TestPlanReportContentWithBLOBs extends TestPlanReportContent implem private String planLoadCaseReportStruct; + private String errorReportCases; + + private String errorReportScenarios; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportContentMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportContentMapper.xml index fbe153e17c..6319bbfc15 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportContentMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportContentMapper.xml @@ -29,6 +29,8 @@ + + @@ -96,7 +98,7 @@ config, summary, function_result, api_result, load_result, function_all_cases, function_failure_cases, issue_list, api_all_cases, api_failure_cases, scenario_all_cases, scenario_failure_cases, load_all_Cases, load_failure_cases, plan_scenario_report_struct, plan_api_case_report_struct, - plan_load_case_report_struct + plan_load_case_report_struct, error_report_cases, error_report_scenarios @@ -409,6 +425,12 @@ plan_load_case_report_struct = #{record.planLoadCaseReportStruct,jdbcType=LONGVARCHAR}, + + error_report_cases = #{record.errorReportCases,jdbcType=LONGVARCHAR}, + + + error_report_scenarios = #{record.errorReportScenarios,jdbcType=LONGVARCHAR}, + @@ -440,7 +462,9 @@ load_failure_cases = #{record.loadFailureCases,jdbcType=LONGVARCHAR}, plan_scenario_report_struct = #{record.planScenarioReportStruct,jdbcType=LONGVARCHAR}, plan_api_case_report_struct = #{record.planApiCaseReportStruct,jdbcType=LONGVARCHAR}, - plan_load_case_report_struct = #{record.planLoadCaseReportStruct,jdbcType=LONGVARCHAR} + plan_load_case_report_struct = #{record.planLoadCaseReportStruct,jdbcType=LONGVARCHAR}, + error_report_cases = #{record.errorReportCases,jdbcType=LONGVARCHAR}, + error_report_scenarios = #{record.errorReportScenarios,jdbcType=LONGVARCHAR} @@ -534,6 +558,12 @@ plan_load_case_report_struct = #{planLoadCaseReportStruct,jdbcType=LONGVARCHAR}, + + error_report_cases = #{errorReportCases,jdbcType=LONGVARCHAR}, + + + error_report_scenarios = #{errorReportScenarios,jdbcType=LONGVARCHAR}, + where id = #{id,jdbcType=VARCHAR} @@ -562,7 +592,9 @@ load_failure_cases = #{loadFailureCases,jdbcType=LONGVARCHAR}, plan_scenario_report_struct = #{planScenarioReportStruct,jdbcType=LONGVARCHAR}, plan_api_case_report_struct = #{planApiCaseReportStruct,jdbcType=LONGVARCHAR}, - plan_load_case_report_struct = #{planLoadCaseReportStruct,jdbcType=LONGVARCHAR} + plan_load_case_report_struct = #{planLoadCaseReportStruct,jdbcType=LONGVARCHAR}, + error_report_cases = #{errorReportCases,jdbcType=LONGVARCHAR}, + error_report_scenarios = #{errorReportScenarios,jdbcType=LONGVARCHAR} where id = #{id,jdbcType=VARCHAR} diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml index f9f8c3b17a..d599aa2d21 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml @@ -321,7 +321,7 @@ on t.api_case_id = c.id and t.test_plan_id = #{planId} - and t.status = 'error' + and t.status = #{status} and (c.status != 'Trash' or c.status is null) where t.test_plan_id = #{planId}; diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanScenarioCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanScenarioCaseMapper.xml index e2cf25949c..effc4088e7 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanScenarioCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanScenarioCaseMapper.xml @@ -214,7 +214,7 @@ on t.api_scenario_id = c.id and (c.status != 'Trash' or c.status is null) and t.test_plan_id = #{planId} - and t.last_result = 'Fail' + and t.last_result = #{status} where t.test_plan_id = #{planId} diff --git a/backend/src/main/java/io/metersphere/commons/utils/TestPlanUtils.java b/backend/src/main/java/io/metersphere/commons/utils/TestPlanUtils.java index d3875d2488..ebabaddf47 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/TestPlanUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/TestPlanUtils.java @@ -1,5 +1,6 @@ package io.metersphere.commons.utils; +import io.metersphere.commons.constants.ExecuteResult; import io.metersphere.commons.constants.TestPlanTestCaseStatus; import io.metersphere.track.dto.PlanReportCaseDTO; import io.metersphere.track.dto.TestCaseReportStatusResultDTO; @@ -51,6 +52,7 @@ public class TestPlanUtils { addToReportStatusResultList(resultMap, statusResult, "Success"); addToReportStatusResultList(resultMap, statusResult, "SUCCESS"); addToReportStatusResultList(resultMap, statusResult, TestPlanTestCaseStatus.Prepare.name()); + addToReportStatusResultList(resultMap, statusResult, ExecuteResult.errorReportResult.name()); } /** diff --git a/backend/src/main/java/io/metersphere/controller/ShareController.java b/backend/src/main/java/io/metersphere/controller/ShareController.java index e9dee178b1..df7eca3811 100644 --- a/backend/src/main/java/io/metersphere/controller/ShareController.java +++ b/backend/src/main/java/io/metersphere/controller/ShareController.java @@ -112,7 +112,11 @@ public class ShareController { shareInfoService.validate(shareId, planId); return testPlanApiCaseService.getFailureCases(planId); } - + @GetMapping("/test/plan/api/case/list/errorReport/{shareId}/{planId}") + public List getErrorReportApiCaseList(@PathVariable String shareId, @PathVariable String planId) { + shareInfoService.validate(shareId, planId); + return testPlanApiCaseService.getErrorReportCases(planId); + } @GetMapping("/test/plan/api/case/list/all/{shareId}/{planId}") public List getApiAllList(@PathVariable String shareId, @PathVariable String planId) { shareInfoService.validate(shareId, planId); @@ -131,6 +135,12 @@ public class ShareController { return testPlanScenarioCaseService.getAllCases(planId); } + @GetMapping("/test/plan/scenario/case/list/errorReport/{shareId}/{planId}") + public List getScenarioErrorReportList(@PathVariable String shareId, @PathVariable String planId) { + shareInfoService.validate(shareId, planId); + return testPlanScenarioCaseService.getErrorReportCases(planId); + } + @GetMapping("/api/definition/report/getReport/{shareId}/{testId}") public APIReportResult getApiReport(@PathVariable String shareId, @PathVariable String testId) { // shareInfoService.apiReportValidate(shareId, testId); diff --git a/backend/src/main/java/io/metersphere/track/controller/TestPlanApiCaseController.java b/backend/src/main/java/io/metersphere/track/controller/TestPlanApiCaseController.java index 4560b07c42..fd2c5f1255 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestPlanApiCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestPlanApiCaseController.java @@ -40,6 +40,11 @@ public class TestPlanApiCaseController { return testPlanApiCaseService.getFailureCases(planId); } + @GetMapping("/list/errorReport/{planId}") + public List getErrorReportList(@PathVariable String planId) { + return testPlanApiCaseService.getErrorReportCases(planId); + } + @GetMapping("/list/all/{planId}") public List getAllList(@PathVariable String planId) { return testPlanApiCaseService.getAllCases(planId); diff --git a/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java b/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java index 8f095412a3..80f1e756d6 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestPlanScenarioCaseController.java @@ -40,6 +40,11 @@ public class TestPlanScenarioCaseController { return testPlanScenarioCaseService.getFailureCases(planId); } + @GetMapping("/list/errorReport/{planId}") + public List getErrorReportList(@PathVariable String planId) { + return testPlanScenarioCaseService.getErrorReportCases(planId); + } + @GetMapping("/list/all/{planId}") public List getAllList(@PathVariable String planId) { return testPlanScenarioCaseService.getAllCases(planId); diff --git a/backend/src/main/java/io/metersphere/track/dto/TestPlanScenarioStepCountDTO.java b/backend/src/main/java/io/metersphere/track/dto/TestPlanScenarioStepCountDTO.java index 8157ba1358..2b40e63523 100644 --- a/backend/src/main/java/io/metersphere/track/dto/TestPlanScenarioStepCountDTO.java +++ b/backend/src/main/java/io/metersphere/track/dto/TestPlanScenarioStepCountDTO.java @@ -12,6 +12,7 @@ public class TestPlanScenarioStepCountDTO { private int scenarioStepTotal; private int scenarioStepSuccess; private int scenarioStepError; + private int scenarioStepErrorReport; private List underwayIds = new ArrayList<>(); private int scenarioStepUnderway; } diff --git a/backend/src/main/java/io/metersphere/track/dto/TestPlanSimpleReportDTO.java b/backend/src/main/java/io/metersphere/track/dto/TestPlanSimpleReportDTO.java index 2211081364..dc7702b531 100644 --- a/backend/src/main/java/io/metersphere/track/dto/TestPlanSimpleReportDTO.java +++ b/backend/src/main/java/io/metersphere/track/dto/TestPlanSimpleReportDTO.java @@ -33,4 +33,6 @@ public class TestPlanSimpleReportDTO extends TestPlanReportContent { List scenarioAllCases; List loadAllCases; List loadFailureCases; + List errorReportCases; + List errorReportScenarios; } diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java index d837a984f3..3c86e63c16 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java @@ -17,6 +17,7 @@ import io.metersphere.base.mapper.ApiTestCaseMapper; import io.metersphere.base.mapper.TestPlanApiCaseMapper; import io.metersphere.base.mapper.TestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper; +import io.metersphere.commons.constants.ExecuteResult; import io.metersphere.commons.utils.*; import io.metersphere.controller.request.ResetOrderRequest; import io.metersphere.dto.MsExecResponseDTO; @@ -435,4 +436,9 @@ public class TestPlanApiCaseService { } return buildCases(apiTestCases); } + + public List getErrorReportCases(String planId) { + List apiTestCases = extTestPlanApiCaseMapper.getFailureList(planId, ExecuteResult.errorReportResult.name()); + return buildCases(apiTestCases); + } } 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 1cf46d3f36..3dd50e1a24 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java @@ -460,6 +460,12 @@ public class TestPlanReportService { if (reportDTO.getLoadFailureCases() != null) { testPlanReportContentWithBLOBs.setLoadFailureCases(JSONObject.toJSONString(reportDTO.getLoadFailureCases())); } + if (reportDTO.getErrorReportCases() != null) { + testPlanReportContentWithBLOBs.setErrorReportCases(JSONObject.toJSONString(reportDTO.getErrorReportCases())); + } + if (reportDTO.getErrorReportScenarios() != null) { + testPlanReportContentWithBLOBs.setErrorReportScenarios(JSONObject.toJSONString(reportDTO.getErrorReportScenarios())); + } return testPlanReportContentWithBLOBs; } @@ -732,6 +738,12 @@ public class TestPlanReportService { if (StringUtils.isNotBlank(testPlanReportContent.getLoadFailureCases())) { testPlanReportDTO.setLoadFailureCases(JSONObject.parseArray(testPlanReportContent.getLoadFailureCases(), TestPlanLoadCaseDTO.class)); } + if (StringUtils.isNotBlank(testPlanReportContent.getErrorReportCases())) { + testPlanReportDTO.setErrorReportCases(JSONObject.parseArray(testPlanReportContent.getErrorReportCases(), TestPlanFailureApiDTO.class)); + } + if (StringUtils.isNotBlank(testPlanReportContent.getErrorReportScenarios())) { + testPlanReportDTO.setErrorReportScenarios(JSONObject.parseArray(testPlanReportContent.getErrorReportScenarios(), TestPlanFailureScenarioDTO.class)); + } testPlanReportDTO.setId(reportId); TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(testPlanReportContent.getTestPlanReportId()); testPlanReportDTO.setName(testPlanReport.getName()); diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java index 21684b0fe7..1ea18a1e34 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanScenarioCaseService.java @@ -15,6 +15,7 @@ import io.metersphere.base.mapper.TestPlanApiScenarioMapper; import io.metersphere.base.mapper.TestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanScenarioCaseMapper; import io.metersphere.commons.constants.ApiRunMode; +import io.metersphere.commons.constants.ExecuteResult; import io.metersphere.commons.constants.TestPlanTestCaseStatus; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.PageUtils; @@ -450,15 +451,13 @@ public class TestPlanScenarioCaseService { for (PlanReportCaseDTO item : planReportCaseDTOS) { calculateScenarioResultDTO(item, stepCount); } - int underwayStepsCounts = getUnderwayStepsCounts(stepCount.getUnderwayIds()); - List stepResult = new ArrayList<>(); getScenarioCaseReportStatusResultDTO(TestPlanTestCaseStatus.Failure.name(), stepCount.getScenarioStepError(), stepResult); getScenarioCaseReportStatusResultDTO(TestPlanTestCaseStatus.Pass.name(), stepCount.getScenarioStepSuccess(), stepResult); + getScenarioCaseReportStatusResultDTO(ExecuteResult.errorReportResult.name(), stepCount.getScenarioStepErrorReport(), stepResult); getScenarioCaseReportStatusResultDTO(TestPlanTestCaseStatus.Underway.name(), - stepCount.getScenarioStepTotal() - stepCount.getScenarioStepSuccess() - stepCount.getScenarioStepError() + underwayStepsCounts, stepResult); - + stepCount.getScenarioStepTotal() - stepCount.getScenarioStepSuccess() - stepCount.getScenarioStepError() -stepCount.getScenarioStepErrorReport() + underwayStepsCounts, stepResult); apiResult.setApiScenarioData(statusResult); apiResult.setApiScenarioStepData(stepResult); } @@ -488,6 +487,7 @@ public class TestPlanScenarioCaseService { stepCount.setScenarioStepTotal(stepCount.getScenarioStepTotal() + jsonObject.getIntValue("scenarioStepTotal")); stepCount.setScenarioStepSuccess(stepCount.getScenarioStepSuccess() + jsonObject.getIntValue("scenarioStepSuccess")); stepCount.setScenarioStepError(stepCount.getScenarioStepError() + jsonObject.getIntValue("scenarioStepError")); + stepCount.setScenarioStepErrorReport(stepCount.getScenarioStepErrorReport() + jsonObject.getIntValue("scenarioStepErrorReport")); } } } else { @@ -583,4 +583,9 @@ public class TestPlanScenarioCaseService { testPlanApiScenarioMapper::updateByPrimaryKeySelective); } + public List getErrorReportCases(String planId) { + List apiTestCases = + extTestPlanScenarioCaseMapper.getFailureList(planId, ExecuteResult.errorReportResult.name()); + return buildCases(apiTestCases); + } } diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java index 1a748bd4dc..6a4885aed9 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java @@ -166,8 +166,6 @@ public class TestPlanService { @Resource private ApiDefinitionService apiDefinitionService; @Resource - private IssueTemplateService issueTemplateService; - @Resource private PerformanceReportService performanceReportService; @Resource private MetricQueryService metricQueryService; @@ -1461,37 +1459,9 @@ public class TestPlanService { } report.setScenarioAllCases(scenarioAllCases); } - if (checkReportConfig(config, "api", "failure")) { - // 接口 - List apiFailureCases = null; - if (!CollectionUtils.isEmpty(apiAllCases)) { - apiFailureCases = apiAllCases.stream() - .filter(i -> StringUtils.isNotBlank(i.getExecResult()) - && i.getExecResult().equals("error")) - .collect(Collectors.toList()); - } else { - apiFailureCases = testPlanApiCaseService.getFailureCases(planId); - } - if (saveResponse) { - buildApiResponse(apiFailureCases); - } - report.setApiFailureCases(apiFailureCases); - - // 场景 - List scenarioFailureCases = null; - if (!CollectionUtils.isEmpty(scenarioAllCases)) { - scenarioFailureCases = scenarioAllCases.stream() - .filter(i -> StringUtils.isNotBlank(i.getLastResult()) - && i.getLastResult().equals("Fail")) - .collect(Collectors.toList()); - } else { - scenarioFailureCases = testPlanScenarioCaseService.getFailureCases(planId); - } - if (saveResponse) { - buildScenarioResponse(scenarioFailureCases); - } - report.setScenarioFailureCases(scenarioFailureCases); - } + //筛选符合配置需要的执行结果的用例和场景 + this.screenApiCaseByStatusAndReportConfig(report, apiAllCases, config); + this.screenScenariosByStatusAndReportConfig(report, scenarioAllCases, config); } } @@ -1651,26 +1621,51 @@ public class TestPlanService { report.setScenarioAllCases(scenarioAllCases); } } - if (checkReportConfig(config, "api", "failure")) { - // 接口 - List apiFailureCases = null; - if (!CollectionUtils.isEmpty(apiAllCases)) { - apiFailureCases = apiAllCases.stream() - .filter(i -> StringUtils.isNotBlank(i.getExecResult()) - && i.getExecResult().equals("error")) - .collect(Collectors.toList()); - } - report.setApiFailureCases(apiFailureCases); - // 场景 - List scenarioFailureCases = null; - if (!CollectionUtils.isEmpty(scenarioAllCases)) { - scenarioFailureCases = scenarioAllCases.stream() - .filter(i -> StringUtils.isNotBlank(i.getLastResult()) - && i.getLastResult().equals("Fail")) - .collect(Collectors.toList()); + //筛选符合配置需要的执行结果的用例和场景 + this.screenApiCaseByStatusAndReportConfig(report, apiAllCases, config); + this.screenScenariosByStatusAndReportConfig(report, scenarioAllCases, config); + } + } + + private void screenScenariosByStatusAndReportConfig(TestPlanSimpleReportDTO report, List scenarios, JSONObject reportConfig) { + + if (!CollectionUtils.isEmpty(scenarios)) { + List failureScenarios = new ArrayList<>(); + List errorReportScenarios = new ArrayList<>(); + for (TestPlanFailureScenarioDTO scenario : scenarios) { + if (StringUtils.equalsIgnoreCase(scenario.getLastResult(), "Fail")) { + failureScenarios.add(scenario); + } else if (StringUtils.equalsIgnoreCase(scenario.getLastResult(), ExecuteResult.errorReportResult.name())) { + errorReportScenarios.add(scenario); } - report.setScenarioFailureCases(scenarioFailureCases); + } + if (checkReportConfig(reportConfig, "api", "failure")) { + report.setScenarioFailureCases(failureScenarios); + } + if (checkReportConfig(reportConfig, "api", "errorReport")) { + report.setErrorReportScenarios(errorReportScenarios); + } + } + } + + private void screenApiCaseByStatusAndReportConfig(TestPlanSimpleReportDTO report, List apiAllCases, JSONObject reportConfig) { + if (!CollectionUtils.isEmpty(apiAllCases)) { + List apiFailureCases = new ArrayList<>(); + List apiErrorReportCases = new ArrayList<>(); + for (TestPlanFailureApiDTO apiDTO : apiAllCases) { + if (StringUtils.equalsIgnoreCase(apiDTO.getExecResult(), "error")) { + apiFailureCases.add(apiDTO); + } else if (StringUtils.equalsIgnoreCase(apiDTO.getExecResult(), ExecuteResult.errorReportResult.name())) { + apiErrorReportCases.add(apiDTO); + } + } + + if (checkReportConfig(reportConfig, "api", "failure")) { + report.setApiFailureCases(apiFailureCases); + } + if (checkReportConfig(reportConfig, "api", "errorReport")) { + report.setErrorReportCases(apiErrorReportCases); } } } diff --git a/backend/src/main/resources/db/migration/V106__v1.17_release.sql b/backend/src/main/resources/db/migration/V106__v1.17_release.sql index cb41303d00..aab7b69bb3 100644 --- a/backend/src/main/resources/db/migration/V106__v1.17_release.sql +++ b/backend/src/main/resources/db/migration/V106__v1.17_release.sql @@ -190,3 +190,6 @@ SET ref_id = id; UPDATE test_case INNER JOIN project_version ON project_version.project_id = test_case.project_id SET version_id = project_version.id; + +ALTER TABLE `test_plan_report_content` ADD COLUMN `error_report_cases` LONGTEXT COMMENT '误报状态接口用例'; +ALTER TABLE `test_plan_report_content` ADD COLUMN `error_report_scenarios` LONGTEXT COMMENT '误报状态场景用例'; diff --git a/frontend/src/business/components/api/definition/model/JsonData.js b/frontend/src/business/components/api/definition/model/JsonData.js index 436eb29bc1..230e322c9f 100644 --- a/frontend/src/business/components/api/definition/model/JsonData.js +++ b/frontend/src/business/components/api/definition/model/JsonData.js @@ -118,6 +118,7 @@ export const REQUIRED = [ export const RESULT_MAP = new Map([ ['success', '通过'], ['error', '未通过'], - ['default', '未执行'] + ['default', '未执行'], + ['errorReportResult', '误报'] ]); diff --git a/frontend/src/business/components/track/common/tableItems/planview/StatusTableItem.vue b/frontend/src/business/components/track/common/tableItems/planview/StatusTableItem.vue index 48cf299c8f..893cab2b05 100644 --- a/frontend/src/business/components/track/common/tableItems/planview/StatusTableItem.vue +++ b/frontend/src/business/components/track/common/tableItems/planview/StatusTableItem.vue @@ -9,6 +9,7 @@ + diff --git a/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue b/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue index b57532733a..56ad7ca862 100644 --- a/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue +++ b/frontend/src/business/components/track/plan/view/comonents/api/TestPlanApiScenarioList.vue @@ -142,6 +142,9 @@ {{ $t('api_test.automation.fail') }} + + {{ $t('error_report_library.option.name') }} + - + - + + + + + - + @@ -27,6 +36,7 @@ import TestPlanReportContainer from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContainer"; import ApiCases from "@/business/components/track/plan/view/comonents/report/detail/component/ApiCases"; import TabPaneCount from "@/business/components/track/plan/view/comonents/report/detail/component/TabPaneCount"; + export default { name: "TestPlanApiReport", components: {TabPaneCount, ApiCases, TestPlanReportContainer, ApiResult, MsFormDivider}, @@ -34,6 +44,7 @@ export default { return { activeName: 'first', failureSize: 0, + errorReportSize: 0, allSize: 0, }; }, @@ -49,6 +60,10 @@ export default { let disable = this.report.config && this.report.config.api.children.failure.enable === false; return !disable; }, + errorReportEnable() { + let disable = this.report.config && this.report.config.api.children.errorReport && this.report.config.api.children.errorReport.enable === false; + return !disable; + }, allEnable() { let disable = this.report.config && this.report.config.api.children.all.enable === false; return !disable; @@ -61,6 +76,9 @@ export default { failureEnable() { this.initActiveName(); }, + errorReportEnable() { + this.initActiveName(); + }, allEnable() { this.initActiveName(); }, @@ -74,13 +92,18 @@ export default { this.activeName = 'first'; } else if (this.failureEnable) { this.activeName = 'second'; - } else if (this.allEnable) { + } else if (this.errorReportEnable) { this.activeName = 'third'; + } else if (this.allEnable) { + this.activeName = 'fourth'; } }, setFailureSize(size) { this.failureSize = size; }, + setErrorReportSize(size) { + this.errorReportSize = size; + }, setAllSize(size) { this.allSize = size; }, diff --git a/frontend/src/business/components/track/plan/view/comonents/report/detail/TestPlanReportContent.vue b/frontend/src/business/components/track/plan/view/comonents/report/detail/TestPlanReportContent.vue index 0a9e39ac2a..0ccf8d403e 100644 --- a/frontend/src/business/components/track/plan/view/comonents/report/detail/TestPlanReportContent.vue +++ b/frontend/src/business/components/track/plan/view/comonents/report/detail/TestPlanReportContent.vue @@ -205,6 +205,10 @@ export default { enable: true, name: this.$t('test_track.report.fail_case'), }, + errorReport: { + enable: true, + name: this.$t('error_report_library.option.name'), + }, all: { enable: true, name: this.$t('test_track.report.all_case'), diff --git a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCaseFailureResult.vue b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCaseFailureResult.vue index b0eb23c40a..cca636746a 100644 --- a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCaseFailureResult.vue +++ b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCaseFailureResult.vue @@ -1,62 +1,64 @@ @@ -66,9 +68,9 @@ import TypeTableItem from "../../../../../../common/tableItems/planview/TypeTabl import MethodTableItem from "../../../../../../common/tableItems/planview/MethodTableItem"; import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem"; import { - getPlanApiAllCase, + getPlanApiAllCase, getPlanApiErrorReportCase, getPlanApiFailureCase, - getSharePlanApiAllCase, + getSharePlanApiAllCase, getSharePlanApiErrorReportCase, getSharePlanApiFailureCase } from "@/network/test-plan"; import MsTable from "@/business/components/common/components/table/MsTable"; @@ -77,13 +79,15 @@ import {getApiReport, getShareApiReport} from "@/network/api"; import MsRequestResultTail from "@/business/components/api/definition/components/response/RequestResultTail"; import MsAsideContainer from "@/business/components/common/components/MsAsideContainer"; import MsMainContainer from "@/business/components/common/components/MsMainContainer"; + export default { name: "ApiCaseFailureResult", components: { MsMainContainer, MsAsideContainer, MsRequestResultTail, - MsTableColumn, MsTable, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem}, + MsTableColumn, MsTable, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem + }, props: { planId: String, isTemplate: Boolean, @@ -91,6 +95,7 @@ export default { isShare: Boolean, shareId: String, isAll: Boolean, + isErrorReport: Boolean, isDb: Boolean }, data() { @@ -116,13 +121,19 @@ export default { methods: { getScenarioApiCase() { if (this.isTemplate || this.isDb) { - if (this.isAll) { + if(this.isErrorReport){ + this.apiCases = this.report.errorReportCases ? this.report.errorReportCases : []; + }else if (this.isAll) { this.apiCases = this.report.apiAllCases ? this.report.apiAllCases : []; } else { this.apiCases = this.report.apiFailureCases ? this.report.apiFailureCases : []; } } else if (this.isShare) { - if (this.isAll) { + if(this.isErrorReport){ + this.result = getSharePlanApiErrorReportCase(this.shareId, this.planId, (data) => { + this.apiCases = data; + }); + }else if (this.isAll) { this.result = getSharePlanApiAllCase(this.shareId, this.planId, (data) => { this.apiCases = data; }); @@ -132,7 +143,11 @@ export default { }); } } else { - if (this.isAll) { + if(this.isErrorReport){ + this.result = getPlanApiErrorReportCase(this.planId, (data) => { + this.apiCases = data; + }); + }else if (this.isAll) { this.result = getPlanApiAllCase(this.planId, (data) => { this.apiCases = data; }); diff --git a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCases.vue b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCases.vue index 703351dfe3..e88e5b0ed6 100644 --- a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCases.vue +++ b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiCases.vue @@ -5,15 +5,16 @@ - - + @@ -29,12 +30,14 @@ import ApiScenarioFailureResult import ApiCaseFailureResult from "@/business/components/track/plan/view/comonents/report/detail/component/ApiCaseFailureResult"; import TabPaneCount from "@/business/components/track/plan/view/comonents/report/detail/component/TabPaneCount"; + export default { name: "ApiCases", components: { TabPaneCount, ApiCaseFailureResult, - ApiScenarioFailureResult, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem}, + ApiScenarioFailureResult, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem + }, props: { planId: String, isTemplate: Boolean, @@ -42,6 +45,7 @@ export default { report: {}, shareId: String, isAll: Boolean, + isErrorReport: Boolean, isDb: Boolean }, data() { diff --git a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiResult.vue b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiResult.vue index af12ca537e..bad06bc7e2 100644 --- a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiResult.vue +++ b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiResult.vue @@ -33,6 +33,7 @@ export default { ["Failure", {name: this.$t('test_track.plan_view.failure'), itemStyle: {color: '#F56C6C'}}], ["Prepare", {name: this.$t('api_test.home_page.detail_card.unexecute'), itemStyle: {color: '#909399'}}], ["Underway", {name: this.$t('api_test.home_page.detail_card.unexecute'), itemStyle: {color: '#909399'}}], + ["errorReportResult", {name: this.$t('error_report_library.option.name'), itemStyle: {color: '#F6972A'}}], ]), caseCharData: [], scenarioCharData: [], diff --git a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiScenarioFailureResult.vue b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiScenarioFailureResult.vue index 8e5c903ef3..ad8ec58ca8 100644 --- a/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiScenarioFailureResult.vue +++ b/frontend/src/business/components/track/plan/view/comonents/report/detail/component/ApiScenarioFailureResult.vue @@ -1,64 +1,66 @@