feat(测试计划): 获取组内测试计划接口的开发

This commit is contained in:
Jianguo-Genius 2024-06-03 17:05:29 +08:00 committed by 刘瑞斌
parent 86eee33ee9
commit 536185bdca
6 changed files with 107 additions and 65 deletions

View File

@ -54,6 +54,15 @@ public class TestPlanController {
return testPlanManagementService.page(request); return testPlanManagementService.page(request);
} }
@GetMapping("/list-in-group/{groupId}")
@Operation(summary = "测试计划-表格分页查询")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@CheckOwner(resourceId = "#groupId", resourceType = "test_plan")
public List<TestPlanResponse> listInGroup(@NotBlank @PathVariable String groupId) {
testPlanManagementService.checkModuleIsOpen(groupId, TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
return testPlanManagementService.selectByGroupId(groupId);
}
@PostMapping("/statistics") @PostMapping("/statistics")
@Operation(summary = "测试计划-获取计划详情统计{通过率, 执行进度}") @Operation(summary = "测试计划-获取计划详情统计{通过率, 执行进度}")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ)

View File

@ -41,4 +41,6 @@ public class TestPlanResponse extends TestPlanStatisticsResponse {
@Schema(description = "描述") @Schema(description = "描述")
private String description; private String description;
private long pos;
} }

View File

@ -13,11 +13,11 @@ import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
public interface ExtTestPlanMapper { public interface ExtTestPlanMapper {
List<String> selectByGroupId(String parentId); List<String> selectIdByGroupId(String parentId);
List<String> selectByGroupIdList(@Param("list") List<String> parentTestPlanId); List<String> selectByGroupIdList(@Param("list") List<String> parentTestPlanId);
List<TestPlanResponse> selectByConditions(@Param("request") TestPlanTableRequest request,@Param("groupIds") List<String> groupIds); List<TestPlanResponse> selectByConditions(@Param("request") TestPlanTableRequest request);
List<String> selectIdByConditions(@Param("request") TestPlanBatchProcessRequest request); List<String> selectIdByConditions(@Param("request") TestPlanBatchProcessRequest request);
@ -48,4 +48,6 @@ public interface ExtTestPlanMapper {
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam); DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
long selectMaxPosByGroupId(String groupId); long selectMaxPosByGroupId(String groupId);
List<TestPlanResponse> selectByGroupIds(@Param("groupIds") List<String> groupIds);
} }

View File

