feat(测试计划): 测试计划更新接口开发以及测试计划组相关个功能完善

This commit is contained in:
song-tianyang 2024-01-18 20:36:05 +08:00 committed by 建国
parent 4f962098fb
commit 222a6901f4
32 changed files with 844 additions and 165 deletions

View File

@ -1,24 +1,96 @@
package io.metersphere.plan.domain; package io.metersphere.plan.domain;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.*;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.*;
import jakarta.validation.constraints.Size;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import lombok.Data; import lombok.Data;
@Data @Data
public class TestPlanFollower implements Serializable { public class TestPlanFollower implements Serializable {
@Schema(description = "测试计划ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "测试计划ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan_follower.test_plan_id.not_blank}", groups = {Created.class}) @NotBlank(message = "{test_plan_follower.test_plan_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{test_plan_follower.test_plan_id.length_range}", groups = {Created.class, Updated.class}) @Size(min = 1, max = 50, message = "{test_plan_follower.test_plan_id.length_range}", groups = {Created.class, Updated.class})
private String testPlanId; private String testPlanId;
@Schema(description = "用户ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "用户ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan_follower.user_id.not_blank}", groups = {Created.class}) @NotBlank(message = "{test_plan_follower.user_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{test_plan_follower.user_id.length_range}", groups = {Created.class, Updated.class}) @Size(min = 1, max = 50, message = "{test_plan_follower.user_id.length_range}", groups = {Created.class, Updated.class})
private String userId; private String userId;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public enum Column {
testPlanId("test_plan_id", "testPlanId", "VARCHAR", false),
userId("user_id", "userId", "VARCHAR", false);
private static final String BEGINNING_DELIMITER = "`";
private static final String ENDING_DELIMITER = "`";
private final String column;
private final boolean isColumnNameDelimited;
private final String javaProperty;
private final String jdbcType;
public String value() {
return this.column;
}
public String getValue() {
return this.column;
}
public String getJavaProperty() {
return this.javaProperty;
}
public String getJdbcType() {
return this.jdbcType;
}
Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) {
this.column = column;
this.javaProperty = javaProperty;
this.jdbcType = jdbcType;
this.isColumnNameDelimited = isColumnNameDelimited;
}
public String desc() {
return this.getEscapedColumnName() + " DESC";
}
public String asc() {
return this.getEscapedColumnName() + " ASC";
}
public static Column[] excludes(Column ... excludes) {
ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
if (excludes != null && excludes.length > 0) {
columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));
}
return columns.toArray(new Column[]{});
}
public static Column[] all() {
return Column.values();
}
public String getEscapedColumnName() {
if (this.isColumnNameDelimited) {
return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString();
} else {
return this.column;
}
}
public String getAliasedEscapedColumnName() {
return this.getEscapedColumnName();
}
}
} }

View File

@ -21,4 +21,8 @@ public interface TestPlanFollowerMapper {
int updateByExampleSelective(@Param("record") TestPlanFollower record, @Param("example") TestPlanFollowerExample example); int updateByExampleSelective(@Param("record") TestPlanFollower record, @Param("example") TestPlanFollowerExample example);
int updateByExample(@Param("record") TestPlanFollower record, @Param("example") TestPlanFollowerExample example); int updateByExample(@Param("record") TestPlanFollower record, @Param("example") TestPlanFollowerExample example);
int batchInsert(@Param("list") List<TestPlanFollower> list);
int batchInsertSelective(@Param("list") List<TestPlanFollower> list, @Param("selective") TestPlanFollower.Column ... selective);
} }

View File

