From 6657ad923f0dc0952f3751ab6716eadfd5292230 Mon Sep 17 00:00:00 2001 From: Jianguo-Genius Date: Thu, 7 Nov 2024 16:28:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=88=97=E8=A1=A8=E6=80=BB=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=8E=87=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001048522 --- .../metersphere/sdk/util/CalculateUtils.java | 22 +++++++++++++++ .../scenario/ApiScenarioController.java | 10 +++++++ .../metersphere/api/dto/ApiExecResultDTO.java | 11 ++++++++ .../api/dto/scenario/ApiScenarioDTO.java | 2 ++ .../mapper/ExtApiScenarioReportMapper.java | 3 ++ .../api/mapper/ExtApiScenarioReportMapper.xml | 9 ++++++ .../service/scenario/ApiScenarioService.java | 28 +++++++++++++++++++ .../ApiScenarioControllerTests.java | 6 ++++ .../ApiScenarioReportControllerTests.java | 12 +++++++- 9 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 backend/framework/sdk/src/main/java/io/metersphere/sdk/util/CalculateUtils.java create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiExecResultDTO.java diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/CalculateUtils.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/CalculateUtils.java new file mode 100644 index 0000000000..429ec0b0cc --- /dev/null +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/CalculateUtils.java @@ -0,0 +1,22 @@ +package io.metersphere.sdk.util; + +import java.text.DecimalFormat; + +public class CalculateUtils { + + // 报告所需的百分比计算 + public static String reportPercentage(int numerator, int denominator) { + DecimalFormat rateFormat = new DecimalFormat("#0.00"); + rateFormat.setMinimumFractionDigits(2); + rateFormat.setMaximumFractionDigits(2); + + double passRate = Double.parseDouble(rateFormat.format((double) numerator * 100 / (double) denominator)); + if (passRate == 100 && numerator < denominator) { + return "99.99%"; + } else if (passRate == 0 && numerator > 0) { + return "0.01%"; + } else { + return passRate + "%"; + } + } +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/scenario/ApiScenarioController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/scenario/ApiScenarioController.java index ef90d25f79..a19acf7433 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/scenario/ApiScenarioController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/scenario/ApiScenarioController.java @@ -35,6 +35,8 @@ import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.SessionUtils; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; @@ -74,6 +76,14 @@ public class ApiScenarioController { return PageUtils.setPageInfo(page, apiScenarioService.getScenarioPage(request, true, null)); } + @PostMapping("/statistics") + @Operation(summary = "接口测试-接口场景管理-获取通过率") + @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ) + @Parameter(name = "ids", description = "场景id集合", schema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED)) + public List selectTestPlanMetricById(@RequestBody List ids) { + return apiScenarioService.calculateRate(ids); + } + @PostMapping("/trash/page") @Operation(summary = "接口测试-接口场景管理-场景列表(deleted 状态为 1 时为回收站数据)") @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ) diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiExecResultDTO.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiExecResultDTO.java new file mode 100644 index 0000000000..d19ed45454 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/ApiExecResultDTO.java @@ -0,0 +1,11 @@ +package io.metersphere.api.dto; + +import lombok.Data; + +@Data +public class ApiExecResultDTO { + // 接口定义、接口用例、场景等的id + private String resourceId; + + private String execResult; +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDTO.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDTO.java index 40a0ef8568..c0e8ce4bd5 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDTO.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioDTO.java @@ -28,4 +28,6 @@ public class ApiScenarioDTO extends ApiScenario { private Long nextTriggerTime; @Schema(description = "脚本错误标识") private String scriptIdentifier; + @Schema(description = "执行通过率", requiredMode = Schema.RequiredMode.REQUIRED) + private String execPassRate = "0%"; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.java b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.java index 92d3a3b889..06436bfa90 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.java @@ -2,6 +2,7 @@ package io.metersphere.api.mapper; import io.metersphere.api.domain.ApiScenarioBlob; import io.metersphere.api.domain.ApiScenarioReport; +import io.metersphere.api.dto.ApiExecResultDTO; import io.metersphere.api.dto.definition.ApiReportBatchRequest; import io.metersphere.api.dto.definition.ApiReportPageRequest; import io.metersphere.api.dto.definition.ExecuteReportDTO; @@ -62,4 +63,6 @@ public interface ExtApiScenarioReportMapper { List getHistoryDeleted(@Param("ids") List ids); List getTestPlanNum(@Param("ids") List ids); + + List selectExecResultByScenarioIds(@Param("ids") List scenarioIds); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml index 2e33cc97f5..0821b1b0f2 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml @@ -273,6 +273,15 @@ + diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java index 508a7133dc..2ffb595ddf 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java @@ -2619,4 +2619,32 @@ public class ApiScenarioService extends MoveNodeService { } } } + + // 场景统计相关 + public List calculateRate(List ids) { + List result = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(ids)) { + List scenarioExecResult = extApiScenarioReportMapper.selectExecResultByScenarioIds(ids); + Map> scenarioReportMap = scenarioExecResult.stream().collect(Collectors.groupingBy(ApiExecResultDTO::getResourceId)); + + for (String scenarioId : ids) { + ApiScenarioDTO dto = new ApiScenarioDTO(); + dto.setId(scenarioId); + + List execResultDTOs = scenarioReportMap.get(scenarioId); + if (CollectionUtils.isNotEmpty(execResultDTOs)) { + int all = execResultDTOs.size(); + int passCount = 0; + for (ApiExecResultDTO execResultDTO : execResultDTOs) { + if (StringUtils.equals(execResultDTO.getExecResult(), ResultStatus.SUCCESS.name())) { + passCount++; + } + } + dto.setExecPassRate(CalculateUtils.reportPercentage(passCount, all)); + } + result.add(dto); + } + } + return result; + } } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java index 7f3c09fbfd..d1bba1a4e4 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java @@ -100,6 +100,8 @@ public class ApiScenarioControllerTests extends BaseTest { private static final String BASE_PATH = "/api/scenario/"; private static final String TRASH_PAGE = "trash/page"; private static final String BATCH_EDIT = "batch-operation/edit"; + private static final String STATISTICS = "/statistics"; + private static final String FOLLOW = "follow/"; protected static final String UPLOAD_TEMP_FILE = "upload/temp/file"; protected static final String DELETE_TO_GC = "delete-to-gc/{0}"; @@ -1458,6 +1460,10 @@ public class ApiScenarioControllerTests extends BaseTest { //返回的数据量不超过规定要返回的数据量相同 Assertions.assertTrue(((List) returnPager.getList()).size() <= pageRequest.getPageSize()); + // 查统计数据 + List apiScenarioIds = Collections.singletonList("api-scenario-id1"); + requestPostWithOk(STATISTICS, apiScenarioIds); + //查询api-scenario-id1的数据 pageRequest.setScenarioId("api-scenario-id1"); mvcResult = requestPostAndReturn(DEFAULT_PAGE, pageRequest); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java index e9e13383f0..0c41ffa791 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java @@ -29,6 +29,7 @@ import io.metersphere.sdk.domain.ShareInfo; import io.metersphere.sdk.mapper.EnvironmentGroupMapper; import io.metersphere.sdk.mapper.EnvironmentMapper; import io.metersphere.sdk.mapper.ShareInfoMapper; +import io.metersphere.sdk.util.CalculateUtils; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; @@ -50,6 +51,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -97,7 +99,7 @@ public class ApiScenarioReportControllerTests extends BaseTest { @Test @Order(1) - public void testInsert() { + public void testInsert() throws Exception { List reports = new ArrayList<>(); List records = new ArrayList<>(); for (int i = 0; i < 2515; i++) { @@ -192,6 +194,14 @@ public class ApiScenarioReportControllerTests extends BaseTest { //校验权限 requestPostPermissionTest(PermissionConstants.PROJECT_API_REPORT_READ, PAGE, request); + + // 顺便查找一下通过率 + // 查统计数据 + List apiScenarioIds = Collections.singletonList("scenario-record-id0"); + requestPostWithOk("/api/scenario/statistics", apiScenarioIds); + Assertions.assertEquals(CalculateUtils.reportPercentage(1, 999999999), "0.01%"); + Assertions.assertEquals(CalculateUtils.reportPercentage(999999998, 999999999), "99.99%"); + Assertions.assertNotEquals(CalculateUtils.reportPercentage(499999998, 999999999), "100%"); } @Override