From b254e3a0a34a697e89b4c7cdfc366619c8afd74f Mon Sep 17 00:00:00 2001 From: WangXu10 Date: Mon, 13 May 2024 20:48:21 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92):=20?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/TestPlanCaseExecuteHistory.java | 10 +-- .../TestPlanCaseExecuteHistoryExample.java | 56 ++++++------- .../TestPlanCaseExecuteHistoryMapper.xml | 40 +++++----- .../3.0.0/ddl/V3.0.0_12__beta_ddl.sql | 6 +- .../resources/i18n/commons_en_US.properties | 1 + .../resources/i18n/commons_zh_CN.properties | 1 + .../resources/i18n/commons_zh_TW.properties | 1 + .../constants/CaseFileSourceType.java | 3 +- .../mapper/ExtFunctionalCaseTestMapper.xml | 6 +- .../FunctionalTestCaseControllerTests.java | 4 +- .../TestPlanFunctionalCaseController.java | 14 +++- .../dto/request/TestPlanCaseRunRequest.java | 47 +++++++++++ .../TestPlanFunctionalCaseService.java | 78 +++++++++++++++++-- .../service/TestPlanSendNoticeService.java | 74 ++++++++++++++++++ .../TestPlanCaseControllerTests.java | 24 +++++- 15 files changed, 288 insertions(+), 77 deletions(-) create mode 100644 backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCaseRunRequest.java create mode 100644 backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanSendNoticeService.java diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistory.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistory.java index e519b2ed8f..e4179f3925 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistory.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistory.java @@ -15,10 +15,10 @@ public class TestPlanCaseExecuteHistory implements Serializable { @Size(min = 1, max = 50, message = "{test_plan_case_execute_history.id.length_range}", groups = {Created.class, Updated.class}) private String id; - @Schema(description = "测试计划ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_case_execute_history.test_plan_id.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 50, message = "{test_plan_case_execute_history.test_plan_id.length_range}", groups = {Created.class, Updated.class}) - private String testPlanId; + @Schema(description = "计划关联用例表ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan_case_execute_history.test_plan_case_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{test_plan_case_execute_history.test_plan_case_id.length_range}", groups = {Created.class, Updated.class}) + private String testPlanCaseId; @Schema(description = "用例ID", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan_case_execute_history.case_id.not_blank}", groups = {Created.class}) @@ -53,7 +53,7 @@ public class TestPlanCaseExecuteHistory implements Serializable { public enum Column { id("id", "id", "VARCHAR", false), - testPlanId("test_plan_id", "testPlanId", "VARCHAR", false), + testPlanCaseId("test_plan_case_id", "testPlanCaseId", "VARCHAR", false), caseId("case_id", "caseId", "VARCHAR", false), status("status", "status", "VARCHAR", true), deleted("deleted", "deleted", "BIT", false), diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistoryExample.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistoryExample.java index 2ea7b16a86..977e285536 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistoryExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanCaseExecuteHistoryExample.java @@ -174,73 +174,73 @@ public class TestPlanCaseExecuteHistoryExample { return (Criteria) this; } - public Criteria andTestPlanIdIsNull() { - addCriterion("test_plan_id is null"); + public Criteria andTestPlanCaseIdIsNull() { + addCriterion("test_plan_case_id is null"); return (Criteria) this; } - public Criteria andTestPlanIdIsNotNull() { - addCriterion("test_plan_id is not null"); + public Criteria andTestPlanCaseIdIsNotNull() { + addCriterion("test_plan_case_id is not null"); return (Criteria) this; } - public Criteria andTestPlanIdEqualTo(String value) { - addCriterion("test_plan_id =", value, "testPlanId"); + public Criteria andTestPlanCaseIdEqualTo(String value) { + addCriterion("test_plan_case_id =", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdNotEqualTo(String value) { - addCriterion("test_plan_id <>", value, "testPlanId"); + public Criteria andTestPlanCaseIdNotEqualTo(String value) { + addCriterion("test_plan_case_id <>", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdGreaterThan(String value) { - addCriterion("test_plan_id >", value, "testPlanId"); + public Criteria andTestPlanCaseIdGreaterThan(String value) { + addCriterion("test_plan_case_id >", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdGreaterThanOrEqualTo(String value) { - addCriterion("test_plan_id >=", value, "testPlanId"); + public Criteria andTestPlanCaseIdGreaterThanOrEqualTo(String value) { + addCriterion("test_plan_case_id >=", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdLessThan(String value) { - addCriterion("test_plan_id <", value, "testPlanId"); + public Criteria andTestPlanCaseIdLessThan(String value) { + addCriterion("test_plan_case_id <", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdLessThanOrEqualTo(String value) { - addCriterion("test_plan_id <=", value, "testPlanId"); + public Criteria andTestPlanCaseIdLessThanOrEqualTo(String value) { + addCriterion("test_plan_case_id <=", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdLike(String value) { - addCriterion("test_plan_id like", value, "testPlanId"); + public Criteria andTestPlanCaseIdLike(String value) { + addCriterion("test_plan_case_id like", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdNotLike(String value) { - addCriterion("test_plan_id not like", value, "testPlanId"); + public Criteria andTestPlanCaseIdNotLike(String value) { + addCriterion("test_plan_case_id not like", value, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdIn(List values) { - addCriterion("test_plan_id in", values, "testPlanId"); + public Criteria andTestPlanCaseIdIn(List values) { + addCriterion("test_plan_case_id in", values, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdNotIn(List values) { - addCriterion("test_plan_id not in", values, "testPlanId"); + public Criteria andTestPlanCaseIdNotIn(List values) { + addCriterion("test_plan_case_id not in", values, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdBetween(String value1, String value2) { - addCriterion("test_plan_id between", value1, value2, "testPlanId"); + public Criteria andTestPlanCaseIdBetween(String value1, String value2) { + addCriterion("test_plan_case_id between", value1, value2, "testPlanCaseId"); return (Criteria) this; } - public Criteria andTestPlanIdNotBetween(String value1, String value2) { - addCriterion("test_plan_id not between", value1, value2, "testPlanId"); + public Criteria andTestPlanCaseIdNotBetween(String value1, String value2) { + addCriterion("test_plan_case_id not between", value1, value2, "testPlanCaseId"); return (Criteria) this; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanCaseExecuteHistoryMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanCaseExecuteHistoryMapper.xml index f6e7e5387f..18104c10e6 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanCaseExecuteHistoryMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanCaseExecuteHistoryMapper.xml @@ -3,7 +3,7 @@ - + @@ -74,7 +74,7 @@ - id, test_plan_id, case_id, `status`, deleted, notifier, create_user, create_time + id, test_plan_case_id, case_id, `status`, deleted, notifier, create_user, create_time content, steps @@ -128,11 +128,11 @@ - insert into test_plan_case_execute_history (id, test_plan_id, case_id, + insert into test_plan_case_execute_history (id, test_plan_case_id, case_id, `status`, deleted, notifier, create_user, create_time, content, steps) - values (#{id,jdbcType=VARCHAR}, #{testPlanId,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, + values (#{id,jdbcType=VARCHAR}, #{testPlanCaseId,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{deleted,jdbcType=BIT}, #{notifier,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY}, #{steps,jdbcType=LONGVARBINARY}) @@ -143,8 +143,8 @@ id, - - test_plan_id, + + test_plan_case_id, case_id, @@ -175,8 +175,8 @@ #{id,jdbcType=VARCHAR}, - - #{testPlanId,jdbcType=VARCHAR}, + + #{testPlanCaseId,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, @@ -216,8 +216,8 @@ id = #{record.id,jdbcType=VARCHAR}, - - test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, + + test_plan_case_id = #{record.testPlanCaseId,jdbcType=VARCHAR}, case_id = #{record.caseId,jdbcType=VARCHAR}, @@ -251,7 +251,7 @@ update test_plan_case_execute_history set id = #{record.id,jdbcType=VARCHAR}, - test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, + test_plan_case_id = #{record.testPlanCaseId,jdbcType=VARCHAR}, case_id = #{record.caseId,jdbcType=VARCHAR}, `status` = #{record.status,jdbcType=VARCHAR}, deleted = #{record.deleted,jdbcType=BIT}, @@ -267,7 +267,7 @@ update test_plan_case_execute_history set id = #{record.id,jdbcType=VARCHAR}, - test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, + test_plan_case_id = #{record.testPlanCaseId,jdbcType=VARCHAR}, case_id = #{record.caseId,jdbcType=VARCHAR}, `status` = #{record.status,jdbcType=VARCHAR}, deleted = #{record.deleted,jdbcType=BIT}, @@ -281,8 +281,8 @@ update test_plan_case_execute_history - - test_plan_id = #{testPlanId,jdbcType=VARCHAR}, + + test_plan_case_id = #{testPlanCaseId,jdbcType=VARCHAR}, case_id = #{caseId,jdbcType=VARCHAR}, @@ -313,7 +313,7 @@ update test_plan_case_execute_history - set test_plan_id = #{testPlanId,jdbcType=VARCHAR}, + set test_plan_case_id = #{testPlanCaseId,jdbcType=VARCHAR}, case_id = #{caseId,jdbcType=VARCHAR}, `status` = #{status,jdbcType=VARCHAR}, deleted = #{deleted,jdbcType=BIT}, @@ -326,7 +326,7 @@ update test_plan_case_execute_history - set test_plan_id = #{testPlanId,jdbcType=VARCHAR}, + set test_plan_case_id = #{testPlanCaseId,jdbcType=VARCHAR}, case_id = #{caseId,jdbcType=VARCHAR}, `status` = #{status,jdbcType=VARCHAR}, deleted = #{deleted,jdbcType=BIT}, @@ -337,11 +337,11 @@ insert into test_plan_case_execute_history - (id, test_plan_id, case_id, `status`, deleted, notifier, create_user, create_time, + (id, test_plan_case_id, case_id, `status`, deleted, notifier, create_user, create_time, content, steps) values - (#{item.id,jdbcType=VARCHAR}, #{item.testPlanId,jdbcType=VARCHAR}, #{item.caseId,jdbcType=VARCHAR}, + (#{item.id,jdbcType=VARCHAR}, #{item.testPlanCaseId,jdbcType=VARCHAR}, #{item.caseId,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.deleted,jdbcType=BIT}, #{item.notifier,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY}, #{item.steps,jdbcType=LONGVARBINARY}) @@ -360,8 +360,8 @@ #{item.id,jdbcType=VARCHAR} - - #{item.testPlanId,jdbcType=VARCHAR} + + #{item.testPlanCaseId,jdbcType=VARCHAR} #{item.caseId,jdbcType=VARCHAR} diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql index ee55e63d19..46e86d4261 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_12__beta_ddl.sql @@ -44,7 +44,7 @@ ALTER TABLE test_plan_functional_case DROP COLUMN num; CREATE TABLE IF NOT EXISTS test_plan_case_execute_history( `id` VARCHAR(50) NOT NULL COMMENT 'ID' , - `test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID' , + `test_plan_case_id` VARCHAR(50) NOT NULL COMMENT '计划关联用例表ID' , `case_id` VARCHAR(50) NOT NULL COMMENT '用例ID' , `status` VARCHAR(64) NOT NULL COMMENT '执行结果:成功/失败/阻塞' , `content` LONGBLOB COMMENT '执行评论意见' , @@ -59,9 +59,7 @@ CREATE TABLE IF NOT EXISTS test_plan_case_execute_history( COLLATE = utf8mb4_general_ci COMMENT = '功能用例执行历史表'; -CREATE INDEX idx_case_id ON test_plan_case_execute_history(case_id); -CREATE INDEX idx_test_plan_id ON test_plan_case_execute_history(test_plan_id); -CREATE INDEX idx_test_plan_id_case_id ON test_plan_case_execute_history(test_plan_id,case_id); +CREATE INDEX idx_test_plan_case_id ON test_plan_case_execute_history(test_plan_case_id); CREATE INDEX idx_status ON test_plan_case_execute_history(status); CREATE INDEX idx_deleted ON test_plan_case_execute_history(deleted); 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 f7e10f9cb1..29d8d382eb 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 @@ -451,6 +451,7 @@ recover=Recover copy=Copy move=Move archive=Archive +run=Run project_is_not_exist=Project is not exist #permission 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 cd5389d865..9204ab1178 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 @@ -450,6 +450,7 @@ recover=恢复 copy=复制 move=移动 archive=归档 +run=执行 project_is_not_exist=项目不存在 #permission 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 9547d4427d..989ccad0b5 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 @@ -448,6 +448,7 @@ recover=恢復 copy=複製 move=移動 archive=歸檔 +run=執行 project_is_not_exist=項目不存在 #permission diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/constants/CaseFileSourceType.java b/backend/services/case-management/src/main/java/io/metersphere/functional/constants/CaseFileSourceType.java index 9a7d8ea440..e0b9561559 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/constants/CaseFileSourceType.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/constants/CaseFileSourceType.java @@ -4,5 +4,6 @@ public enum CaseFileSourceType { ATTACHMENT,//附件 CASE_DETAIL,//功能用例详情 CASE_COMMENT,//用例评论 - REVIEW_COMMENT//评审评论 + REVIEW_COMMENT,//评审评论 + PLAN_COMMENT//计划评论 } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml index 2b17c90932..e3f972bd4d 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml @@ -79,7 +79,7 @@ diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java index 1785d34960..2c9852b06a 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java @@ -567,7 +567,7 @@ public class FunctionalTestCaseControllerTests extends BaseTest { @Order(13) public void testPlanExecuteHistoryList() throws Exception { TestPlanCaseExecuteHistory testPlanCaseExecuteHistory = new TestPlanCaseExecuteHistory(); - testPlanCaseExecuteHistory.setTestPlanId("test_plan_associate_case_gyq_two"); + testPlanCaseExecuteHistory.setTestPlanCaseId("test_plan_associate_case_gyq_two"); testPlanCaseExecuteHistory.setCaseId("gyq_associate_function_case"); testPlanCaseExecuteHistory.setCreateUser("admin"); testPlanCaseExecuteHistory.setStatus(FunctionalCaseReviewStatus.RE_REVIEWED.toString()); @@ -579,7 +579,7 @@ public class FunctionalTestCaseControllerTests extends BaseTest { List gyqReviewCaseTest = getPlanExecuteHistoryList("gyq_associate_function_case"); Assertions.assertTrue(StringUtils.isNotBlank(gyqReviewCaseTest.get(0).getContentText())); testPlanCaseExecuteHistory = new TestPlanCaseExecuteHistory(); - testPlanCaseExecuteHistory.setTestPlanId("test_plan_associate_case_gyq_two"); + testPlanCaseExecuteHistory.setTestPlanCaseId("test_plan_associate_case_gyq_two"); testPlanCaseExecuteHistory.setCaseId("gyq_associate_function_case"); testPlanCaseExecuteHistory.setCreateUser("admin"); testPlanCaseExecuteHistory.setStatus(FunctionalCaseReviewStatus.RE_REVIEWED.toString()); diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java index 75c2734632..fd29997dae 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java @@ -4,10 +4,7 @@ import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.metersphere.dto.BugProviderDTO; import io.metersphere.plan.constants.TestPlanResourceConfig; -import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest; -import io.metersphere.plan.dto.request.ResourceSortRequest; -import io.metersphere.plan.dto.request.TestPlanCaseAssociateBugRequest; -import io.metersphere.plan.dto.request.TestPlanCaseRequest; +import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanCasePageResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; @@ -113,4 +110,13 @@ public class TestPlanFunctionalCaseController { public void disassociateBug(@PathVariable String id) { testPlanFunctionalCaseService.disassociateBug(id); } + + @PostMapping("/run") + @Operation(summary = "测试计划-计划详情-功能用例-执行") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) + @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") + public void run(@Validated @RequestBody TestPlanCaseRunRequest request) { + testPlanFunctionalCaseService.run(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/run", HttpMethodConstants.POST.name())); + } + } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCaseRunRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCaseRunRequest.java new file mode 100644 index 0000000000..51d4737735 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCaseRunRequest.java @@ -0,0 +1,47 @@ +package io.metersphere.plan.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.util.List; + +/** + * @author wx + */ +@Data +public class TestPlanCaseRunRequest { + + @Schema(description = "项目Id") + @NotBlank(message = "{test_plan.project_id.not_blank}") + private String projectId; + + @Schema(description = "id") + @NotBlank(message = "{id.not_blank}") + private String id; + + @Schema(description = "测试计划id") + @NotBlank(message = "{test_plan_id.not_blank}") + private String testPlanId; + + @Schema(description = "用例id") + @NotBlank(message = "{case_id.not_blank}") + private String caseId; + + @Schema(description = "最终执行结果") + @NotBlank(message = "{test_plan.last_exec_result.not_blank}") + private String lastExecResult; + + @Schema(description = "步骤执行结果") + private String stepsExecResult; + + @Schema(description = "执行内容") + private String content; + + @Schema(description = "评论@的人的Id, 多个以';'隔开") + private String notifier; + + @Schema(description = "测试计划执行评论副文本的文件id集合") + private List planCommentFileIds; + +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java index 18e5e9c11b..849e4f2c9f 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java @@ -7,35 +7,33 @@ import io.metersphere.bug.mapper.BugMapper; import io.metersphere.bug.mapper.BugRelationCaseMapper; import io.metersphere.bug.mapper.ExtBugRelateCaseMapper; import io.metersphere.dto.BugProviderDTO; +import io.metersphere.functional.constants.CaseFileSourceType; import io.metersphere.functional.domain.FunctionalCaseModule; import io.metersphere.functional.dto.FunctionalCaseCustomFieldDTO; import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO; import io.metersphere.functional.dto.FunctionalCaseModuleDTO; import io.metersphere.functional.dto.ProjectOptionDTO; +import io.metersphere.functional.service.FunctionalCaseAttachmentService; import io.metersphere.functional.service.FunctionalCaseModuleService; import io.metersphere.functional.service.FunctionalCaseService; import io.metersphere.plan.domain.TestPlan; +import io.metersphere.plan.domain.TestPlanCaseExecuteHistory; import io.metersphere.plan.domain.TestPlanFunctionalCase; import io.metersphere.plan.domain.TestPlanFunctionalCaseExample; import io.metersphere.plan.dto.AssociationNodeSortDTO; import io.metersphere.plan.dto.ResourceLogInsertModule; import io.metersphere.plan.dto.TestPlanResourceAssociationParam; -import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest; -import io.metersphere.plan.dto.request.ResourceSortRequest; -import io.metersphere.plan.dto.request.TestPlanCaseAssociateBugRequest; -import io.metersphere.plan.dto.request.TestPlanCaseRequest; +import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanCasePageResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; -import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper; -import io.metersphere.plan.mapper.ExtTestPlanModuleMapper; -import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper; -import io.metersphere.plan.mapper.TestPlanMapper; +import io.metersphere.plan.mapper.*; import io.metersphere.project.domain.Project; import io.metersphere.project.dto.ModuleCountDTO; import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.request.BugPageProviderRequest; import io.metersphere.sdk.constants.CaseType; +import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.TestPlanResourceConstants; import io.metersphere.sdk.exception.MSException; @@ -49,11 +47,13 @@ import io.metersphere.system.log.aspect.OperationLogAspect; import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.dto.LogDTO; +import io.metersphere.system.notice.constants.NoticeConstants; import io.metersphere.system.service.UserLoginService; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; @@ -97,6 +97,12 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService { private BugRelationCaseMapper bugRelationCaseMapper; @Resource private BugMapper bugMapper; + @Resource + private TestPlanCaseExecuteHistoryMapper testPlanCaseExecuteHistoryMapper; + @Resource + private FunctionalCaseAttachmentService functionalCaseAttachmentService; + @Resource + private TestPlanSendNoticeService testPlanSendNoticeService; private static final String CASE_MODULE_COUNT_ALL = "all"; @Override @@ -341,4 +347,60 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService { } return null; } + + /** + * 执行功能用例 + * + * @param request + * @param logInsertModule + */ + public void run(TestPlanCaseRunRequest request, LogInsertModule logInsertModule) { + TestPlanFunctionalCase functionalCase = new TestPlanFunctionalCase(); + functionalCase.setLastExecResult(request.getLastExecResult()); + functionalCase.setLastExecTime(System.currentTimeMillis()); + functionalCase.setExecuteUser(logInsertModule.getOperator()); + functionalCase.setId(request.getId()); + testPlanFunctionalCaseMapper.updateByPrimaryKeySelective(functionalCase); + + //执行记录 + TestPlanCaseExecuteHistory executeHistory = buildHistory(request, logInsertModule.getOperator()); + testPlanCaseExecuteHistoryMapper.insert(executeHistory); + + //富文本评论的处理 + functionalCaseAttachmentService.uploadMinioFile(request.getCaseId(), request.getProjectId(), request.getPlanCommentFileIds(), logInsertModule.getOperator(), CaseFileSourceType.PLAN_COMMENT.toString()); + + //发通知 + if (StringUtils.isNotBlank(request.getNotifier())) { + List relatedUsers = Arrays.asList(request.getNotifier().split(";")); + testPlanSendNoticeService.sendNoticeCase(relatedUsers, logInsertModule.getOperator(), request.getCaseId(), NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.REVIEW_AT, request.getTestPlanId()); + } + + if (StringUtils.equalsIgnoreCase(request.getLastExecResult(), FunctionalCaseExecuteResult.SUCCESS.name())) { + //成功 发送通知 + testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), logInsertModule.getOperator(), request.getCaseId(), NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.EXECUTE_PASSED, request.getTestPlanId()); + } + + if (StringUtils.equalsIgnoreCase(request.getLastExecResult(), FunctionalCaseExecuteResult.ERROR.name())) { + //失败 发送通知 + testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), logInsertModule.getOperator(), request.getCaseId(), NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.EXECUTE_FAIL, request.getTestPlanId()); + } + + //TODO 日志 + } + + + private TestPlanCaseExecuteHistory buildHistory(TestPlanCaseRunRequest request, String operator) { + TestPlanCaseExecuteHistory executeHistory = new TestPlanCaseExecuteHistory(); + executeHistory.setId(IDGenerator.nextStr()); + executeHistory.setTestPlanCaseId(request.getId()); + executeHistory.setCaseId(request.getCaseId()); + executeHistory.setStatus(request.getLastExecResult()); + executeHistory.setContent(request.getContent().getBytes()); + executeHistory.setSteps(request.getStepsExecResult().getBytes()); + executeHistory.setDeleted(false); + executeHistory.setNotifier(request.getNotifier()); + executeHistory.setCreateUser(operator); + executeHistory.setCreateTime(System.currentTimeMillis()); + return executeHistory; + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanSendNoticeService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanSendNoticeService.java new file mode 100644 index 0000000000..91883b5a85 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanSendNoticeService.java @@ -0,0 +1,74 @@ +package io.metersphere.plan.service; + +import io.metersphere.functional.domain.FunctionalCase; +import io.metersphere.functional.mapper.FunctionalCaseMapper; +import io.metersphere.plan.domain.TestPlan; +import io.metersphere.plan.mapper.TestPlanMapper; +import io.metersphere.system.domain.User; +import io.metersphere.system.mapper.UserMapper; +import io.metersphere.system.notice.NoticeModel; +import io.metersphere.system.notice.constants.NoticeConstants; +import io.metersphere.system.notice.utils.MessageTemplateUtils; +import io.metersphere.system.service.NoticeSendService; +import jakarta.annotation.Resource; +import org.apache.commons.beanutils.BeanMap; +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +@Service +@Transactional(rollbackFor = Exception.class) +public class TestPlanSendNoticeService { + + @Resource + private FunctionalCaseMapper functionalCaseMapper; + @Resource + private UserMapper userMapper; + @Resource + private TestPlanMapper testPlanMapper; + @Resource + private NoticeSendService noticeSendService; + + public void sendNoticeCase(List relatedUsers, String userId, String caseId, String task, String event, String testPlanId) { + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(caseId); + User user = userMapper.selectByPrimaryKey(userId); + setLanguage(user.getLanguage()); + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(testPlanId); + Map defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap(); + String template = defaultTemplateMap.get(task + "_" + event); + Map defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap(); + String subject = defaultSubjectMap.get(task + "_" + event); + Map paramMap; + BeanMap beanMap = new BeanMap(functionalCase); + paramMap = new HashMap<>(beanMap); + paramMap.put("testPlanName", testPlan.getName()); + paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName()); + NoticeModel noticeModel = NoticeModel.builder() + .operator(user.getId()) + .context(template) + .subject(subject) + .paramMap(paramMap) + .event(event) + .status((String) paramMap.get("status")) + .excludeSelf(true) + .relatedUsers(relatedUsers) + .build(); + noticeSendService.send(task, noticeModel); + } + + private static void setLanguage(String language) { + Locale locale = Locale.SIMPLIFIED_CHINESE; + if (StringUtils.containsIgnoreCase("US",language)) { + locale = Locale.US; + } else if (StringUtils.containsIgnoreCase("TW",language)){ + locale = Locale.TAIWAN; + } + LocaleContextHolder.setLocale(locale); + } +} diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanCaseControllerTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanCaseControllerTests.java index 924a573fec..83052cd686 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanCaseControllerTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanCaseControllerTests.java @@ -9,6 +9,7 @@ import io.metersphere.plan.domain.TestPlanFunctionalCaseExample; import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest; import io.metersphere.plan.dto.request.TestPlanCaseAssociateBugRequest; import io.metersphere.plan.dto.request.TestPlanCaseRequest; +import io.metersphere.plan.dto.request.TestPlanCaseRunRequest; import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper; import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.request.BugPageProviderRequest; @@ -39,7 +40,7 @@ public class TestPlanCaseControllerTests extends BaseTest { public static final String FUNCTIONAL_CASE_TREE_COUNT_URL = "/test-plan/functional/case/module/count"; public static final String FUNCTIONAL_CASE_DISASSOCIATE_URL = "/test-plan/functional/case/batch/disassociate"; - + public static final String FUNCTIONAL_CASE_RUN_URL = "/test-plan/functional/case/run"; @Resource private TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper; @Resource @@ -53,7 +54,7 @@ public class TestPlanCaseControllerTests extends BaseTest { @Sql(scripts = {"/dml/init_test_plan_case_relate_bug.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void testGetFunctionalCaseList() throws Exception { TestPlanCaseRequest request = new TestPlanCaseRequest(); - request.setProjectId("123"); + request.setProjectId(DEFAULT_PROJECT_ID); request.setCurrent(1); request.setPageSize(10); request.setTestPlanId("plan_1"); @@ -154,4 +155,23 @@ public class TestPlanCaseControllerTests extends BaseTest { this.requestGetWithOk("/test-plan/functional/case/disassociate/bug/" + bugRelationCases.get(0).getId()); } + + + @Test + @Order(11) + public void testFunctionalCaseRun() throws Exception { + TestPlanCaseRunRequest request = new TestPlanCaseRunRequest(); + request.setProjectId("1234"); + request.setId("relate_case_3"); + request.setTestPlanId("plan_2"); + request.setCaseId("fc_1"); + request.setLastExecResult("SUCCESS"); + request.setStepsExecResult("123"); + request.setContent("12334"); + request.setNotifier("123"); + this.requestPostWithOk(FUNCTIONAL_CASE_RUN_URL, request); + request.setLastExecResult("ERROR"); + this.requestPostWithOk(FUNCTIONAL_CASE_RUN_URL, request); + + } }