@ -142,4 +142,32 @@
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
</update> </update>
<insert id="batchInsert" parameterType="map">
insert into test_plan_follower
(test_plan_id, user_id)
values
<foreach collection="list" item="item" separator=",">
(#{item.testPlanId,jdbcType=VARCHAR}, #{item.userId,jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
insert into test_plan_follower (
<foreach collection="selective" item="column" separator=",">
${column.escapedColumnName}
</foreach>
)
values
<foreach collection="list" item="item" separator=",">
(
<foreach collection="selective" item="column" separator=",">
<if test="'test_plan_id'.toString() == column.value">
#{item.testPlanId,jdbcType=VARCHAR}
</if>
<if test="'user_id'.toString() == column.value">
#{item.userId,jdbcType=VARCHAR}
</if>
</foreach>
)
</foreach>
</insert>
</mapper> </mapper>

View File

@ -13,7 +13,9 @@ CREATE TABLE IF NOT EXISTS test_plan_module
`create_user` VARCHAR(100) COMMENT '创建人', `create_user` VARCHAR(100) COMMENT '创建人',
`update_user` VARCHAR(100) COMMENT '更新人', `update_user` VARCHAR(100) COMMENT '更新人',
PRIMARY KEY (id) PRIMARY KEY (id)
) COMMENT = '测试计划模块'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划模块';
CREATE INDEX idx_project_id ON test_plan_module (project_id); CREATE INDEX idx_project_id ON test_plan_module (project_id);
@ -42,7 +44,9 @@ CREATE TABLE IF NOT EXISTS test_plan
`actual_end_time` BIGINT COMMENT '实际结束时间', `actual_end_time` BIGINT COMMENT '实际结束时间',
`description` VARCHAR(2000) COMMENT '描述', `description` VARCHAR(2000) COMMENT '描述',
PRIMARY KEY (id) PRIMARY KEY (id)
) COMMENT = '测试计划'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划';
CREATE INDEX idx_group_id ON test_plan (group_id); CREATE INDEX idx_group_id ON test_plan (group_id);
CREATE INDEX idx_project_id ON test_plan (project_id); CREATE INDEX idx_project_id ON test_plan (project_id);
@ -60,14 +64,18 @@ CREATE TABLE IF NOT EXISTS test_plan_config
`repeat_case` BIT NOT NULL DEFAULT 0 COMMENT '是否允许重复添加用例', `repeat_case` BIT NOT NULL DEFAULT 0 COMMENT '是否允许重复添加用例',
`pass_threshold` DOUBLE NOT NULL DEFAULT 100 COMMENT '测试计划通过阈值;0-100', `pass_threshold` DOUBLE NOT NULL DEFAULT 100 COMMENT '测试计划通过阈值;0-100',
PRIMARY KEY (test_plan_id) PRIMARY KEY (test_plan_id)
) COMMENT = '测试计划配置'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划配置';
CREATE TABLE IF NOT EXISTS test_plan_follower CREATE TABLE IF NOT EXISTS test_plan_follower
( (
`test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID;联合主键', `test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID;联合主键',
`user_id` VARCHAR(50) NOT NULL COMMENT '用户ID;联合主键', `user_id` VARCHAR(50) NOT NULL COMMENT '用户ID;联合主键',
PRIMARY KEY (test_plan_id, user_id) PRIMARY KEY (test_plan_id, user_id)
) COMMENT = '测试计划关注人'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划关注人';
CREATE TABLE IF NOT EXISTS test_plan_functional_case CREATE TABLE IF NOT EXISTS test_plan_functional_case
( (
@ -81,7 +89,9 @@ CREATE TABLE IF NOT EXISTS test_plan_functional_case
`last_exec_result` VARCHAR(50) COMMENT '最后执行结果', `last_exec_result` VARCHAR(50) COMMENT '最后执行结果',
`pos` BIGINT NOT NULL COMMENT '自定义排序间隔5000', `pos` BIGINT NOT NULL COMMENT '自定义排序间隔5000',
PRIMARY KEY (id) PRIMARY KEY (id)
) COMMENT = '测试计划关联功能用例'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划关联功能用例';
CREATE INDEX idx_functional_case_id ON test_plan_functional_case (functional_case_id); CREATE INDEX idx_functional_case_id ON test_plan_functional_case (functional_case_id);
CREATE INDEX idx_test_plan_id ON test_plan_functional_case (test_plan_id); CREATE INDEX idx_test_plan_id ON test_plan_functional_case (test_plan_id);
@ -100,7 +110,9 @@ CREATE TABLE IF NOT EXISTS test_plan_api_case
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人', `create_user` VARCHAR(50) NOT NULL COMMENT '创建人',
`pos` BIGINT NOT NULL COMMENT '自定义排序间隔5000', `pos` BIGINT NOT NULL COMMENT '自定义排序间隔5000',
PRIMARY KEY (id) PRIMARY KEY (id)
) COMMENT = '测试计划关联接口用例'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划关联接口用例';
CREATE INDEX idx_api_case_id ON test_plan_api_case (api_case_id); CREATE INDEX idx_api_case_id ON test_plan_api_case (api_case_id);
@ -120,12 +132,23 @@ CREATE TABLE IF NOT EXISTS test_plan_api_scenario
`create_user` VARCHAR(40) NOT NULL COMMENT '创建人', `create_user` VARCHAR(40) NOT NULL COMMENT '创建人',
`pos` BIGINT NOT NULL COMMENT '自定义排序间隔5000', `pos` BIGINT NOT NULL COMMENT '自定义排序间隔5000',
PRIMARY KEY (id) PRIMARY KEY (id)
) COMMENT = '测试计划关联场景用例'; ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划关联场景用例';
CREATE INDEX idx_api_scenario_id ON test_plan_api_scenario (api_scenario_id); CREATE INDEX idx_api_scenario_id ON test_plan_api_scenario (api_scenario_id);
CREATE INDEX idx_test_plan_id ON test_plan_api_scenario (test_plan_id); CREATE INDEX idx_test_plan_id ON test_plan_api_scenario (test_plan_id);
CREATE INDEX idx_create_user ON test_plan_api_scenario (create_user); CREATE INDEX idx_create_user ON test_plan_api_scenario (create_user);
CREATE TABLE IF NOT EXISTS test_plan_follower
(
`test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID;联合主键',
`user_id` VARCHAR(50) NOT NULL COMMENT '用户ID;联合主键',
PRIMARY KEY (test_plan_id, user_id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划关注人';
-- set innodb lock wait timeout to default -- set innodb lock wait timeout to default
SET SESSION innodb_lock_wait_timeout = DEFAULT; SET SESSION innodb_lock_wait_timeout = DEFAULT;

View File

@ -6,7 +6,7 @@ public class TestPlanConstants {
//测试计划类型-测试计划组 //测试计划类型-测试计划组
public static final String TEST_PLAN_TYPE_GROUP = "GROUP"; public static final String TEST_PLAN_TYPE_GROUP = "GROUP";
//测试计划组默认ID //测试计划组默认ID
public static final String TEST_PLAN_DEFAULT_GROUP_ID = "none"; public static final String TEST_PLAN_DEFAULT_GROUP_ID = "NONE";
//测试计划状态-未开始 //测试计划状态-未开始
public static final String TEST_PLAN_STATUS_PREPARED = "PREPARED"; public static final String TEST_PLAN_STATUS_PREPARED = "PREPARED";

View File

@ -1,3 +1,5 @@
test_plan.test_plan=测试计划
test_plan.test_plan_group=测试计划组
test_plan.id.not_blank=测试计划id不能为空 test_plan.id.not_blank=测试计划id不能为空
test_plan.project_id.length_range=测试计划所属项目id长度过长 test_plan.project_id.length_range=测试计划所属项目id长度过长
test_plan.project_id.not_blank=测试计划所属项目id不能为空 test_plan.project_id.not_blank=测试计划所属项目id不能为空

View File

@ -1,3 +1,5 @@
test_plan.test_plan=Test plan
test_plan.test_plan_group=Test plan group
test_plan.id.not_blank=Test plan id cannot be empty test_plan.id.not_blank=Test plan id cannot be empty
test_plan.project_id.length_range=Test plan project id length too long test_plan.project_id.length_range=Test plan project id length too long
test_plan.project_id.not_blank=Test plan project id cannot be empty test_plan.project_id.not_blank=Test plan project id cannot be empty

View File

@ -1,3 +1,5 @@
test_plan.test_plan=测试计划
test_plan.test_plan_group=测试计划组
test_plan.id.not_blank=测试计划id不能为空 test_plan.id.not_blank=测试计划id不能为空
test_plan.project_id.length_range=测试计划所属项目id长度过长 test_plan.project_id.length_range=测试计划所属项目id长度过长
test_plan.project_id.not_blank=测试计划所属项目id不能为空 test_plan.project_id.not_blank=测试计划所属项目id不能为空

View File

@ -1,3 +1,5 @@
test_plan.test_plan=測試計劃
test_plan.test_plan_group=測試計劃組
test_plan.id.not_blank=測試計劃id不能為空 test_plan.id.not_blank=測試計劃id不能為空
test_plan.project_id.length_range=測試計劃所屬項目id長度過長 test_plan.project_id.length_range=測試計劃所屬項目id長度過長
test_plan.project_id.not_blank=測試計劃所屬項目id不能為空 test_plan.project_id.not_blank=測試計劃所屬項目id不能為空

View File

@ -63,6 +63,7 @@ public abstract class ModuleTreeService {
* @param haveVirtualRootNode 是否包含虚拟跟节点 * @param haveVirtualRootNode 是否包含虚拟跟节点
*/ */
public List<BaseTreeNode> buildTreeAndCountResource(List<BaseTreeNode> traverseList, boolean haveVirtualRootNode, String virtualRootName) { public List<BaseTreeNode> buildTreeAndCountResource(List<BaseTreeNode> traverseList, boolean haveVirtualRootNode, String virtualRootName) {
List<BaseTreeNode> baseTreeNodeList = new ArrayList<>(); List<BaseTreeNode> baseTreeNodeList = new ArrayList<>();
if (haveVirtualRootNode) { if (haveVirtualRootNode) {
BaseTreeNode defaultNode = this.getDefaultModule(virtualRootName); BaseTreeNode defaultNode = this.getDefaultModule(virtualRootName);

View File

@ -1,10 +1,10 @@
package io.metersphere.system.controller; package io.metersphere.system.controller;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.system.dto.sdk.LicenseDTO;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.LicenseDTO;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.MethodOrderer;
@ -72,7 +72,7 @@ public class LicenseControllerTests extends BaseTest {
Assertions.assertEquals(200, mvcResult.getResponse().getStatus()); Assertions.assertEquals(200, mvcResult.getResponse().getStatus());
LicenseDTO licenseDTO = parseObjectFromMvcResult(mvcResult, LicenseDTO.class); LicenseDTO licenseDTO = parseObjectFromMvcResult(mvcResult, LicenseDTO.class);
Assertions.assertNotNull(licenseDTO); Assertions.assertNotNull(licenseDTO);
Assertions.assertEquals("OK", licenseDTO.getStatus()); Assertions.assertEquals("valid", licenseDTO.getStatus());
} }
@Test @Test
@ -81,7 +81,7 @@ public class LicenseControllerTests extends BaseTest {
Assertions.assertEquals(200, mvcResult.getResponse().getStatus()); Assertions.assertEquals(200, mvcResult.getResponse().getStatus());
LicenseDTO licenseDTO = parseObjectFromMvcResult(mvcResult, LicenseDTO.class); LicenseDTO licenseDTO = parseObjectFromMvcResult(mvcResult, LicenseDTO.class);
Assertions.assertNotNull(licenseDTO); Assertions.assertNotNull(licenseDTO);
Assertions.assertEquals("OK", licenseDTO.getStatus()); Assertions.assertEquals("valid", licenseDTO.getStatus());
} }

View File

@ -10,21 +10,21 @@ public class LicenseServiceMockImpl implements LicenseService {
@Override @Override
public LicenseDTO refreshLicense() { public LicenseDTO refreshLicense() {
LicenseDTO licenseDTO = new LicenseDTO(); LicenseDTO licenseDTO = new LicenseDTO();
licenseDTO.setStatus("OK"); licenseDTO.setStatus("valid");
return licenseDTO; return licenseDTO;
} }
@Override @Override
public LicenseDTO validate() { public LicenseDTO validate() {
LicenseDTO licenseDTO = new LicenseDTO(); LicenseDTO licenseDTO = new LicenseDTO();
licenseDTO.setStatus("OK"); licenseDTO.setStatus("valid");
return licenseDTO; return licenseDTO;
} }
@Override @Override
public LicenseDTO addLicense(String licenseCode, String userId) { public LicenseDTO addLicense(String licenseCode, String userId) {
LicenseDTO licenseDTO = new LicenseDTO(); LicenseDTO licenseDTO = new LicenseDTO();
licenseDTO.setStatus("OK"); licenseDTO.setStatus("valid");
return licenseDTO; return licenseDTO;
} }

View File

@ -3,6 +3,8 @@ package io.metersphere.plan.controller;
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
import io.metersphere.plan.dto.request.TestPlanCreateRequest; import io.metersphere.plan.dto.request.TestPlanCreateRequest;
import io.metersphere.plan.dto.request.TestPlanTableRequest; import io.metersphere.plan.dto.request.TestPlanTableRequest;
import io.metersphere.plan.dto.request.TestPlanUpdateRequest;
import io.metersphere.plan.dto.response.TestPlanCountResponse;
import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanManagementService;
import io.metersphere.plan.service.TestPlanService; import io.metersphere.plan.service.TestPlanService;
@ -43,7 +45,7 @@ public class TestPlanController {
@Operation(summary = "测试计划-获取统计数据") @Operation(summary = "测试计划-获取统计数据")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@CheckOwner(resourceId = "#id", resourceType = "test_plan") @CheckOwner(resourceId = "#id", resourceType = "test_plan")
public TestPlanResponse getCount(@PathVariable String id) { public TestPlanCountResponse getCount(@PathVariable String id) {
return testPlanService.getCount(id); return testPlanService.getCount(id);
} }
@ -52,7 +54,8 @@ public class TestPlanController {
@Operation(summary = "测试计划-模块统计") @Operation(summary = "测试计划-模块统计")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public Map<String, Long> moduleCount(@Validated @RequestBody TestPlanTableRequest request) { public Map<String, Long> moduleCount(@Validated @RequestBody TestPlanTableRequest
request) {
return testPlanManagementService.moduleCount(request); return testPlanManagementService.moduleCount(request);
} }
@ -61,8 +64,16 @@ public class TestPlanController {
@Operation(summary = "测试计划-创建测试计划") @Operation(summary = "测试计划-创建测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public String add(@Validated @RequestBody TestPlanCreateRequest testPlan) { public String add(@Validated @RequestBody TestPlanCreateRequest request) {
return testPlanService.add(testPlan, SessionUtils.getUserId(), "/test-plan/add", HttpMethodConstants.POST.name()); return testPlanService.add(request, SessionUtils.getUserId(), "/test-plan/add", HttpMethodConstants.POST.name());
}
@PostMapping("/update")
@Operation(summary = "测试计划-创建测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getId()", resourceType = "test_plan")
public String add(@Validated @RequestBody TestPlanUpdateRequest request) {
return testPlanService.update(request, SessionUtils.getUserId(), "/test-plan/update", HttpMethodConstants.POST.name());
} }

View File

@ -21,7 +21,7 @@ public class TestPlanQueryConditions {
private String projectId; private String projectId;
//测试计划所属GroupId //测试计划所属GroupId
private String groupId = TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID; private String groupId;
//查询条件 //查询条件
private BaseCondition condition = new BaseCondition(); private BaseCondition condition = new BaseCondition();
@ -29,7 +29,11 @@ public class TestPlanQueryConditions {
//隐藏的测试计划ID //隐藏的测试计划ID
public List<String> hiddenIds = new ArrayList<>(); public List<String> hiddenIds = new ArrayList<>();
//需要包含的ID
public List<String> includeIds = new ArrayList<>();
public TestPlanQueryConditions(List<String > moduleIds,String projectId,BaseCondition condition){ public TestPlanQueryConditions(List<String > moduleIds,String projectId,BaseCondition condition){
this.groupId = TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID;
this.moduleIds = moduleIds; this.moduleIds = moduleIds;
this.projectId = projectId; this.projectId = projectId;
this.condition = condition; this.condition = condition;

View File

@ -7,6 +7,7 @@ import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -58,8 +59,14 @@ public class TestPlanCreateRequest {
@Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED)
@Max(value = 100, message = "{test_plan.pass_threshold.max}") @Max(value = 100, message = "{test_plan.pass_threshold.max}")
private double passThreshold = 100; private double passThreshold = 100;
@Schema(description = "测试计划类型")
private String type = TestPlanConstants.TEST_PLAN_TYPE_PLAN;
public List<String> getTags() { public List<String> getTags() {
return tags == null ? null : new ArrayList<>(tags); return tags == null ? null : new ArrayList<>(tags);
} }
public boolean isGroupOption() {
return StringUtils.equals(this.type, TestPlanConstants.TEST_PLAN_TYPE_GROUP) || !StringUtils.equals(this.groupId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
}
} }

View File

@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
@ -22,4 +24,9 @@ public class TestPlanTableRequest extends BasePageRequest {
this.setCurrent(1); this.setCurrent(1);
this.setPageSize(5); this.setPageSize(5);
} }
//没有查询条件
public boolean conditionIsEmpty() {
return StringUtils.isEmpty(this.getKeyword()) && MapUtils.isEmpty(this.getFilter()) && MapUtils.isEmpty(this.getCombine());
}
} }

View File

@ -0,0 +1,49 @@
package io.metersphere.plan.dto.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.util.LinkedHashSet;
@Data
public class TestPlanUpdateRequest {
@Schema(description = "测试计划ID")
@NotBlank(message = "{test_plan.id.not_blank}")
private String id;
@Schema(description = "测试计划名称")
private String name;
@Schema(description = "模块ID")
private String moduleId;
@Schema(description = "标签")
private LinkedHashSet<String> tags;
@Schema(description = "计划开始时间")
private Long plannedStartTime;
@Schema(description = "计划结束时间")
private Long plannedEndTime;
@Schema(description = "描述")
private String description;
@Schema(description = "是否自定更新功能用例状态")
private Boolean automaticStatusUpdate;
@Schema(description = "是否允许重复添加用例")
private Boolean repeatCase;
@Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED)
@Max(value = 100)
@Min(value = 0)
private Double passThreshold;
@Schema(description = "测试计划组Id")
private String testPlanGroupId;
}

View File

@ -0,0 +1,22 @@
package io.metersphere.plan.dto.response;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class TestPlanCountResponse {
@Schema(description = "测试计划ID")
private String id;
@Schema(description = "通过率")
private String passRate;
@Schema(description = "功能用例数")
private long functionalCaseCount = -1;
@Schema(description = "接口用例数")
private long apiCaseCount = -1;
@Schema(description = "接口场景数")
private long apiScenarioCount = -1;
@Schema(description = "Bug数量")
private long bugCount = -1;
@Schema(description = "测试进度")
private String testProgress;
}

View File

@ -3,29 +3,22 @@ package io.metersphere.plan.dto.response;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.List;
@Data @Data
public class TestPlanResponse { public class TestPlanResponse {
//ID计划名称计划状态测试进度通过率用例数定时任务bug数创建人创建时间模块
@Schema(description = "测试计划ID") @Schema(description = "测试计划ID")
private String id; private String id;
@Schema(description = "项目ID")
private String projectId;
@Schema(description = "测试计划编号") @Schema(description = "测试计划编号")
private long num; private long num;
@Schema(description = "名称") @Schema(description = "名称")
private String name; private String name;
@Schema(description = "状态") @Schema(description = "状态")
private String status; private String status;
@Schema(description = "测试进度") @Schema(description = "标签")
private String testProgress; private List<String> tags;
@Schema(description = "通过率")
private String passRate;
@Schema(description = "功能用例数")
private long functionalCaseCount = -1;
@Schema(description = "接口用例数")
private long apiCaseCount = -1;
@Schema(description = "接口场景数")
private long apiScenarioCount = -1;
@Schema(description = "Bug数量")
private long bugCount = -1;
@Schema(description = "定时任务") @Schema(description = "定时任务")
private String schedule; private String schedule;
@Schema(description = "创建人") @Schema(description = "创建人")
@ -36,6 +29,9 @@ public class TestPlanResponse {
private String moduleName; private String moduleName;
@Schema(description = "模块Id") @Schema(description = "模块Id")
private String moduleId; private String moduleId;
@Schema(description = "类型(测试计划组/测试计划)") @Schema(description = "测试计划组内的测试计划")
private String type; List<TestPlanResponse> testPlanItem;
@Schema(description = "测试计划组Id")
private String testPlanGroupId;
} }

View File

@ -17,7 +17,9 @@ public interface ExtTestPlanMapper {
List<String> selectIdByConditions(TestPlanQueryConditions testPlanQueryConditions); List<String> selectIdByConditions(TestPlanQueryConditions testPlanQueryConditions);
List<ModuleCountDTO> countModuleIdByKeywordAndFileType(TestPlanQueryConditions testPlanQueryConditions); List<String> selectGroupIdByConditions(TestPlanQueryConditions testPlanQueryConditions);
List<ModuleCountDTO> countModuleIdByConditions(TestPlanQueryConditions testPlanQueryConditions);
List<TestPlan> selectBaseInfoByIds(@Param("list") List<String> deleteIdList); List<TestPlan> selectBaseInfoByIds(@Param("list") List<String> deleteIdList);

View File

@ -1,9 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.plan.mapper.ExtTestPlanMapper"> <mapper namespace="io.metersphere.plan.mapper.ExtTestPlanMapper">
<resultMap id="testPlanBaseInfo" type="io.metersphere.plan.dto.response.TestPlanResponse">
<id column="id" jdbcType="VARCHAR" property="id"/>
<result column="num" jdbcType="BIGINT" property="num"/>
<result column="module_id" jdbcType="VARCHAR" property="moduleId"/>
<result column="project_id" jdbcType="VARCHAR" property="projectId"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler"/>
<result column="create_user" jdbcType="VARCHAR" property="createUser"/>
<result column="create_time" jdbcType="BIGINT" property="createTime"/>
<result column="status" jdbcType="VARCHAR" property="status"/>
</resultMap>
<update id="updateDefaultGroupId"> <update id="updateDefaultGroupId">
UPDATE test_plan UPDATE test_plan
SET group_id = 'none' SET group_id = 'NONE'
WHERE group_id IN WHERE group_id IN
<foreach collection="list" item="item" open="(" separator="," close=")"> <foreach collection="list" item="item" open="(" separator="," close=")">
#{item} #{item}
@ -22,7 +34,7 @@
<select id="selectByConditions" <select id="selectByConditions"
parameterType="io.metersphere.plan.dto.TestPlanQueryConditions" parameterType="io.metersphere.plan.dto.TestPlanQueryConditions"
resultType="io.metersphere.plan.dto.response.TestPlanResponse"> resultMap="testPlanBaseInfo">
SELECT SELECT
t.id,t.num,t.name,t.status, t.id,t.num,t.name,t.status,
createUser.name AS createUser, createUser.name AS createUser,
@ -34,7 +46,8 @@
INNER JOIN user createUser ON t.create_user = createUser.id INNER JOIN user createUser ON t.create_user = createUser.id
<include refid="test_plan_page_request"/> <include refid="test_plan_page_request"/>
</select> </select>
<select id="countModuleIdByKeywordAndFileType"
<select id="countModuleIdByConditions"
parameterType="io.metersphere.plan.dto.TestPlanQueryConditions" parameterType="io.metersphere.plan.dto.TestPlanQueryConditions"
resultType="io.metersphere.project.dto.ModuleCountDTO"> resultType="io.metersphere.project.dto.ModuleCountDTO">
SELECT t.module_id AS moduleId, count(t.id) AS dataCount SELECT t.module_id AS moduleId, count(t.id) AS dataCount
@ -52,6 +65,18 @@
INNER JOIN user createUser ON t.create_user = createUser.id INNER JOIN user createUser ON t.create_user = createUser.id
<include refid="test_plan_page_request"/> <include refid="test_plan_page_request"/>
</select> </select>
<select id="selectGroupIdByConditions"
parameterType="io.metersphere.plan.dto.TestPlanQueryConditions"
resultType="java.lang.String">
SELECT
distinct t.group_id
FROM test_plan t
INNER JOIN user createUser ON t.create_user = createUser.id
<include refid="test_plan_page_request"/>
AND t.group_id != 'NONE'
</select>
<select id="selectBaseInfoByIds" resultType="io.metersphere.plan.domain.TestPlan"> <select id="selectBaseInfoByIds" resultType="io.metersphere.plan.domain.TestPlan">
SELECT SELECT
t.id,t.name,t.type,t.project_id t.id,t.name,t.type,t.project_id
@ -63,10 +88,9 @@
</select> </select>
<sql id="test_plan_page_request"> <sql id="test_plan_page_request">
<where> WHERE t.project_id = #{projectId}
t.group_id = #{groupId} <if test="groupId != null and groupId != ''">
<if test="projectId != null and projectId != ''"> AND t.group_id = #{groupId}
AND t.project_id = #{projectId}
</if> </if>
<if test="condition.keyword != null and condition.keyword != ''"> <if test="condition.keyword != null and condition.keyword != ''">
AND t.name like concat('%', #{condition.keyword}, '%') AND t.name like concat('%', #{condition.keyword}, '%')
@ -83,6 +107,13 @@
#{item} #{item}
</foreach> </foreach>
</if> </if>
</where> <if test="includeIds != null and includeIds.size() != 0">
OR
t.id IN
<foreach collection="includeIds" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</sql> </sql>
</mapper> </mapper>

View File

@ -0,0 +1,8 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanConfig;
public interface TestPlanGroupService {
boolean validateGroup(TestPlan testPlan, TestPlanConfig testPlanConfig);
}

View File

@ -40,7 +40,7 @@ public class TestPlanLogService {
.method(requestMethod) .method(requestMethod)
.path(requestUrl) .path(requestUrl)
.sourceId(module.getId()) .sourceId(module.getId())
.content(module.getName()) .content(generateTestPlanSimpleContent(module))
.originalValue(JSON.toJSONBytes(module)) .originalValue(JSON.toJSONBytes(module))
.createUser(operator) .createUser(operator)
.build().getLogDTO(); .build().getLogDTO();
@ -103,6 +103,16 @@ public class TestPlanLogService {
operationLogService.batchAdd(list); operationLogService.batchAdd(list);
} }
private String generateTestPlanSimpleContent(TestPlan testPlan) {
StringBuilder content = new StringBuilder();
if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
content.append(Translator.get("test_plan.test_plan_group")).append(StringUtils.SPACE).append(testPlan.getName()).append(StringUtils.SPACE);
} else {
content.append(Translator.get("test_plan.test_plan")).append(StringUtils.SPACE).append(testPlan.getName()).append(StringUtils.SPACE);
}
return content.toString();
}
private String generateTestPlanDeleteContent(TestPlan deleteTestPlan) { private String generateTestPlanDeleteContent(TestPlan deleteTestPlan) {
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
if(StringUtils.equals(deleteTestPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)){ if(StringUtils.equals(deleteTestPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)){

View File

@ -28,20 +28,37 @@ public class TestPlanManagementService {
public Map<String, Long> moduleCount(TestPlanTableRequest request) { public Map<String, Long> moduleCount(TestPlanTableRequest request) {
//查出每个模块节点下的资源数量 不需要按照模块进行筛选 //查出每个模块节点下的资源数量 不需要按照模块进行筛选
TestPlanQueryConditions testPlanQueryConditions = new TestPlanQueryConditions(null, request.getProjectId(), request); TestPlanQueryConditions testPlanQueryConditions = new TestPlanQueryConditions(null, request.getProjectId(), request);
List<ModuleCountDTO> moduleCountDTOList = extTestPlanMapper.countModuleIdByKeywordAndFileType(testPlanQueryConditions); List<ModuleCountDTO> moduleCountDTOList = extTestPlanMapper.countModuleIdByConditions(testPlanQueryConditions);
Map<String, Long> moduleCountMap = testPlanModuleService.getModuleCountMap(request.getProjectId(), moduleCountDTOList); Map<String, Long> moduleCountMap = testPlanModuleService.getModuleCountMap(request.getProjectId(), moduleCountDTOList);
return moduleCountMap; return moduleCountMap;
} }
public Pager<List<TestPlanResponse>> page(TestPlanTableRequest request) { public Pager<List<TestPlanResponse>> page(TestPlanTableRequest request) {
TestPlanQueryConditions queryConditions = this.generateTestPlanConditions(request);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "t.update_time desc"); StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "t.update_time desc");
return PageUtils.setPageInfo(page, this.getTableList(request)); return PageUtils.setPageInfo(page, this.getTableList(queryConditions));
} }
private List<TestPlanResponse> getTableList(TestPlanTableRequest request) { /**
List<TestPlanResponse> testPlanResponses = extTestPlanMapper.selectByConditions(new TestPlanQueryConditions(request.getModuleIds(), request.getProjectId(), request)); * 生成查询条件
*
* @param request 前端传来的筛选条件
* @return
*/
private TestPlanQueryConditions generateTestPlanConditions(TestPlanTableRequest request) {
TestPlanQueryConditions conditions = new TestPlanQueryConditions(request.getModuleIds(), request.getProjectId(), request);
if (!request.conditionIsEmpty()) {
//查询符合匹配的子节点时不需要传入groupId
conditions.setGroupId(null);
List<String> includeGroupIds = extTestPlanMapper.selectGroupIdByConditions(conditions);
conditions.setIncludeIds(includeGroupIds);
}
return conditions;
}
private List<TestPlanResponse> getTableList(TestPlanQueryConditions request) {
List<TestPlanResponse> testPlanResponses = extTestPlanMapper.selectByConditions(request);
testPlanResponses.forEach(item -> { testPlanResponses.forEach(item -> {
item.setModuleName(testPlanModuleService.getNameById(item.getModuleId())); item.setModuleName(testPlanModuleService.getNameById(item.getModuleId()));
//todo 定时任务相关信息处理 //todo 定时任务相关信息处理

View File

@ -150,13 +150,13 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP
public void deleteModule(String deleteId, String operator, String requestUrl, String requestMethod) { public void deleteModule(String deleteId, String operator, String requestUrl, String requestMethod) {
TestPlanModule deleteModule = testPlanModuleMapper.selectByPrimaryKey(deleteId); TestPlanModule deleteModule = testPlanModuleMapper.selectByPrimaryKey(deleteId);
if (deleteModule != null) { if (deleteModule != null) {
this.deleteModule(Collections.singletonList(deleteId), operator, requestUrl, requestMethod); this.deleteModule(Collections.singletonList(deleteId), deleteModule.getProjectId(), operator, requestUrl, requestMethod);
//记录日志 //记录日志
testPlanModuleLogService.saveDeleteLog(deleteModule, operator, requestUrl, requestMethod); testPlanModuleLogService.saveDeleteLog(deleteModule, operator, requestUrl, requestMethod);
} }
} }
public void deleteModule(List<String> deleteIds, String operator, String requestUrl, String requestMethod) { public void deleteModule(List<String> deleteIds, String projectId, String operator, String requestUrl, String requestMethod) {
if (CollectionUtils.isEmpty(deleteIds)) { if (CollectionUtils.isEmpty(deleteIds)) {
return; return;
} }
@ -165,11 +165,12 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP
TestPlanBatchProcessRequest request = new TestPlanBatchProcessRequest(); TestPlanBatchProcessRequest request = new TestPlanBatchProcessRequest();
request.setModuleIds(deleteIds); request.setModuleIds(deleteIds);
request.setSelectAll(true); request.setSelectAll(true);
request.setProjectId(projectId);
testPlanService.batchDelete(request, operator, requestUrl, requestMethod); testPlanService.batchDelete(request, operator, requestUrl, requestMethod);
List<String> childrenIds = extTestPlanModuleMapper.selectChildrenIdsByParentIds(deleteIds); List<String> childrenIds = extTestPlanModuleMapper.selectChildrenIdsByParentIds(deleteIds);
if (CollectionUtils.isNotEmpty(childrenIds)) { if (CollectionUtils.isNotEmpty(childrenIds)) {
deleteModule(childrenIds, operator, requestUrl, requestMethod); deleteModule(childrenIds, projectId, operator, requestUrl, requestMethod);
} }
} }
@ -234,7 +235,7 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP
public void deleteResources(String projectId) { public void deleteResources(String projectId) {
List<String> fileModuleIdList = extTestPlanModuleMapper.selectIdsByProjectId(projectId); List<String> fileModuleIdList = extTestPlanModuleMapper.selectIdsByProjectId(projectId);
if (CollectionUtils.isNotEmpty(fileModuleIdList)) { if (CollectionUtils.isNotEmpty(fileModuleIdList)) {
this.deleteModule(fileModuleIdList, "SCHEDULE", "none", "none"); this.deleteModule(fileModuleIdList, projectId, "SCHEDULE", "none", "none");
} }
} }

View File

@ -1,16 +1,16 @@
package io.metersphere.plan.service; package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlan; import io.metersphere.plan.domain.*;
import io.metersphere.plan.domain.TestPlanConfig;
import io.metersphere.plan.domain.TestPlanConfigExample;
import io.metersphere.plan.domain.TestPlanExample;
import io.metersphere.plan.dto.TestPlanQueryConditions; import io.metersphere.plan.dto.TestPlanQueryConditions;
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
import io.metersphere.plan.dto.request.TestPlanCreateRequest; import io.metersphere.plan.dto.request.TestPlanCreateRequest;
import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.dto.request.TestPlanUpdateRequest;
import io.metersphere.plan.dto.response.TestPlanCountResponse;
import io.metersphere.plan.mapper.ExtTestPlanMapper; import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.plan.mapper.TestPlanConfigMapper; import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.mapper.TestPlanFollowerMapper;
import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.plan.utils.TestPlanXPackFactory;
import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.constants.TestPlanConstants;
@ -26,6 +26,7 @@ import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.BatchProcessUtils; import io.metersphere.system.utils.BatchProcessUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -50,10 +51,10 @@ public class TestPlanService {
@Resource @Resource
private TestPlanModuleMapper testPlanModuleMapper; private TestPlanModuleMapper testPlanModuleMapper;
@Resource @Resource
private TestPlanConfigService testPlanConfigService; private TestPlanFollowerMapper testPlanFollowerMapper;
@Resource @Resource
private TestPlanFollowerService testPlanFollowerService; private TestPlanXPackFactory testPlanXPackFactory;
@Resource @Resource
private TestPlanApiCaseService testPlanApiCaseService; private TestPlanApiCaseService testPlanApiCaseService;
@Resource @Resource
@ -87,18 +88,20 @@ public class TestPlanService {
createTestPlan.setCreateTime(operateTime); createTestPlan.setCreateTime(operateTime);
createTestPlan.setUpdateTime(operateTime); createTestPlan.setUpdateTime(operateTime);
createTestPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED); createTestPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);
createTestPlan.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
testPlanMapper.insert(createTestPlan);
TestPlanConfig testPlanConfig = new TestPlanConfig(); TestPlanConfig testPlanConfig = new TestPlanConfig();
testPlanConfig.setTestPlanId(createTestPlan.getId()); testPlanConfig.setTestPlanId(createTestPlan.getId());
testPlanConfig.setAutomaticStatusUpdate(testPlanCreateRequest.isAutomaticStatusUpdate()); testPlanConfig.setAutomaticStatusUpdate(testPlanCreateRequest.isAutomaticStatusUpdate());
testPlanConfig.setRepeatCase(testPlanCreateRequest.isRepeatCase()); testPlanConfig.setRepeatCase(testPlanCreateRequest.isRepeatCase());
testPlanConfig.setPassThreshold(testPlanCreateRequest.getPassThreshold()); testPlanConfig.setPassThreshold(testPlanCreateRequest.getPassThreshold());
if (testPlanCreateRequest.isGroupOption()) {
testPlanXPackFactory.getTestPlanGroupService().validateGroup(createTestPlan, testPlanConfig);
}
testPlanMapper.insert(createTestPlan);
testPlanConfigMapper.insert(testPlanConfig); testPlanConfigMapper.insert(testPlanConfig);
testPlanLogService.saveAddLog(createTestPlan, operator, requestUrl, requestMethod); testPlanLogService.saveAddLog(createTestPlan, operator, requestUrl, requestMethod);
return createTestPlan.getId(); return createTestPlan.getId();
} }
@ -107,26 +110,23 @@ public class TestPlanService {
if (StringUtils.isBlank(testPlan.getId())) { if (StringUtils.isBlank(testPlan.getId())) {
TestPlanExample.Criteria criteria = example.createCriteria(); TestPlanExample.Criteria criteria = example.createCriteria();
//测试计划第一层的数据还不能超过1000个 //测试计划第一层的数据还不能超过1000个
criteria.andGroupIdEqualTo(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID); if (StringUtils.equals(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
if (testPlanMapper.countByExample(example) >= MAX_TEST_PLAN_SIZE) { criteria.andGroupIdEqualTo(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
throw new MSException(Translator.getWithArgs("test_plan.too_many", MAX_TEST_PLAN_SIZE)); if (testPlanMapper.countByExample(example) >= MAX_TEST_PLAN_SIZE) {
throw new MSException(Translator.getWithArgs("test_plan.too_many", MAX_TEST_PLAN_SIZE));
}
} }
example.clear(); example.clear();
example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()); example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId());
if (testPlanMapper.countByExample(example) > 0) { if (testPlanMapper.countByExample(example) > 0) {
throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName()); throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName());
} }
} } else {
/*
//todo 重名校验-写到测试计划修改的时候再增加
else {
example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()).andIdNotEqualTo(testPlan.getId()); example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()).andIdNotEqualTo(testPlan.getId());
if (testPlanMapper.countByExample(example) > 0) { if (testPlanMapper.countByExample(example) > 0) {
throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName()); throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName());
} }
} }
*/
} }
public void delete(String id, String operator, String requestUrl, String requestMethod) { public void delete(String id, String operator, String requestUrl, String requestMethod) {
@ -212,23 +212,26 @@ public class TestPlanService {
TestPlanConfigExample configExample = new TestPlanConfigExample(); TestPlanConfigExample configExample = new TestPlanConfigExample();
configExample.createCriteria().andTestPlanIdIn(testPlanIds); configExample.createCriteria().andTestPlanIdIn(testPlanIds);
testPlanConfigMapper.deleteByExample(configExample); testPlanConfigMapper.deleteByExample(configExample);
TestPlanFollowerExample testPlanFollowerExample = new TestPlanFollowerExample();
testPlanFollowerExample.createCriteria().andTestPlanIdIn(testPlanIds);
testPlanFollowerMapper.deleteByExample(testPlanFollowerExample);
/* /*
todo todo
删除计划的关注者
删除计划报告
删除计划定时任务 删除计划定时任务
*/ */
} }
public TestPlanResponse getCount(String id) { public TestPlanCountResponse getCount(String id) {
TestPlanResponse response = new TestPlanResponse(); TestPlanCountResponse response = new TestPlanCountResponse();
response.setId(id); response.setId(id);
/* /*
todo 统计测试进度通过率用例数Bug数量这些比较慢的查询是否需要另开接口查询) todo 统计测试进度通过率用例数Bug数量这些比较慢的查询是否需要另开接口查询)
Q:测试计划组需要查询这些数据吗 Q:测试计划组需要查询这些数据吗
*/ */
response.setFunctionalCaseCount(0); response.setFunctionalCaseCount(0);
response.setApiCaseCount(0); response.setApiCaseCount(0);
response.setApiScenarioCount(0); response.setApiScenarioCount(0);
@ -236,4 +239,51 @@ public class TestPlanService {
response.setTestProgress("15.92%"); response.setTestProgress("15.92%");
return response; return response;
} }
public String update(TestPlanUpdateRequest request, String userId, String requestUrl, String requestMethod) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getId());
if (testPlan == null) {
throw new MSException("test_plan.not.exist");
}
if (!ObjectUtils.allNull(request.getName(), request.getModuleId(), request.getTags(), request.getPlannedEndTime(), request.getPlannedStartTime(), request.getDescription(), request.getTestPlanGroupId())) {
TestPlan updateTestPlan = new TestPlan();
updateTestPlan.setId(request.getId());
if (StringUtils.isNotBlank(request.getName())) {
updateTestPlan.setName(request.getName());
updateTestPlan.setProjectId(testPlan.getProjectId());
this.validateTestPlan(updateTestPlan);
}
if (StringUtils.isNotBlank(request.getModuleId())) {
//检查模块的合法性
this.checkModule(request.getModuleId());
updateTestPlan.setModuleId(request.getModuleId());
}
if (CollectionUtils.isNotEmpty(request.getTags())) {
updateTestPlan.setTags(new ArrayList<>(request.getTags()));
}
updateTestPlan.setPlannedStartTime(request.getPlannedStartTime());
updateTestPlan.setPlannedEndTime(request.getPlannedEndTime());
updateTestPlan.setDescription(request.getDescription());
updateTestPlan.setGroupId(request.getTestPlanGroupId());
updateTestPlan.setType(testPlan.getType());
if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP) || StringUtils.isNotEmpty(request.getTestPlanGroupId())) {
//修改组移动测试计划进组出组需要特殊的处理方式
testPlanXPackFactory.getTestPlanGroupService().validateGroup(testPlan, null);
}
testPlanMapper.updateByPrimaryKeySelective(updateTestPlan);
}
if (!ObjectUtils.allNull(request.getAutomaticStatusUpdate(), request.getRepeatCase(), request.getPassThreshold())) {
TestPlanConfig testPlanConfig = new TestPlanConfig();
testPlanConfig.setTestPlanId(request.getId());
testPlanConfig.setAutomaticStatusUpdate(request.getAutomaticStatusUpdate());
testPlanConfig.setRepeatCase(request.getRepeatCase());
testPlanConfig.setPassThreshold(request.getPassThreshold());
testPlanConfigMapper.updateByPrimaryKeySelective(testPlanConfig);
}
testPlanLogService.saveUpdateLog(testPlan, testPlanMapper.selectByPrimaryKey(request.getId()), testPlan.getProjectId(), userId, requestUrl, requestMethod);
return request.getId();
}
} }

View File

@ -0,0 +1,38 @@
package io.metersphere.plan.utils;
import io.metersphere.plan.service.TestPlanGroupService;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.system.dto.sdk.LicenseDTO;
import io.metersphere.system.service.LicenseService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@Component
public class TestPlanXPackFactory {
private TestPlanGroupService testPlanGroupService;
private LicenseService licenseService;
public TestPlanGroupService getTestPlanGroupService() {
this.checkService();
if (licenseValidate()) {
return testPlanGroupService;
} else {
return null;
}
}
private void checkService() {
if (licenseService == null) {
licenseService = CommonBeanFactory.getBean(LicenseService.class);
}
if (testPlanGroupService == null) {
testPlanGroupService = CommonBeanFactory.getBean(TestPlanGroupService.class);
}
}
private boolean licenseValidate() {
LicenseDTO licenseDTO = licenseService.validate();
return (licenseDTO != null && StringUtils.equals(licenseDTO.getStatus(), "valid"));
}
}

View File

@ -77,9 +77,10 @@
<!-- typeHandler="io.metersphere.handler.ListTypeHandler"/>--> <!-- typeHandler="io.metersphere.handler.ListTypeHandler"/>-->
<!-- </table>--> <!-- </table>-->
<table tableName="test_plan_functional_case"/> <!-- <table tableName="test_plan_functional_case"/>-->
<table tableName="test_plan_api_case"/> <!-- <table tableName="test_plan_api_case"/>-->
<table tableName="test_plan_api_scenario"/> <!-- <table tableName="test_plan_api_scenario"/>-->
<table tableName="test_plan_follower"/>
<!-- <table tableName="test_plan_config"/>--> <!-- <table tableName="test_plan_config"/>-->
<!-- 要忽略的字段--> <!-- 要忽略的字段-->
<!-- <table tableName="test_case"> <!-- <table tableName="test_case">

View File

@ -2,15 +2,17 @@ package io.metersphere.plan.controller;
import io.metersphere.functional.domain.FunctionalCase; import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.plan.domain.TestPlan; import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanConfig;
import io.metersphere.plan.domain.TestPlanFunctionalCase; import io.metersphere.plan.domain.TestPlanFunctionalCase;
import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse;
import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.plan.service.TestPlanModuleService; import io.metersphere.plan.service.TestPlanModuleService;
import io.metersphere.plan.service.TestPlanService; import io.metersphere.plan.service.TestPlanService;
import io.metersphere.plan.service.TestPlanTestService; import io.metersphere.plan.service.TestPlanTestService;
import io.metersphere.plan.utils.TestPlanUtils; import io.metersphere.plan.utils.TestPlanTestUtils;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.filemanagement.request.FileModuleCreateRequest; import io.metersphere.project.dto.filemanagement.request.FileModuleCreateRequest;
import io.metersphere.project.dto.filemanagement.request.FileModuleUpdateRequest; import io.metersphere.project.dto.filemanagement.request.FileModuleUpdateRequest;
@ -73,6 +75,8 @@ public class TestPlanTests extends BaseTest {
@Resource @Resource
private TestPlanModuleMapper testPlanModuleMapper; private TestPlanModuleMapper testPlanModuleMapper;
@Resource @Resource
private TestPlanMapper testPlanMapper;
@Resource
private TestPlanModuleService testPlanModuleService; private TestPlanModuleService testPlanModuleService;
@Resource @Resource
@ -118,6 +122,12 @@ public class TestPlanTests extends BaseTest {
} }
} }
private static long a1NodeCount = 0;
private static long a2NodeCount = 0;
private static long a3NodeCount = 0;
private static long a1a1NodeCount = 0;
private static long a1b1NodeCount = 0;
@Test @Test
@Order(1) @Order(1)
public void emptyDataTest() throws Exception { public void emptyDataTest() throws Exception {
@ -324,7 +334,7 @@ public class TestPlanTests extends BaseTest {
treeNodes = this.getFileModuleTreeNode(); treeNodes = this.getFileModuleTreeNode();
preliminaryTreeNodes = treeNodes; preliminaryTreeNodes = treeNodes;
a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1"); a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1");
assert a1Node != null; assert a1Node != null;
//参数校验 //参数校验
@ -406,7 +416,7 @@ public class TestPlanTests extends BaseTest {
new CheckLogModel(a1Node.getId(), OperationLogType.UPDATE, URL_POST_MODULE_UPDATE) new CheckLogModel(a1Node.getId(), OperationLogType.UPDATE, URL_POST_MODULE_UPDATE)
); );
a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-a1"); a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-a1");
assert a1Node != null; assert a1Node != null;
//反例-参数校验 //反例-参数校验
updateRequest = new FileModuleUpdateRequest(); updateRequest = new FileModuleUpdateRequest();
@ -434,11 +444,11 @@ public class TestPlanTests extends BaseTest {
public void testPlanAddTest() throws Exception { public void testPlanAddTest() throws Exception {
this.preliminaryData(); this.preliminaryData();
BaseTreeNode a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1"); BaseTreeNode a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1");
BaseTreeNode a2Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a2"); BaseTreeNode a2Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a2");
BaseTreeNode a3Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a3"); BaseTreeNode a3Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a3");
BaseTreeNode a1a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-a1"); BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-a1");
BaseTreeNode a1b1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-b1"); BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null; assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
TestPlanCreateRequest request = new TestPlanCreateRequest(); TestPlanCreateRequest request = new TestPlanCreateRequest();
@ -448,20 +458,29 @@ public class TestPlanTests extends BaseTest {
String moduleId; String moduleId;
if (i < 50) { if (i < 50) {
moduleId = a1Node.getId(); moduleId = a1Node.getId();
//选择安东尼巅峰期球衣号码为标志该测试计划将改为测试计划组并用于后续的测试用例相关操作
if (i == 7 || i == 15) {
request.setType(TestPlanConstants.TEST_PLAN_TYPE_GROUP);
}
a1NodeCount++;
} else if (i < 100) { } else if (i < 100) {
moduleId = a2Node.getId(); moduleId = a2Node.getId();
request.setPlannedStartTime(System.currentTimeMillis()); request.setPlannedStartTime(System.currentTimeMillis());
request.setPlannedEndTime(System.currentTimeMillis() + 20000); request.setPlannedEndTime(System.currentTimeMillis() + 20000);
a2NodeCount++;
} else if (i < 150) { } else if (i < 150) {
moduleId = a3Node.getId(); moduleId = a3Node.getId();
request.setRepeatCase(true); request.setRepeatCase(true);
request.setAutomaticStatusUpdate(true); request.setAutomaticStatusUpdate(true);
a3NodeCount++;
} else if (i < 200) { } else if (i < 200) {
moduleId = a1a1Node.getId(); moduleId = a1a1Node.getId();
request.setPassThreshold((double) i / 3); request.setPassThreshold((double) i / 3);
request.setDescription("test plan desc " + i); request.setDescription("test plan desc " + i);
a1a1NodeCount++;
} else { } else {
moduleId = a1b1Node.getId(); moduleId = a1b1Node.getId();
a1b1NodeCount++;
} }
//添加测试计划 //添加测试计划
@ -473,12 +492,13 @@ public class TestPlanTests extends BaseTest {
ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class); ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class);
String returnId = holder.getData().toString(); String returnId = holder.getData().toString();
Assertions.assertNotNull(returnId); Assertions.assertNotNull(returnId);
//选择安东尼巅峰期球衣号码为标志该测试计划将改为测试计划组并用于后续的测试用例相关操作
if (i == 7) { if (i == 7) {
groupTestPlanId7 = returnId; groupTestPlanId7 = returnId;
} else if (i == 15) { } else if (i == 15) {
groupTestPlanId15 = returnId; groupTestPlanId15 = returnId;
} }
//操作日志检查 //操作日志检查
LOG_CHECK_LIST.add( LOG_CHECK_LIST.add(
new CheckLogModel(returnId, OperationLogType.ADD, URL_POST_TEST_PLAN_ADD) new CheckLogModel(returnId, OperationLogType.ADD, URL_POST_TEST_PLAN_ADD)
@ -491,8 +511,15 @@ public class TestPlanTests extends BaseTest {
request.setAutomaticStatusUpdate(false); request.setAutomaticStatusUpdate(false);
request.setPassThreshold(100); request.setPassThreshold(100);
request.setDescription(null); request.setDescription(null);
request.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
} }
TestPlan updateTestPlan = new TestPlan();
updateTestPlan.setId(groupTestPlanId7);
updateTestPlan.setType(TestPlanConstants.TEST_PLAN_TYPE_GROUP);
testPlanMapper.updateByPrimaryKeySelective(updateTestPlan);
updateTestPlan.setId(groupTestPlanId15);
testPlanMapper.updateByPrimaryKeySelective(updateTestPlan);
/* /*
抽查 抽查
testPlan_13没有设置计划开始时间没有设置重复添加用例和自动更新状态阈值为100描述为空 testPlan_13没有设置计划开始时间没有设置重复添加用例和自动更新状态阈值为100描述为空
@ -509,6 +536,26 @@ public class TestPlanTests extends BaseTest {
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError()); this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError());
} }
//在groupTestPlanId7groupTestPlanId15下面各创建20条数据
for (int i = 0; i < 20; i++) {
TestPlanCreateRequest itemRequest = new TestPlanCreateRequest();
itemRequest.setProjectId(project.getId());
itemRequest.setModuleId(a1Node.getId());
itemRequest.setGroupId(groupTestPlanId7);
itemRequest.setName("testPlan_group7_" + i);
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_ADD, itemRequest);
String returnStr = mvcResult.getResponse().getContentAsString();
ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class);
Assertions.assertNotNull(holder.getData().toString());
itemRequest.setGroupId(groupTestPlanId15);
itemRequest.setName("testPlan_group15_" + i);
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_ADD, itemRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
Assertions.assertNotNull(holder.getData().toString());
}
/* /*
反例 反例
1.参数校验 name为空 1.参数校验 name为空
@ -524,17 +571,12 @@ public class TestPlanTests extends BaseTest {
request.setModuleId(IDGenerator.nextStr()); request.setModuleId(IDGenerator.nextStr());
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError()); this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError());
request.setModuleId(a1Node.getId()); request.setModuleId(a1Node.getId());
request.setGroupId(IDGenerator.nextStr()); request.setGroupId(testPlanTestService.selectTestPlanByName("testPlan_60").getGroupId());
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError());
request.setGroupId(groupTestPlanId7);
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError()); this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError());
request.setGroupId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID); request.setGroupId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
request.setPassThreshold(100.111); request.setPassThreshold(100.111);
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().isBadRequest()); this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().isBadRequest());
//修改一个测试计划的type为group创建子测试计划x-pack功能
testPlanTestService.updateTestPlanTypeToGroup(new String[]{groupTestPlanId7, groupTestPlanId15});
//测试权限 //测试权限
request.setProjectId(DEFAULT_PROJECT_ID); request.setProjectId(DEFAULT_PROJECT_ID);
request.setPassThreshold(100); request.setPassThreshold(100);
@ -563,27 +605,14 @@ public class TestPlanTests extends BaseTest {
this.testPlanAddTest(); this.testPlanAddTest();
this.testPlanPageCountTest(); this.testPlanPageCountTest();
} else { } else {
BaseTreeNode a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1"); this.checkModuleCount(moduleCountMap, a1NodeCount, a2NodeCount, a3NodeCount, a1a1NodeCount, a1b1NodeCount);
BaseTreeNode a2Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a2");
BaseTreeNode a3Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a3");
BaseTreeNode a1a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-a1");
BaseTreeNode a1b1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
//检查每个节点下的数据是否匹配的上父节点的统计会一并添加上子节点的数据
moduleCountMap.forEach((k, v) -> {
if (StringUtils.equals(k, a1Node.getId())) {
Assertions.assertEquals(v, 50 + 50 + 799);
} else if (StringUtils.equals(k, a2Node.getId())) {
Assertions.assertEquals(v, 50);
} else if (StringUtils.equals(k, a3Node.getId())) {
Assertions.assertEquals(v, 50);
} else if (StringUtils.equals(k, a1a1Node.getId())) {
Assertions.assertEquals(v, 50);
} else if (StringUtils.equals(k, a1b1Node.getId())) {
Assertions.assertEquals(v, 799);
}
});
BaseTreeNode a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1");
BaseTreeNode a2Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a2");
BaseTreeNode a3Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a3");
BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-a1");
BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
//查询测试计划列表 //查询测试计划列表
MvcResult pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); MvcResult pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
@ -607,19 +636,7 @@ public class TestPlanTests extends BaseTest {
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest); moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8); moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class); moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
moduleCountMap.forEach((k, v) -> { this.checkModuleCount(moduleCountMap, a1NodeCount, a2NodeCount, a3NodeCount, a1a1NodeCount, a1b1NodeCount);
if (StringUtils.equals(k, a1Node.getId())) {
Assertions.assertEquals(v, 50 + 50 + 799);
} else if (StringUtils.equals(k, a2Node.getId())) {
Assertions.assertEquals(v, 50);
} else if (StringUtils.equals(k, a3Node.getId())) {
Assertions.assertEquals(v, 50);
} else if (StringUtils.equals(k, a1a1Node.getId())) {
Assertions.assertEquals(v, 50);
} else if (StringUtils.equals(k, a1b1Node.getId())) {
Assertions.assertEquals(v, 799);
}
});
pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8); returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
@ -638,19 +655,7 @@ public class TestPlanTests extends BaseTest {
moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest); moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8); moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class); moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
moduleCountMap.forEach((k, v) -> { this.checkModuleCount(moduleCountMap, 11, 0, 0, 0, 100);
if (StringUtils.equals(k, a1Node.getId())) {
Assertions.assertEquals(v, 11 + 100);
} else if (StringUtils.equals(k, a2Node.getId())) {
Assertions.assertEquals(v, 0);
} else if (StringUtils.equals(k, a3Node.getId())) {
Assertions.assertEquals(v, 0);
} else if (StringUtils.equals(k, a1a1Node.getId())) {
Assertions.assertEquals(v, 0);
} else if (StringUtils.equals(k, a1b1Node.getId())) {
Assertions.assertEquals(v, 100);
}
});
pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8); returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
@ -676,6 +681,168 @@ public class TestPlanTests extends BaseTest {
} }
@Test
@Order(13)
public void testPlanUpdateTest() throws Exception {
if (StringUtils.isAnyBlank(groupTestPlanId7, groupTestPlanId15)) {
this.testPlanAddTest();
}
TestPlan testPlan = testPlanTestService.selectTestPlanByName("testPlan_21");
TestPlanConfig testPlanConfig = testPlanTestService.selectTestPlanConfigById(testPlan.getId());
//修改名称
TestPlanUpdateRequest updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setName(IDGenerator.nextStr());
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
String returnStr = mvcResult.getResponse().getContentAsString();
ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class);
String returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
//操作日志检查
LOG_CHECK_LIST.add(
new CheckLogModel(returnId, OperationLogType.UPDATE, URL_POST_TEST_PLAN_UPDATE)
);
//修改回来
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setName(testPlan.getName());
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
//修改模块
BaseTreeNode a2Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a2");
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setModuleId(a2Node.getId());
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
//修改回来
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setModuleId(testPlan.getModuleId());
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
//修改标签
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setTags(new LinkedHashSet<>(Arrays.asList("tag1", "tag2", "tag3", "tag3")));
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
testPlan = testPlanTestService.selectTestPlanByName("testPlan_21");
//修改计划开始结束时间
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setPlannedStartTime(System.currentTimeMillis());
updateRequest.setPlannedEndTime(updateRequest.getPlannedStartTime() - 10000);
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
testPlan = testPlanTestService.selectTestPlanByName("testPlan_21");
//修改描述
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setDescription("This is desc");
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
testPlan = testPlanTestService.selectTestPlanByName("testPlan_21");
//修改配置项
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setAutomaticStatusUpdate(true);
updateRequest.setRepeatCase(true);
updateRequest.setPassThreshold(43.123);
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setAutomaticStatusUpdate(false);
updateRequest.setRepeatCase(false);
updateRequest.setPassThreshold(56.478);
mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest);
returnStr = mvcResult.getResponse().getContentAsString();
holder = JSON.parseObject(returnStr, ResultHolder.class);
returnId = holder.getData().toString();
Assertions.assertEquals(returnId, testPlan.getId());
testPlanTestService.checkTestPlanUpdateResult(testPlan, testPlanConfig, updateRequest);
testPlan = testPlanTestService.selectTestPlanByName("testPlan_21");
testPlanConfig = testPlanTestService.selectTestPlanConfigById(testPlan.getId());
//修改a2节点下的数据91,92的所属测试计划组
updateRequest = testPlanTestService.generateUpdateRequest(testPlanTestService.selectTestPlanByName("testPlan_91").getId());
updateRequest.setTestPlanGroupId(groupTestPlanId7);
this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest);
a2NodeCount--;
updateRequest = testPlanTestService.generateUpdateRequest(testPlanTestService.selectTestPlanByName("testPlan_92").getId());
updateRequest.setTestPlanGroupId(groupTestPlanId7);
this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest);
a2NodeCount--;
//修改测试计划组信息
updateRequest = testPlanTestService.generateUpdateRequest(groupTestPlanId7);
updateRequest.setName(IDGenerator.nextStr());
updateRequest.setDescription("This is desc");
updateRequest.setTags(new LinkedHashSet<>(Arrays.asList("tag1", "tag2", "tag3", "tag3")));
updateRequest.setPlannedStartTime(System.currentTimeMillis());
updateRequest.setPlannedEndTime(updateRequest.getPlannedStartTime() - 10000);
this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest);
//什么都不修改
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest);
//因为有条数据被移动了测试计划组里所以检查一下moduleCount.
TestPlanTableRequest testPlanTableRequest = new TestPlanTableRequest();
testPlanTableRequest.setProjectId(project.getId());
MvcResult moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest);
String moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
Map<String, Object> moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class);
this.checkModuleCount(moduleCountMap, a1NodeCount, a2NodeCount, a3NodeCount, a1a1NodeCount, a1b1NodeCount);
//反例不写id
updateRequest = new TestPlanUpdateRequest();
this.requestPost(URL_POST_TEST_PLAN_UPDATE, updateRequest).andExpect(status().isBadRequest());
//反例阈值小于0
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setPassThreshold(-1.2);
this.requestPost(URL_POST_TEST_PLAN_UPDATE, updateRequest).andExpect(status().isBadRequest());
//反例阈值大于100
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setPassThreshold(100.2);
this.requestPost(URL_POST_TEST_PLAN_UPDATE, updateRequest).andExpect(status().isBadRequest());
//反例id是错的
updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId());
updateRequest.setId(IDGenerator.nextStr());
this.requestPost(URL_POST_TEST_PLAN_UPDATE, updateRequest).andExpect(status().is5xxServerError());
}
private static final String URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION = "/test-plan/functional/case/association"; private static final String URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION = "/test-plan/functional/case/association";
private static final String URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT = "/test-plan/functional/case/sort"; private static final String URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT = "/test-plan/functional/case/sort";
@ -844,11 +1011,11 @@ public class TestPlanTests extends BaseTest {
| |
·a3 ·a3
*/ */
BaseTreeNode a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1"); BaseTreeNode a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1");
BaseTreeNode a2Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a2"); BaseTreeNode a2Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a2");
BaseTreeNode a3Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a3"); BaseTreeNode a3Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a3");
BaseTreeNode a1a1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-a1"); BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-a1");
BaseTreeNode a1b1Node = TestPlanUtils.getNodeByName(preliminaryTreeNodes, "a1-b1"); BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null; assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
//父节点内移动-移动到首位 a1挪到a3后面 //父节点内移动-移动到首位 a1挪到a3后面
NodeMoveRequest request = new NodeMoveRequest(); NodeMoveRequest request = new NodeMoveRequest();
@ -1082,7 +1249,7 @@ public class TestPlanTests extends BaseTest {
List<TestPlan> testPlanList = testPlanTestService.selectByProjectIdAndNames(project.getId(), List<TestPlan> testPlanList = testPlanTestService.selectByProjectIdAndNames(project.getId(),
new String[]{"testPlan_61"}); new String[]{"testPlan_61"});
this.requestGet(String.format(URL_GET_TEST_PLAN_DELETE, testPlanList.get(0).getId())).andExpect(status().isOk()); this.requestGet(String.format(URL_GET_TEST_PLAN_DELETE, testPlanList.get(0).getId())).andExpect(status().isOk());
Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 - 1)); Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - 1));
//根据id删除 删除 第610-619这11个) //根据id删除 删除 第610-619这11个)
testPlanList = testPlanTestService.selectByProjectIdAndNames(project.getId(), testPlanList = testPlanTestService.selectByProjectIdAndNames(project.getId(),
@ -1091,7 +1258,7 @@ public class TestPlanTests extends BaseTest {
request.setProjectId(project.getId()); request.setProjectId(project.getId());
request.setSelectIds(testPlanList.stream().map(TestPlan::getId).collect(Collectors.toList())); request.setSelectIds(testPlanList.stream().map(TestPlan::getId).collect(Collectors.toList()));
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request);
Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 - 1 - 10)); Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - 1 - 10));
// 根据查询条件删除 删除plan_2)这一部分 // 根据查询条件删除 删除plan_2)这一部分
request = new TestPlanBatchProcessRequest(); request = new TestPlanBatchProcessRequest();
@ -1099,33 +1266,33 @@ public class TestPlanTests extends BaseTest {
request.setSelectAll(true); request.setSelectAll(true);
request.getCondition().setKeyword("plan_2"); request.getCondition().setKeyword("plan_2");
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request);
Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 - (1 + 10) - (1 + 10 + 100))); Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100)));
//批量删除的数据中包含group7这个用户组 //批量删除的数据中包含group7这个用户组
request = new TestPlanBatchProcessRequest(); request = new TestPlanBatchProcessRequest();
request.setSelectIds(Collections.singletonList(groupTestPlanId7)); request.setSelectIds(Collections.singletonList(groupTestPlanId7));
request.setProjectId(project.getId()); request.setProjectId(project.getId());
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request);
Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 - (1 + 10) - (1 + 10 + 100) - 1)); Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100) - 1));
//根据a1a1Node模快删除 //根据a1a1Node模快删除
BaseTreeNode a1a1Node = TestPlanUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-a1"); BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-a1");
request = new TestPlanBatchProcessRequest(); request = new TestPlanBatchProcessRequest();
request.setSelectAll(true); request.setSelectAll(true);
request.setModuleIds(Arrays.asList(a1a1Node.getId())); request.setModuleIds(Arrays.asList(a1a1Node.getId()));
request.setProjectId(project.getId()); request.setProjectId(project.getId());
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request);
Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 - (1 + 10) - (1 + 10 + 100) - 1 - 50)); Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100) - 1 - 50));
//根据 a1b1Node模块以及planSty这个条件删除应当删除0条数据量不会变化 //根据 a1b1Node模块以及planSty这个条件删除应当删除0条数据量不会变化
BaseTreeNode a1b1Node = TestPlanUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-b1"); BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-b1");
request = new TestPlanBatchProcessRequest(); request = new TestPlanBatchProcessRequest();
request.setSelectAll(true); request.setSelectAll(true);
request.setModuleIds(Arrays.asList(a1b1Node.getId())); request.setModuleIds(Arrays.asList(a1b1Node.getId()));
request.getCondition().setKeyword("planSty"); request.getCondition().setKeyword("planSty");
request.setProjectId(project.getId()); request.setProjectId(project.getId());
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request);
Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 - (1 + 10) - (1 + 10 + 100) - 1 - 50)); Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100) - 1 - 50));
} }
@Test @Test
@ -1134,7 +1301,7 @@ public class TestPlanTests extends BaseTest {
this.preliminaryData(); this.preliminaryData();
// 删除没有文件的节点a1-b1-c1 检查是否级联删除根节点 // 删除没有文件的节点a1-b1-c1 检查是否级联删除根节点
BaseTreeNode a1b1Node = TestPlanUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-b1"); BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-b1");
assert a1b1Node != null; assert a1b1Node != null;
this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, a1b1Node.getId())); this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, a1b1Node.getId()));
@ -1144,7 +1311,7 @@ public class TestPlanTests extends BaseTest {
); );
// 删除有文件的节点 a1-a1 检查是否级联删除根节点 // 删除有文件的节点 a1-a1 检查是否级联删除根节点
BaseTreeNode a1a1Node = TestPlanUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-a1"); BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-a1");
assert a1a1Node != null; assert a1a1Node != null;
this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, a1a1Node.getId())); this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, a1a1Node.getId()));
this.checkModuleIsEmpty(a1a1Node.getId()); this.checkModuleIsEmpty(a1a1Node.getId());
@ -1158,7 +1325,7 @@ public class TestPlanTests extends BaseTest {
this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID)); this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID));
//service层判断测试删除空集合 //service层判断测试删除空集合
testPlanModuleService.deleteModule(new ArrayList<>(), null, null, null); testPlanModuleService.deleteModule(new ArrayList<>(), project.getId(), null, null, null);
//service层判断测试删除项目 //service层判断测试删除项目
testPlanModuleService.deleteResources(project.getId()); testPlanModuleService.deleteResources(project.getId());
@ -1223,6 +1390,7 @@ public class TestPlanTests extends BaseTest {
·a3 ·a3
*/ */
this.updateModuleTest(); this.updateModuleTest();
this.testPlanAddTest();
} }
} }
@ -1259,6 +1427,31 @@ public class TestPlanTests extends BaseTest {
} }
} }
private void checkModuleCount(Map<String, Object> moduleCountMap, long a1NodeCount, long a2NodeCount, long a3NodeCount, long a1a1NodeCount, long a1b1NodeCount) throws Exception {
BaseTreeNode a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1");
BaseTreeNode a2Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a2");
BaseTreeNode a3Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a3");
BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-a1");
BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
//检查每个节点下的数据是否匹配的上父节点的统计会一并添加上子节点的数据
moduleCountMap.forEach((k, v) -> {
long value = Long.parseLong(String.valueOf(v));
if (StringUtils.equals(k, a1Node.getId())) {
Assertions.assertEquals(value, a1NodeCount + a1a1NodeCount + a1b1NodeCount);
} else if (StringUtils.equals(k, a2Node.getId())) {
Assertions.assertEquals(value, a2NodeCount);
} else if (StringUtils.equals(k, a3Node.getId())) {
Assertions.assertEquals(value, a3NodeCount);
} else if (StringUtils.equals(k, a1a1Node.getId())) {
Assertions.assertEquals(value, a1a1NodeCount);
} else if (StringUtils.equals(k, a1b1Node.getId())) {
Assertions.assertEquals(value, a1b1NodeCount);
}
});
}
@Resource @Resource
private TestPlanService testPlanService; private TestPlanService testPlanService;

View File

@ -3,13 +3,16 @@ package io.metersphere.plan.service;
import io.metersphere.functional.domain.FunctionalCase; import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.mapper.FunctionalCaseMapper; import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.plan.domain.*; import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.request.TestPlanUpdateRequest;
import io.metersphere.plan.mapper.TestPlanConfigMapper; import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper; import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper;
import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.sdk.constants.*; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator; import io.metersphere.system.uid.NumGenerator;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
@ -148,4 +151,80 @@ public class TestPlanTestService {
example.setOrderByClause(" pos asc "); example.setOrderByClause(" pos asc ");
return testPlanFunctionalCaseMapper.selectByExample(example); return testPlanFunctionalCaseMapper.selectByExample(example);
} }
public TestPlanConfig selectTestPlanConfigById(String id) {
return testPlanConfigMapper.selectByPrimaryKey(id);
}
public void checkTestPlanUpdateResult(TestPlan testPlan, TestPlanConfig testPlanConfig, TestPlanUpdateRequest updateRequest) {
TestPlan newTestPlan = testPlanMapper.selectByPrimaryKey(updateRequest.getId());
if (StringUtils.isNotBlank(updateRequest.getName())) {
Assertions.assertEquals(newTestPlan.getName(), updateRequest.getName());
} else {
Assertions.assertEquals(newTestPlan.getName(), testPlan.getName());
}
if (StringUtils.isNotBlank(updateRequest.getModuleId())) {
Assertions.assertEquals(newTestPlan.getModuleId(), updateRequest.getModuleId());
} else {
Assertions.assertEquals(newTestPlan.getModuleId(), testPlan.getModuleId());
}
if (CollectionUtils.isNotEmpty(updateRequest.getTags())) {
Assertions.assertEquals(JSON.toJSONString(newTestPlan.getTags()), JSON.toJSONString(updateRequest.getTags()));
} else {
Assertions.assertEquals(JSON.toJSONString(newTestPlan.getTags()), JSON.toJSONString(testPlan.getTags()));
}
if (updateRequest.getPlannedStartTime() != null) {
Assertions.assertEquals(newTestPlan.getPlannedStartTime(), updateRequest.getPlannedStartTime());
} else {
Assertions.assertEquals(newTestPlan.getPlannedStartTime(), testPlan.getPlannedStartTime());
}
if (updateRequest.getPlannedEndTime() != null) {
Assertions.assertEquals(newTestPlan.getPlannedEndTime(), updateRequest.getPlannedEndTime());
} else {
Assertions.assertEquals(newTestPlan.getPlannedEndTime(), testPlan.getPlannedEndTime());
}
if (StringUtils.isNotBlank(updateRequest.getDescription())) {
Assertions.assertEquals(newTestPlan.getDescription(), updateRequest.getDescription());
} else {
Assertions.assertEquals(newTestPlan.getDescription(), testPlan.getDescription());
}
if (testPlanConfig != null) {
TestPlanConfig newTestPlanConfig = testPlanConfigMapper.selectByPrimaryKey(updateRequest.getId());
if (updateRequest.getAutomaticStatusUpdate() != null) {
Assertions.assertEquals(newTestPlanConfig.getAutomaticStatusUpdate(), updateRequest.getAutomaticStatusUpdate());
} else {
Assertions.assertEquals(newTestPlanConfig.getAutomaticStatusUpdate(), testPlanConfig.getAutomaticStatusUpdate());
}
if (updateRequest.getRepeatCase() != null) {
Assertions.assertEquals(newTestPlanConfig.getRepeatCase(), updateRequest.getRepeatCase());
} else {
Assertions.assertEquals(newTestPlanConfig.getRepeatCase(), testPlanConfig.getRepeatCase());
}
if (updateRequest.getPassThreshold() != null) {
Assertions.assertEquals(newTestPlanConfig.getPassThreshold(), updateRequest.getPassThreshold());
} else {
Assertions.assertEquals(newTestPlanConfig.getPassThreshold(), testPlanConfig.getPassThreshold());
}
}
if (updateRequest.getTestPlanGroupId() != null) {
Assertions.assertEquals(newTestPlan.getGroupId(), updateRequest.getTestPlanGroupId());
} else {
Assertions.assertEquals(newTestPlan.getGroupId(), testPlan.getGroupId());
}
}
public TestPlanUpdateRequest generateUpdateRequest(String testPlanId) {
TestPlanUpdateRequest updateRequest = new TestPlanUpdateRequest();
updateRequest.setId(testPlanId);
return updateRequest;
}
} }

View File

@ -0,0 +1,17 @@
package io.metersphere.plan.service.mock;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanConfig;
import io.metersphere.plan.service.TestPlanGroupService;
import org.springframework.stereotype.Service;
@Service
public class TestPlanGroupServiceImpl implements TestPlanGroupService {
@Override
public boolean validateGroup(TestPlan testPlan, TestPlanConfig testPlanConfig) {
return true;
}
}

View File

@ -6,7 +6,7 @@ import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
public class TestPlanUtils { public class TestPlanTestUtils {
public static BaseTreeNode getNodeByName(List<BaseTreeNode> preliminaryTreeNodes, String nodeName) { public static BaseTreeNode getNodeByName(List<BaseTreeNode> preliminaryTreeNodes, String nodeName) {
for (BaseTreeNode firstLevelNode : preliminaryTreeNodes) { for (BaseTreeNode firstLevelNode : preliminaryTreeNodes) {
if (StringUtils.equals(firstLevelNode.getName(), nodeName)) { if (StringUtils.equals(firstLevelNode.getName(), nodeName)) {