@ -32,7 +32,7 @@
</foreach> </foreach>
</update> </update>
<select id="selectByGroupId" resultType="java.lang.String"> <select id="selectIdByGroupId" resultType="java.lang.String">
SELECT id FROM test_plan WHERE group_id = #{parentId} SELECT id FROM test_plan WHERE group_id = #{parentId}
</select> </select>
<select id="selectByGroupIdList" resultType="java.lang.String"> <select id="selectByGroupIdList" resultType="java.lang.String">
@ -57,23 +57,32 @@
FROM test_plan t FROM test_plan t
INNER JOIN user createUser ON t.create_user = createUser.id INNER JOIN user createUser ON t.create_user = createUser.id
WHERE t.project_id = #{request.projectId} WHERE t.project_id = #{request.projectId}
<if test="groupIds != null and groupIds.size() > 0"> <include refid="queryByTableRequest"/>
and t.group_id IN </select>
<foreach collection="groupIds" item="groupId" separator="," open="(" close=")">
#{groupId} <select id="selectByGroupIds"
resultMap="BaseResultMapDTO">
SELECT
t.id,t.num,t.name,t.status,t.group_id,
t.create_user AS createUser,
createUser.name AS createUserName,
t.create_time as createTime,
t.module_id as moduleId,
t.type,
t.description,
t.pos,
t.tags
FROM test_plan t
INNER JOIN user createUser ON t.create_user = createUser.id
WHERE t.group_id IN
<foreach collection="groupIds" item="groupId" separator="," open="(" close=")">
#{groupId}
</foreach> </foreach>
</if>
<include refid="queryWhereCondition"/>
ORDER BY t.pos ASC ORDER BY t.pos ASC
</select> </select>
<sql id="queryWhereCondition"> <sql id="queryByTableRequest">
<if test="request.moduleIds != null and request.moduleIds.size() > 0"> <include refid="baseConditionQuery"/>
and t.module_id in
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
#{moduleId}
</foreach>
</if>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and ( and (
t.name like concat('%', #{request.keyword},'%') t.name like concat('%', #{request.keyword},'%')
@ -96,9 +105,6 @@
</when> </when>
</choose> </choose>
</if> </if>
<include refid="filters">
<property name="filter" value="request.filter"/>
</include>
<choose> <choose>
<when test='request.searchMode == "AND"'> <when test='request.searchMode == "AND"'>
AND <include refid="queryCombine"/> AND <include refid="queryCombine"/>
@ -109,6 +115,10 @@
) )
</when> </when>
</choose> </choose>
<include refid="filters">
<property name="filter" value="request.filter"/>
</include>
</sql> </sql>
@ -249,7 +259,7 @@
FROM test_plan t FROM test_plan t
INNER JOIN user createUser ON t.create_user = createUser.id INNER JOIN user createUser ON t.create_user = createUser.id
WHERE t.project_id = #{request.projectId} WHERE t.project_id = #{request.projectId}
<include refid="queryWhereCondition"/> <include refid="queryByTableRequest"/>
GROUP BY t.module_id GROUP BY t.module_id
</select> </select>
<select id="selectIdByConditions" <select id="selectIdByConditions"
@ -259,23 +269,15 @@
t.id t.id
FROM test_plan t FROM test_plan t
WHERE t.project_id = #{request.projectId} WHERE t.project_id = #{request.projectId}
<include refid="queryWhereConditionByBaseQueryRequest"/> <include refid="queryByTestPlanQueryConditions"/>
</select> </select>
<sql id="baseConditionQuery">
<sql id="queryWhereConditionByBaseQueryRequest">
<if test="request.moduleIds != null and request.moduleIds.size() > 0"> <if test="request.moduleIds != null and request.moduleIds.size() > 0">
and t.module_id in and t.module_id in
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")"> <foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
#{moduleId} #{moduleId}
</foreach> </foreach>
</if> </if>
<if test="request.condition.keyword != null and request.condition.keyword != ''">
and (
t.name like concat('%', #{request.condition.keyword},'%')
or t.num like concat('%', #{request.condition.keyword},'%')
or t.tags like concat('%', #{request.condition.keyword}, '%')
)
</if>
<if test="request.type != null and request.type != ''"> <if test="request.type != null and request.type != ''">
<choose> <choose>
<when test="request.type == 'ALL'"> <when test="request.type == 'ALL'">
@ -287,13 +289,20 @@
</when> </when>
<when test="request.type == 'GROUP'"> <when test="request.type == 'GROUP'">
and t.group_id = 'NONE' and t.group_id = 'NONE'
and t.type = 'GTOUP' and t.type = 'GROUP'
</when> </when>
</choose> </choose>
</if> </if>
<include refid="filters"> </sql>
<property name="filter" value="request.condition.filter"/> <sql id="queryByTestPlanQueryConditions">
</include> <include refid="baseConditionQuery"/>
<if test="request.condition.keyword != null and request.condition.keyword != ''">
and (
t.name like concat('%', #{request.condition.keyword},'%')
or t.num like concat('%', #{request.condition.keyword},'%')
or t.tags like concat('%', #{request.condition.keyword}, '%')
)
</if>
<choose> <choose>
<when test='request.condition.searchMode == "AND"'> <when test='request.condition.searchMode == "AND"'>
AND <include refid="baseQueryCombine"/> AND <include refid="baseQueryCombine"/>
@ -304,6 +313,9 @@
) )
</when> </when>
</choose> </choose>
<include refid="filters">
<property name="filter" value="request.condition.filter"/>
</include>
</sql> </sql>
<sql id="baseQueryCombine"> <sql id="baseQueryCombine">

View File

@ -17,6 +17,7 @@ import io.metersphere.sdk.util.Translator;
import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -63,8 +64,8 @@ public class TestPlanManagementService {
} }
private List<TestPlanResponse> getTableList(TestPlanTableRequest request) { private List<TestPlanResponse> getTableList(TestPlanTableRequest request) {
List<TestPlanResponse> testPlanResponses = extTestPlanMapper.selectByConditions(request, null); List<TestPlanResponse> testPlanResponses = extTestPlanMapper.selectByConditions(request);
handChildren(testPlanResponses, request.getProjectId()); handChildren(testPlanResponses,request.getProjectId());
return testPlanResponses; return testPlanResponses;
} }
@ -73,20 +74,20 @@ public class TestPlanManagementService {
*/ */
private void handChildren(List<TestPlanResponse> testPlanResponses, String projectId) { private void handChildren(List<TestPlanResponse> testPlanResponses, String projectId) {
List<String> groupIds = testPlanResponses.stream().filter(item -> StringUtils.equals(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)).map(TestPlanResponse::getId).toList(); List<String> groupIds = testPlanResponses.stream().filter(item -> StringUtils.equals(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)).map(TestPlanResponse::getId).toList();
TestPlanTableRequest request = new TestPlanTableRequest(); if (CollectionUtils.isNotEmpty(groupIds)) {
request.setProjectId(projectId); List<TestPlanResponse> childrenList = extTestPlanMapper.selectByGroupIds(groupIds);
List<TestPlanResponse> childrenList = extTestPlanMapper.selectByConditions(request, groupIds); Map<String, List<TestPlanResponse>> collect = childrenList.stream().collect(Collectors.groupingBy(TestPlanResponse::getGroupId));
Map<String, List<TestPlanResponse>> collect = childrenList.stream().collect(Collectors.groupingBy(TestPlanResponse::getGroupId)); testPlanResponses.forEach(item -> {
testPlanResponses.forEach(item -> { if (collect.containsKey(item.getId())) {
if (collect.containsKey(item.getId())) { //存在子节点
//存在子节点 List<TestPlanResponse> list = collect.get(item.getId());
List<TestPlanResponse> list = collect.get(item.getId()); testPlanStatisticsService.calculateCaseCount(list);
testPlanStatisticsService.calculateCaseCount(list); item.setChildren(list);
item.setChildren(list); item.setChildrenCount(list.size());
item.setChildrenCount(list.size()); }
} testPlanStatisticsService.calculateCaseCount(List.of(item));
testPlanStatisticsService.calculateCaseCount(List.of(item)); });
}); }
} }
public void checkModuleIsOpen(String resourceId, String resourceType, List<String> moduleMenus) { public void checkModuleIsOpen(String resourceId, String resourceType, List<String> moduleMenus) {
@ -111,6 +112,10 @@ public class TestPlanManagementService {
} }
} }
public List<TestPlanResponse> selectByGroupId(String groupId) {
return extTestPlanMapper.selectByGroupIds(List.of(groupId));
}
/** /**
* 根据项目id检查模块是否开启 * 根据项目id检查模块是否开启

View File

@ -7,6 +7,7 @@ import io.metersphere.plan.constants.TestPlanResourceConfig;
import io.metersphere.plan.domain.*; import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.request.*;
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.mapper.ExtTestPlanMapper; import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.plan.mapper.TestPlanReportMapper; import io.metersphere.plan.mapper.TestPlanReportMapper;
@ -15,6 +16,7 @@ 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;
import io.metersphere.project.utils.NodeSortUtils;
import io.metersphere.sdk.constants.*; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory; import io.metersphere.sdk.util.CommonBeanFactory;
@ -107,6 +109,7 @@ public class TestPlanTests extends BaseTest {
private static final String URL_POST_TEST_PLAN_PAGE = "/test-plan/page"; private static final String URL_POST_TEST_PLAN_PAGE = "/test-plan/page";
private static final String URL_POST_TEST_PLAN_STATISTICS = "/test-plan/statistics"; private static final String URL_POST_TEST_PLAN_STATISTICS = "/test-plan/statistics";
private static final String URL_POST_TEST_PLAN_MODULE_COUNT = "/test-plan/module/count"; private static final String URL_POST_TEST_PLAN_MODULE_COUNT = "/test-plan/module/count";
private static final String URL_GET_TEST_PLAN_LIST_IN_GROUP = "/test-plan/list-in-group/%s";
private static final String URL_POST_TEST_PLAN_ADD = "/test-plan/add"; private static final String URL_POST_TEST_PLAN_ADD = "/test-plan/add";
private static final String URL_POST_TEST_PLAN_SORT = "/test-plan/sort"; private static final String URL_POST_TEST_PLAN_SORT = "/test-plan/sort";
private static final String URL_POST_TEST_PLAN_UPDATE = "/test-plan/update"; private static final String URL_POST_TEST_PLAN_UPDATE = "/test-plan/update";
@ -687,7 +690,16 @@ public class TestPlanTests extends BaseTest {
this.checkTestPlanSortInGroup(groupTestPlanId7); this.checkTestPlanSortInGroup(groupTestPlanId7);
} }
protected void checkTestPlanSortInGroup(String groupTestPlanId7) throws Exception { private List<TestPlanResponse> selectByGroupId(String groupId) throws Exception {
return JSON.parseArray(
JSON.toJSONString(
JSON.parseObject(
this.requestGetWithOkAndReturn(String.format(URL_GET_TEST_PLAN_LIST_IN_GROUP, groupId))
.getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResponse.class);
}
protected void checkTestPlanSortInGroup(String groupId) throws Exception {
/* /*
排序校验用例设计 排序校验用例设计
1.第一个移动到最后一个 1.第一个移动到最后一个
@ -695,13 +707,9 @@ public class TestPlanTests extends BaseTest {
3.第三个移动到第二个 3.第三个移动到第二个
4.修改第一个和第二个之间的pos差小于2将第三个移动到第二个还原为原来的顺序并检查pos有没有初始化 4.修改第一个和第二个之间的pos差小于2将第三个移动到第二个还原为原来的顺序并检查pos有没有初始化
*/ */
List<TestPlanResponse> defaultTestPlanInGroup = this.selectByGroupId(groupId);
TestPlanExample example = new TestPlanExample(); List<TestPlanResponse> lastTestPlanInGroup = defaultTestPlanInGroup;
example.createCriteria().andGroupIdEqualTo(groupTestPlanId7); TestPlanResponse movePlan, targetPlan = null;
example.setOrderByClause("pos asc");
List<TestPlan> defaultTestPlanInGroup = testPlanMapper.selectByExample(example);
List<TestPlan> lastTestPlanInGroup = defaultTestPlanInGroup;
TestPlan movePlan, targetPlan = null;
PosRequest posRequest = null; PosRequest posRequest = null;
TestPlanResourceSortResponse response = null; TestPlanResourceSortResponse response = null;
@ -716,7 +724,7 @@ public class TestPlanTests extends BaseTest {
.getResponse().getContentAsString(), ResultHolder.class).getData()), .getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class); TestPlanResourceSortResponse.class);
//位置校验 //位置校验
List<TestPlan> newTestPlanInGroup = testPlanMapper.selectByExample(example); List<TestPlanResponse> newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1); Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size()); Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) { for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
@ -736,7 +744,7 @@ public class TestPlanTests extends BaseTest {
.getResponse().getContentAsString(), ResultHolder.class).getData()), .getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class); TestPlanResourceSortResponse.class);
//位置校验 //位置校验
newTestPlanInGroup = testPlanMapper.selectByExample(example); newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1); Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size()); Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) { for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
@ -755,7 +763,7 @@ public class TestPlanTests extends BaseTest {
.getResponse().getContentAsString(), ResultHolder.class).getData()), .getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class); TestPlanResourceSortResponse.class);
//位置校验 //位置校验
newTestPlanInGroup = testPlanMapper.selectByExample(example); newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1); Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size()); Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) { for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
@ -772,8 +780,10 @@ public class TestPlanTests extends BaseTest {
// 修改第一个和第二个之间的pos差为2(拖拽的最小pos差将第三个移动到第二个换回来然后检查pos有没有变化 // 修改第一个和第二个之间的pos差为2(拖拽的最小pos差将第三个移动到第二个换回来然后检查pos有没有变化
movePlan = lastTestPlanInGroup.get(2); movePlan = lastTestPlanInGroup.get(2);
targetPlan = lastTestPlanInGroup.get(1); targetPlan = lastTestPlanInGroup.get(1);
targetPlan.setPos(lastTestPlanInGroup.get(0).getPos() + 2); TestPlan updatePlan = new TestPlan();
testPlanMapper.updateByPrimaryKey(targetPlan); updatePlan.setId(targetPlan.getId());
updatePlan.setPos(lastTestPlanInGroup.get(0).getPos() + 2);
testPlanMapper.updateByPrimaryKeySelective(updatePlan);
posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.BEFORE.name()); posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.BEFORE.name());
response = JSON.parseObject( response = JSON.parseObject(
@ -783,13 +793,13 @@ public class TestPlanTests extends BaseTest {
.getResponse().getContentAsString(), ResultHolder.class).getData()), .getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class); TestPlanResourceSortResponse.class);
//位置校验 //位置校验
newTestPlanInGroup = testPlanMapper.selectByExample(example); newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1); Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size()); Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
long lastPos = 0; long lastPos = 0;
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) { for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), defaultTestPlanInGroup.get(newListIndex).getId()); Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), defaultTestPlanInGroup.get(newListIndex).getId());
Assertions.assertTrue(newTestPlanInGroup.get(newListIndex).getPos() > (lastPos + 1)); Assertions.assertTrue(newTestPlanInGroup.get(newListIndex).getPos() == (lastPos + NodeSortUtils.DEFAULT_NODE_INTERVAL_POS));
lastPos = newTestPlanInGroup.get(newListIndex).getPos(); lastPos = newTestPlanInGroup.get(newListIndex).getPos();
} }
} }
@ -847,11 +857,13 @@ public class TestPlanTests extends BaseTest {
dataRequest.getCurrent(), dataRequest.getCurrent(),
dataRequest.getPageSize(), dataRequest.getPageSize(),
1010); 1010);
//只查询组
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn( testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, groupRequest).getResponse().getContentAsString(StandardCharsets.UTF_8), URL_POST_TEST_PLAN_PAGE, groupRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
dataRequest.getCurrent(), dataRequest.getCurrent(),
dataRequest.getPageSize(), dataRequest.getPageSize(),
2); 2);
//只查询计划
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn( testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, onlyPlanRequest).getResponse().getContentAsString(StandardCharsets.UTF_8), URL_POST_TEST_PLAN_PAGE, onlyPlanRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
dataRequest.getCurrent(), dataRequest.getCurrent(),