diff --git a/backend/framework/sdk/src/main/resources/i18n/commons.properties b/backend/framework/sdk/src/main/resources/i18n/commons.properties index 7a6e6ae0b2..ba9db2665e 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons.properties @@ -545,3 +545,5 @@ global_request_header=全局请求头 url_format_error=请检查Swagger URL是否输入正确! swagger_version_error=Swagger 版本不支持,请检查是否为3.0版本! + +test_plan=测试计划 ID diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties index 65d418b74d..518e5db159 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties @@ -582,4 +582,6 @@ global_request_header=Global request header url_format_error=Please check if the Swagger URL is entered correctly! -swagger_version_error=Swagger version not supported, please check if it is version 3.0! \ No newline at end of file +swagger_version_error=Swagger version not supported, please check if it is version 3.0! + +test_plan=Test Plan ID \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties index e223030fcc..8a0bc768f9 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties @@ -578,4 +578,5 @@ current_user_can_not_operation_api_key=当前用户无操作该ApiKey的权限 global_request_header=全局请求头 url_format_error=请检查Swagger URL是否输入正确! -swagger_version_error=Swagger 版本不支持,请检查是否为3.0版本! \ No newline at end of file +swagger_version_error=Swagger 版本不支持,请检查是否为3.0版本! +test_plan=测试计划 ID \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties index 646d83eb10..f5a5fb7053 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties @@ -578,4 +578,5 @@ current_user_can_not_operation_api_key=當前用戶無法操作ApiKey global_request_header=全局請求頭 url_format_error=请检查Swagger URL是否输入正确! -swagger_version_error=Swagger 版本不支持,请检查是否为3.0版本! \ No newline at end of file +swagger_version_error=Swagger 版本不支持,请检查是否为3.0版本! +test_plan=測試計劃 ID \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ExecuteReportDTO.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ExecuteReportDTO.java index 654376dba3..9dfe757549 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ExecuteReportDTO.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ExecuteReportDTO.java @@ -26,7 +26,7 @@ public class ExecuteReportDTO implements Serializable { @Schema(description = "报告结果/SUCCESS/ERROR") private String status; - + @Schema(description = "报告状态") private String execStatus; @@ -42,6 +42,12 @@ public class ExecuteReportDTO implements Serializable { @Schema(description = "是否集成") private boolean integrated; + @Schema(description = "测试计划id") + private String testPlanId; + + @Schema(description = "测试计划Num") + private String testPlanNum; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioMapper.xml index 0629b4cdfa..16a785fc54 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioMapper.xml @@ -500,7 +500,9 @@ api_scenario_report.create_user, api_scenario_report.trigger_mode, api_scenario_report.test_plan_scenario_id, - api_scenario_report.deleted + api_scenario_report.deleted, + api_scenario_report.integrated, + api_scenario_report.test_plan_scenario_id as test_plan_id from api_scenario_report left join api_scenario_record t1 on t1.api_scenario_report_id = api_scenario_report.id where 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 bf2bc24750..953c8b98a0 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 @@ -57,4 +57,6 @@ public interface ExtApiScenarioReportMapper { List getHistoryDeleted(@Param("ids") List ids); + + List getTestPlanNum(@Param("ids") List ids); } 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 f6121a9cbf..9270c245f9 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 @@ -254,6 +254,19 @@ + + diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java index 37e167f2e9..b83fa3d8a0 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.java @@ -75,22 +75,26 @@ public interface ExtApiTestCaseMapper { DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam); - List getApiCaseExecuteInfoByIds(@Param("ids")List ids); + List getApiCaseExecuteInfoByIds(@Param("ids") List ids); /** * 获取缺陷未关联的接口用例列表 + * * @param request provider参数 * @param deleted 是否删除状态 - * @param sort 排序 + * @param sort 排序 * @return 通用的列表Case集合 */ List listUnRelatedCaseWithBug(@Param("request") TestCasePageProviderRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort); /** * 根据关联条件获取关联的用例ID + * * @param request 关联参数 * @param deleted 是否删除状态 * @return 关联的用例ID集合 */ - List getSelectIdsByAssociateParam(@Param("request")AssociateOtherCaseRequest request, @Param("deleted") boolean deleted); + List getSelectIdsByAssociateParam(@Param("request") AssociateOtherCaseRequest request, @Param("deleted") boolean deleted); + + List getTestPlanNum(@Param("ids") List ids); } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml index 3543a2e1f0..47ca19ab86 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml @@ -257,7 +257,8 @@ api_report.trigger_mode, api_report.test_plan_case_id, api_report.deleted, - api_report.integrated + api_report.integrated, + api_report.test_plan_case_id as test_plan_id from api_report left join api_test_case_record atc on atc.api_report_id = api_report.id where @@ -390,6 +391,18 @@ ) + diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java index afada81e2a..250692a068 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java @@ -579,12 +579,26 @@ public class ApiTestCaseService extends MoveNodeService implements GetRunScriptS List historyDeletedList = extApiReportMapper.getHistoryDeleted(reportIds); historyDeletedMap = historyDeletedList.stream().collect(Collectors.toMap(ExecuteReportDTO::getId, Function.identity())); } + + Map testPlanIdMap = executeList.stream() + .filter(apiReport -> !StringUtils.equals(apiReport.getTestPlanId(), "NONE")) + .collect(Collectors.toMap(ExecuteReportDTO::getId, ExecuteReportDTO::getTestPlanId)); + List testPlanIds = new ArrayList<>(testPlanIdMap.keySet()); + Map testPlanNumMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(testPlanIds)) { + List testPlanNameLists = extApiTestCaseMapper.getTestPlanNum(testPlanIds); + testPlanNumMap = testPlanNameLists.stream().collect(Collectors.toMap(ExecuteReportDTO::getId, ExecuteReportDTO::getTestPlanNum)); + } Map finalHistoryDeletedMap = historyDeletedMap; + Map finalTestPlanNumMap = testPlanNumMap; executeList.forEach(apiReport -> { apiReport.setOperationUser(userMap.get(apiReport.getCreateUser())); Date date = new Date(apiReport.getStartTime()); apiReport.setNum(sdf.format(date)); apiReport.setHistoryDeleted(MapUtils.isNotEmpty(finalHistoryDeletedMap) && !finalHistoryDeletedMap.containsKey(apiReport.getId())); + if (MapUtils.isNotEmpty(testPlanIdMap) && testPlanIdMap.containsKey(apiReport.getId())) { + apiReport.setTestPlanNum(StringUtils.join(Translator.get("test_plan"), ": ", finalTestPlanNumMap.get(apiReport.getId()))); + } }); return executeList; } @@ -630,7 +644,7 @@ public class ApiTestCaseService extends MoveNodeService implements GetRunScriptS return apiDefinitionExecuteInfo; } }) - .filter(item -> item != null) + .filter(Objects::nonNull) .toList(); } 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 e81d0b64bf..9de0c12a24 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 @@ -2243,16 +2243,29 @@ public class ApiScenarioService extends MoveNodeService { if (CollectionUtils.isNotEmpty(reportIds)) { List historyDeletedList = extApiScenarioReportMapper.getHistoryDeleted(reportIds); historyDeletedMap = historyDeletedList.stream().collect(Collectors.toMap(ExecuteReportDTO::getId, Function.identity())); - } + Map testPlanIdMap = executeList.stream() + .filter(apiReport -> !StringUtils.equals(apiReport.getTestPlanId(), "NONE")) + .collect(Collectors.toMap(ExecuteReportDTO::getId, ExecuteReportDTO::getTestPlanId)); + List testPlanIds = new ArrayList<>(testPlanIdMap.keySet()); + Map testPlanNumMap = new HashMap<>(); + if (org.apache.commons.collections.CollectionUtils.isNotEmpty(testPlanIds)) { + List testPlanNameLists = extApiScenarioReportMapper.getTestPlanNum(testPlanIds); + testPlanNumMap = testPlanNameLists.stream().collect(Collectors.toMap(ExecuteReportDTO::getId, ExecuteReportDTO::getTestPlanNum)); + } + Map userMap = userLoginService.getUserNameMap(new ArrayList<>(userSet)); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); Map finalHistoryDeletedMap = historyDeletedMap; + Map finalTestPlanNumMap = testPlanNumMap; executeList.forEach(apiReport -> { apiReport.setOperationUser(userMap.get(apiReport.getCreateUser())); Date date = new Date(apiReport.getStartTime()); apiReport.setNum(sdf.format(date)); apiReport.setHistoryDeleted(MapUtils.isNotEmpty(finalHistoryDeletedMap) && !finalHistoryDeletedMap.containsKey(apiReport.getId())); + if (MapUtils.isNotEmpty(testPlanIdMap) && testPlanIdMap.containsKey(apiReport.getId())) { + apiReport.setTestPlanNum(StringUtils.join(Translator.get("test_plan"), ": ", finalTestPlanNumMap.get(apiReport.getId()))); + } }); return executeList; } 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 4123c04363..179dc8c460 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 @@ -26,6 +26,10 @@ import io.metersphere.api.service.definition.ApiTestCaseService; import io.metersphere.api.service.scenario.ApiScenarioReportService; import io.metersphere.api.service.scenario.ApiScenarioService; import io.metersphere.api.utils.ApiDataUtils; +import io.metersphere.plan.domain.TestPlanApiScenario; +import io.metersphere.plan.domain.TestPlanExample; +import io.metersphere.plan.mapper.TestPlanApiScenarioMapper; +import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.project.api.assertion.MsResponseCodeAssertion; import io.metersphere.project.api.assertion.MsScriptAssertion; @@ -179,6 +183,10 @@ public class ApiScenarioControllerTests extends BaseTest { private ApiScenarioReportService scenarioReportService; @Resource private ApiScenarioCsvStepMapper apiScenarioCsvStepMapper; + @Resource + private TestPlanMapper testPlanMapper; + @Resource + private TestPlanApiScenarioMapper testPlanApiScenarioMapper; private static String fileMetadataId; private static String fileMetadataStepId; @@ -2643,6 +2651,20 @@ public class ApiScenarioControllerTests extends BaseTest { ApiScenario first = apiScenarioMapper.selectByExample(new ApiScenarioExample()).getFirst(); List reports = new ArrayList<>(); List records = new ArrayList<>(); + + String planId = testPlanMapper.selectByExample(new TestPlanExample()).getFirst().getId(); + TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario(); + testPlanApiScenario.setTestPlanId(first.getId()); + testPlanApiScenario.setId(IDGenerator.nextStr()); + testPlanApiScenario.setApiScenarioId(first.getId()); + testPlanApiScenario.setCreateUser("admin"); + testPlanApiScenario.setCreateTime(System.currentTimeMillis()); + testPlanApiScenario.setLastExecTime(System.currentTimeMillis()); + testPlanApiScenario.setLastExecReportId(IDGenerator.nextStr()); + testPlanApiScenario.setLastExecResult(ExecStatus.SUCCESS.name()); + testPlanApiScenario.setPos(1024l); + testPlanApiScenario.setTestPlanCollectionId(planId); + testPlanApiScenarioMapper.insert(testPlanApiScenario); for (int i = 0; i < 10; i++) { ApiScenarioReport apiReport = new ApiScenarioReport(); apiReport.setId(IDGenerator.nextStr()); @@ -2658,6 +2680,7 @@ public class ApiScenarioControllerTests extends BaseTest { if (i % 2 == 0) { apiReport.setStatus(ReportStatus.SUCCESS.name()); } else { + apiReport.setTestPlanScenarioId(testPlanApiScenario.getId()); apiReport.setStatus(ReportStatus.ERROR.name()); } apiReport.setTriggerMode("api-trigger-mode" + i); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java index a742000bea..fe13941461 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java @@ -18,6 +18,10 @@ import io.metersphere.api.service.BaseFileManagementTestService; import io.metersphere.api.service.definition.ApiReportService; import io.metersphere.api.service.definition.ApiTestCaseService; import io.metersphere.api.utils.ApiDataUtils; +import io.metersphere.plan.domain.TestPlanApiCase; +import io.metersphere.plan.domain.TestPlanExample; +import io.metersphere.plan.mapper.TestPlanApiCaseMapper; +import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plugin.api.spi.AbstractMsTestElement; import io.metersphere.project.domain.ProjectVersion; import io.metersphere.project.dto.environment.EnvironmentConfig; @@ -151,6 +155,10 @@ public class ApiTestCaseControllerTests extends BaseTest { private ApiScenarioMapper apiScenarioMapper; @Resource private ApiScenarioStepMapper apiScenarioStepMapper; + @Resource + private TestPlanMapper testPlanMapper; + @Resource + private TestPlanApiCaseMapper testPlanApiCaseMapper; @Override public String getBasePath() { @@ -770,6 +778,21 @@ public class ApiTestCaseControllerTests extends BaseTest { ApiTestCase first = apiTestCaseMapper.selectByExample(new ApiTestCaseExample()).getFirst(); List reports = new ArrayList<>(); List records = new ArrayList<>(); + + String planId = testPlanMapper.selectByExample(new TestPlanExample()).getFirst().getId(); + TestPlanApiCase testPlanApiCase = new TestPlanApiCase(); + testPlanApiCase.setTestPlanId(first.getId()); + testPlanApiCase.setId(IDGenerator.nextStr()); + testPlanApiCase.setApiCaseId(first.getId()); + testPlanApiCase.setCreateUser("admin"); + testPlanApiCase.setCreateTime(System.currentTimeMillis()); + testPlanApiCase.setLastExecTime(System.currentTimeMillis()); + testPlanApiCase.setLastExecReportId(IDGenerator.nextStr()); + testPlanApiCase.setLastExecResult(ExecStatus.SUCCESS.name()); + testPlanApiCase.setPos(1024l); + testPlanApiCase.setTestPlanCollectionId(planId); + testPlanApiCaseMapper.insert(testPlanApiCase); + for (int i = 0; i < 10; i++) { ApiReport apiReport = new ApiReport(); apiReport.setId(IDGenerator.nextStr()); @@ -785,6 +808,7 @@ public class ApiTestCaseControllerTests extends BaseTest { if (i % 2 == 0) { apiReport.setStatus(ExecStatus.SUCCESS.name()); } else { + apiReport.setTestPlanCaseId(testPlanApiCase.getId()); apiReport.setStatus(ExecStatus.ERROR.name()); } apiReport.setTriggerMode("api-trigger-mode" + i); diff --git a/frontend/src/views/api-test/management/components/management/case/tabContent/tabCaseExecuteHistory.vue b/frontend/src/views/api-test/management/components/management/case/tabContent/tabCaseExecuteHistory.vue index 72ce3d8804..62688de1ab 100644 --- a/frontend/src/views/api-test/management/components/management/case/tabContent/tabCaseExecuteHistory.vue +++ b/frontend/src/views/api-test/management/components/management/case/tabContent/tabCaseExecuteHistory.vue @@ -12,6 +12,23 @@ />--> + @@ -65,6 +82,7 @@ import MsBaseTable from '@/components/pure/ms-table/base-table.vue'; import { MsTableColumn } from '@/components/pure/ms-table/type'; import useTable from '@/components/pure/ms-table/useTable'; + import MsTag from '@/components/pure/ms-tag/ms-tag.vue'; import caseAndScenarioReportDrawer from '@/views/api-test/components/caseAndScenarioReportDrawer.vue'; import ExecStatus from '@/views/api-test/report/component/execStatus.vue'; import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue'; @@ -117,7 +135,7 @@ dataIndex: 'num', slotName: 'num', sortIndex: 1, - width: 150, + width: 280, }, { title: 'apiTestManagement.executeMethod', @@ -222,6 +240,8 @@ showResponse.value = true; } + const color = 'rgb(var(--primary-7))'; + onBeforeMount(() => { loadExecuteList(); }); @@ -237,6 +257,7 @@ .ms-scroll-bar(); } + .history-table-before { display: flex; justify-content: space-between; diff --git a/frontend/src/views/api-test/scenario/components/executeHistory.vue b/frontend/src/views/api-test/scenario/components/executeHistory.vue index 88bbf0072a..a98012503d 100644 --- a/frontend/src/views/api-test/scenario/components/executeHistory.vue +++ b/frontend/src/views/api-test/scenario/components/executeHistory.vue @@ -2,7 +2,21 @@