fix(测试计划): 修复批量复制会突破测试计划组限制的问题

--bug=1042708 --user=宋天阳 【测试计划】计划实际起止时间为空 https://www.tapd.cn/55049933/s/1533854
This commit is contained in:
Jianguo-Genius 2024-06-21 18:28:11 +08:00 committed by Craftsman
parent 1319927df9
commit fa4539be74
5 changed files with 43 additions and 35 deletions

View File

@ -9,6 +9,7 @@ import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.project.utils.NodeSortUtils; import io.metersphere.project.utils.NodeSortUtils;
import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
@ -56,7 +57,7 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
for (TestPlan testPlan : testPlanList) { for (TestPlan testPlan : testPlanList) {
// 已归档的测试计划无法操作 // 已归档的测试计划无法操作
if (StringUtils.equalsIgnoreCase(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) { if (StringUtils.equalsIgnoreCase(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
continue; throw new MSException(Translator.get("test_plan.is.archived"));
} }
if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) { if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
// 测试计划组下的测试计划不单独处理 如果勾选了他的测试计划组会在下面进行逻辑补足 // 测试计划组下的测试计划不单独处理 如果勾选了他的测试计划组会在下面进行逻辑补足
@ -124,6 +125,10 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
public long batchCopy(List<TestPlan> copyPlanList, String targetId, String targetType, String userId) { public long batchCopy(List<TestPlan> copyPlanList, String targetId, String targetType, String userId) {
long copyCount = 0; long copyCount = 0;
long operatorTime = System.currentTimeMillis(); long operatorTime = System.currentTimeMillis();
//如果目标ID是测试计划组 需要进行容量校验
if (!StringUtils.equalsIgnoreCase(targetType, ModuleConstants.NODE_TYPE_DEFAULT)) {
testPlanGroupService.validateGroupCapacity(targetId, copyPlanList.size());
}
/* /*
此处不选择批量操作原因有两点 此处不选择批量操作原因有两点
1 测试计划内或者测试计划组内数据量不可控选择批量操作时更容易出现数据太多不走索引数据太多内存溢出等问题不批量操作可以减少这些问题出现的概率代价是速度会变慢 1 测试计划内或者测试计划组内数据量不可控选择批量操作时更容易出现数据太多不走索引数据太多内存溢出等问题不批量操作可以减少这些问题出现的概率代价是速度会变慢

View File

@ -223,7 +223,7 @@ public class TestPlanExecuteService {
genReportRequest.setTestPlanId(executionQueue.getSourceID()); genReportRequest.setTestPlanId(executionQueue.getSourceID());
genReportRequest.setProjectId(testPlan.getProjectId()); genReportRequest.setProjectId(testPlan.getProjectId());
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) { if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
//更改测试计划组的状态
List<TestPlan> children = testPlanService.selectNotArchivedChildren(testPlan.getId()); List<TestPlan> children = testPlanService.selectNotArchivedChildren(testPlan.getId());
// 预生成计划组报告 // 预生成计划组报告
Map<String, String> reportMap = testPlanReportService.genReportByExecution(executionQueue.getPrepareReportId(), genReportRequest, executionQueue.getCreateUser()); Map<String, String> reportMap = testPlanReportService.genReportByExecution(executionQueue.getPrepareReportId(), genReportRequest, executionQueue.getCreateUser());
@ -251,12 +251,12 @@ public class TestPlanExecuteService {
} }
LogUtils.info("计划组的执行节点 --- 队列ID[{}],队列类型[{}],父队列ID[{}],父队列类型[{}]", queueId, queueType, executionQueue.getParentQueueId(), executionQueue.getParentQueueType()); LogUtils.info("计划组的执行节点 --- 队列ID[{}],队列类型[{}],父队列ID[{}],父队列类型[{}]", queueId, queueType, executionQueue.getParentQueueId(), executionQueue.getParentQueueType());
testPlanService.setExecuteConfig(executionQueue.getSourceID(), executionQueue.getPrepareReportId());
if (CollectionUtils.isEmpty(childrenQueue)) { if (CollectionUtils.isEmpty(childrenQueue)) {
//本次的测试计划组执行完成 //本次的测试计划组执行完成
this.testPlanGroupQueueFinish(executionQueue.getQueueId(), executionQueue.getQueueType()); this.testPlanGroupQueueFinish(executionQueue.getQueueId(), executionQueue.getQueueType());
} else { } else {
//更改测试计划组的状态
testPlanService.setExecuteConfig(executionQueue.getSourceID(), executionQueue.getPrepareReportId());
testPlanExecuteSupportService.setRedisForList(testPlanExecuteSupportService.genQueueKey(queueId, queueType), childrenQueue.stream().map(JSON::toJSONString).toList()); testPlanExecuteSupportService.setRedisForList(testPlanExecuteSupportService.genQueueKey(queueId, queueType), childrenQueue.stream().map(JSON::toJSONString).toList());
if (StringUtils.equalsIgnoreCase(executionQueue.getRunMode(), ApiBatchRunMode.SERIAL.name())) { if (StringUtils.equalsIgnoreCase(executionQueue.getRunMode(), ApiBatchRunMode.SERIAL.name())) {

View File

@ -27,6 +27,8 @@ public class TestPlanGroupService extends TestPlanSortService {
@Resource @Resource
private ExtTestPlanMapper extTestPlanMapper; private ExtTestPlanMapper extTestPlanMapper;
private static final int MAX_CHILDREN_COUNT = 20;
@Override @Override
public long getNextOrder(String groupId) { public long getNextOrder(String groupId) {
long maxPos = extTestPlanMapper.selectMaxPosByGroupId(groupId); long maxPos = extTestPlanMapper.selectMaxPosByGroupId(groupId);
@ -90,4 +92,24 @@ public class TestPlanGroupService extends TestPlanSortService {
throw new MSException(Translator.get("test_plan.drag.position.error")); throw new MSException(Translator.get("test_plan.drag.position.error"));
} }
} }
public void validateGroupCapacity(String groupId, int size) {
if (!StringUtils.equals(groupId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
// 判断测试计划组是否存在
TestPlan groupPlan = testPlanMapper.selectByPrimaryKey(groupId);
if (StringUtils.equalsIgnoreCase(groupPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
throw new MSException(Translator.get("test_plan.group.error"));
}
//判断并未归档
if (StringUtils.equalsIgnoreCase(groupPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
throw new MSException(Translator.get("test_plan.group.error"));
}
//判断测试计划组下的测试计划数量是否超过20
TestPlanExample example = new TestPlanExample();
example.createCriteria().andGroupIdEqualTo(groupId);
if (testPlanMapper.countByExample(example) + size > 20) {
throw new MSException(Translator.getWithArgs("test_plan.group.children.max", MAX_CHILDREN_COUNT));
}
}
}
} }

View File

@ -103,7 +103,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
private TestPlanApiScenarioMapper testPlanApiScenarioMapper; private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
private static final int MAX_TAG_SIZE = 10; private static final int MAX_TAG_SIZE = 10;
private static final int MAX_CHILDREN_COUNT = 20;
@Autowired @Autowired
private TestPlanReportService testPlanReportService; private TestPlanReportService testPlanReportService;
@ -142,7 +142,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
TestPlan createTestPlan = new TestPlan(); TestPlan createTestPlan = new TestPlan();
BeanUtils.copyBean(createTestPlan, createOrCopyRequest); BeanUtils.copyBean(createTestPlan, createOrCopyRequest);
validateTestPlanGroup(createTestPlan.getGroupId(), 1); testPlanGroupService.validateGroupCapacity(createTestPlan.getGroupId(), 1);
if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) { if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
// 判断测试计划组是否存在 // 判断测试计划组是否存在
@ -171,33 +171,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
return createTestPlan; return createTestPlan;
} }
/**
* 校验测试计划组
*
* @param groupId 测试计划组Id
* @param preAddCount 准备添加的数量
*/
private void validateTestPlanGroup(String groupId, int preAddCount) {
if (!StringUtils.equals(groupId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
// 判断测试计划组是否存在
TestPlan groupPlan = testPlanMapper.selectByPrimaryKey(groupId);
if (StringUtils.equalsIgnoreCase(groupPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
throw new MSException(Translator.get("test_plan.group.error"));
}
//判断并未归档
if (StringUtils.equalsIgnoreCase(groupPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
throw new MSException(Translator.get("test_plan.group.error"));
}
//判断测试计划组下的测试计划数量是否超过20
TestPlanExample example = new TestPlanExample();
example.createCriteria().andGroupIdEqualTo(groupId);
if (testPlanMapper.countByExample(example) + preAddCount > 20) {
throw new MSException(Translator.getWithArgs("test_plan.group.children.max", MAX_CHILDREN_COUNT));
}
}
}
//校验测试计划 //校验测试计划
private void initTestPlanPos(TestPlan createTestPlan) { private void initTestPlanPos(TestPlan createTestPlan) {
if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) { if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
@ -658,7 +631,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
moveTestPlanList = moveTestPlanList.stream().filter( moveTestPlanList = moveTestPlanList.stream().filter(
item -> StringUtils.equalsIgnoreCase(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_PLAN) && !StringUtils.equalsIgnoreCase(item.getGroupId(), request.getTargetId()) item -> StringUtils.equalsIgnoreCase(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_PLAN) && !StringUtils.equalsIgnoreCase(item.getGroupId(), request.getTargetId())
).collect(Collectors.toList()); ).collect(Collectors.toList());
this.validateTestPlanGroup(request.getTargetId(), moveTestPlanList.size()); testPlanGroupService.validateGroupCapacity(request.getTargetId(), moveTestPlanList.size());
moveCount = testPlanBatchOperationService.batchMoveGroup(moveTestPlanList, request.getTargetId(), userId); moveCount = testPlanBatchOperationService.batchMoveGroup(moveTestPlanList, request.getTargetId(), userId);
} else { } else {
moveCount = testPlanBatchOperationService.batchMoveModule(moveTestPlanList, request.getTargetId(), userId); moveCount = testPlanBatchOperationService.batchMoveModule(moveTestPlanList, request.getTargetId(), userId);

View File

@ -226,7 +226,6 @@ public class TestPlanTests extends BaseTest {
testPlanTableRequest.setProjectId(DEFAULT_PROJECT_ID); testPlanTableRequest.setProjectId(DEFAULT_PROJECT_ID);
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ, URL_POST_TEST_PLAN_PAGE, testPlanTableRequest);
} }
@Test @Test
@Order(2) @Order(2)
public void addModuleTest() throws Exception { public void addModuleTest() throws Exception {
@ -1539,6 +1538,15 @@ public class TestPlanTests extends BaseTest {
childs = childs.stream().filter(item -> !StringUtils.equalsIgnoreCase(item.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)).collect(Collectors.toList()); childs = childs.stream().filter(item -> !StringUtils.equalsIgnoreCase(item.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)).collect(Collectors.toList());
Assertions.assertTrue(copyChild.size() == childs.size()); Assertions.assertTrue(copyChild.size() == childs.size());
//赋值超过20个数据到测试计划组
request = new TestPlanBatchRequest();
request.setProjectId(project.getId());
request.setTargetId(groupTestPlanId7);
request.setMoveType("GROUP");
request.setSelectIds(Collections.singletonList(simpleTestPlan.getId()));
this.requestPost(URL_TEST_PLAN_BATCH_COPY, request).andExpect(status().is5xxServerError());
//删除 //删除
this.requestGet(String.format(URL_GET_TEST_PLAN_DELETE, copyGroup.getId())).andExpect(status().isOk()); this.requestGet(String.format(URL_GET_TEST_PLAN_DELETE, copyGroup.getId())).andExpect(status().isOk());