fix(测试计划): 复制计划或计划组暂未复制定时任务
--bug=1042641 --user=宋昌昌 【测试计划】计划列表-操作-复制计划成功-首次进入计划详情-测试规划展示为空 https://www.tapd.cn/55049933/s/1532263
This commit is contained in:
parent
f1fc2f302f
commit
d71ce02d4c
|
@ -47,6 +47,8 @@ public class TestPlanController {
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanService testPlanService;
|
private TestPlanService testPlanService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private TestPlanScheduleService testPlanScheduleService;
|
||||||
|
@Resource
|
||||||
private TestPlanManagementService testPlanManagementService;
|
private TestPlanManagementService testPlanManagementService;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanStatisticsService testPlanStatisticsService;
|
private TestPlanStatisticsService testPlanStatisticsService;
|
||||||
|
@ -245,7 +247,7 @@ public class TestPlanController {
|
||||||
@CheckOwner(resourceId = "#request.getResourceId()", resourceType = "test_plan")
|
@CheckOwner(resourceId = "#request.getResourceId()", resourceType = "test_plan")
|
||||||
public String scheduleConfig(@Validated @RequestBody BaseScheduleConfigRequest request) {
|
public String scheduleConfig(@Validated @RequestBody BaseScheduleConfigRequest request) {
|
||||||
testPlanManagementService.checkModuleIsOpen(request.getResourceId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
testPlanManagementService.checkModuleIsOpen(request.getResourceId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
||||||
return testPlanService.scheduleConfig(request, SessionUtils.getUserId());
|
return testPlanScheduleService.scheduleConfig(request, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/schedule-config-delete/{testPlanId}")
|
@GetMapping(value = "/schedule-config-delete/{testPlanId}")
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.plan.service;
|
||||||
|
|
||||||
import io.metersphere.plan.domain.*;
|
import io.metersphere.plan.domain.*;
|
||||||
import io.metersphere.plan.dto.response.TestPlanResponse;
|
import io.metersphere.plan.dto.response.TestPlanResponse;
|
||||||
|
import io.metersphere.plan.job.TestPlanScheduleJob;
|
||||||
import io.metersphere.plan.mapper.ExtTestPlanMapper;
|
import io.metersphere.plan.mapper.ExtTestPlanMapper;
|
||||||
import io.metersphere.plan.mapper.TestPlanCollectionMapper;
|
import io.metersphere.plan.mapper.TestPlanCollectionMapper;
|
||||||
import io.metersphere.plan.mapper.TestPlanConfigMapper;
|
import io.metersphere.plan.mapper.TestPlanConfigMapper;
|
||||||
|
@ -12,7 +13,11 @@ 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;
|
||||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.domain.Schedule;
|
||||||
|
import io.metersphere.system.dto.request.schedule.BaseScheduleConfigRequest;
|
||||||
|
import io.metersphere.system.schedule.ScheduleService;
|
||||||
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;
|
||||||
|
@ -33,7 +38,10 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
|
||||||
private ExtTestPlanMapper extTestPlanMapper;
|
private ExtTestPlanMapper extTestPlanMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanMapper testPlanMapper;
|
private TestPlanMapper testPlanMapper;
|
||||||
|
@Resource
|
||||||
|
private ScheduleService scheduleService;
|
||||||
|
@Resource
|
||||||
|
private TestPlanScheduleService testPlanScheduleService;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanGroupService testPlanGroupService;
|
private TestPlanGroupService testPlanGroupService;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -237,6 +245,10 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
|
||||||
beansOfType.forEach((k, v) -> {
|
beansOfType.forEach((k, v) -> {
|
||||||
v.copyResource(originalTestPlan.getId(), testPlan.getId(), oldCollectionIdToNewCollectionId, operator, operatorTime);
|
v.copyResource(originalTestPlan.getId(), testPlan.getId(), oldCollectionIdToNewCollectionId, operator, operatorTime);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 复制计划-定时任务信息
|
||||||
|
copySchedule(originalTestPlan.getId(), testPlan.getId(), operator);
|
||||||
|
|
||||||
return testPlan;
|
return testPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,9 +292,32 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
|
||||||
for (TestPlan child : childList) {
|
for (TestPlan child : childList) {
|
||||||
copyPlan(child, testPlanGroup.getId(), TestPlanConstants.TEST_PLAN_TYPE_GROUP, operatorTime, operator);
|
copyPlan(child, testPlanGroup.getId(), TestPlanConstants.TEST_PLAN_TYPE_GROUP, operatorTime, operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 复制计划组-定时任务信息
|
||||||
|
copySchedule(originalGroup.getId(), testPlanGroup.getId(), operator);
|
||||||
return testPlanGroup;
|
return testPlanGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制 计划/计划组 定时任务
|
||||||
|
* @param resourceId 来源ID
|
||||||
|
* @param targetId 目标ID
|
||||||
|
* @param operator 操作人
|
||||||
|
*/
|
||||||
|
private void copySchedule(String resourceId, String targetId, String operator) {
|
||||||
|
Schedule originalSchedule = scheduleService.getScheduleByResource(resourceId, TestPlanScheduleJob.class.getName());
|
||||||
|
if (originalSchedule != null) {
|
||||||
|
// 来源的 "计划/计划组" 存在定时任务即复制, 无论开启或关闭
|
||||||
|
BaseScheduleConfigRequest scheduleRequest = new BaseScheduleConfigRequest();
|
||||||
|
scheduleRequest.setEnable(originalSchedule.getEnable());
|
||||||
|
scheduleRequest.setCron(originalSchedule.getValue());
|
||||||
|
// noinspection unchecked
|
||||||
|
scheduleRequest.setRunConfig(JSON.parseMap(originalSchedule.getConfig()));
|
||||||
|
scheduleRequest.setResourceId(targetId);
|
||||||
|
testPlanScheduleService.scheduleConfig(scheduleRequest, operator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String getCopyName(String name, long oldNum, long newNum) {
|
private String getCopyName(String name, long oldNum, long newNum) {
|
||||||
if (!StringUtils.startsWith(name, "copy_")) {
|
if (!StringUtils.startsWith(name, "copy_")) {
|
||||||
name = "copy_" + name;
|
name = "copy_" + name;
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package io.metersphere.plan.service;
|
||||||
|
|
||||||
|
import io.metersphere.plan.domain.TestPlan;
|
||||||
|
import io.metersphere.plan.domain.TestPlanExample;
|
||||||
|
import io.metersphere.plan.job.TestPlanScheduleJob;
|
||||||
|
import io.metersphere.plan.mapper.TestPlanMapper;
|
||||||
|
import io.metersphere.sdk.constants.ScheduleResourceType;
|
||||||
|
import io.metersphere.sdk.constants.TestPlanConstants;
|
||||||
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
import io.metersphere.sdk.util.JSON;
|
||||||
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.dto.request.ScheduleConfig;
|
||||||
|
import io.metersphere.system.dto.request.schedule.BaseScheduleConfigRequest;
|
||||||
|
import io.metersphere.system.schedule.ScheduleService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class TestPlanScheduleService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TestPlanMapper testPlanMapper;
|
||||||
|
@Resource
|
||||||
|
private ScheduleService scheduleService;
|
||||||
|
|
||||||
|
public String scheduleConfig(BaseScheduleConfigRequest request, String operator) {
|
||||||
|
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getResourceId());
|
||||||
|
if (testPlan == null) {
|
||||||
|
throw new MSException(Translator.get("test_plan.not.exist"));
|
||||||
|
}
|
||||||
|
ScheduleConfig scheduleConfig = ScheduleConfig.builder()
|
||||||
|
.resourceId(testPlan.getId())
|
||||||
|
.key(testPlan.getId())
|
||||||
|
.projectId(testPlan.getProjectId())
|
||||||
|
.name(testPlan.getName())
|
||||||
|
.enable(request.isEnable())
|
||||||
|
.cron(request.getCron())
|
||||||
|
.resourceType(ScheduleResourceType.TEST_PLAN.name())
|
||||||
|
.config(JSON.toJSONString(request.getRunConfig()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
if (request.isEnable() && StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
|
||||||
|
//配置开启的测试计划组定时任务,要将组下的所有测试计划定时任务都关闭掉
|
||||||
|
TestPlanExample example = new TestPlanExample();
|
||||||
|
example.createCriteria().andGroupIdEqualTo(testPlan.getId()).andStatusNotEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
|
||||||
|
example.setOrderByClause("pos asc");
|
||||||
|
List<TestPlan> children = testPlanMapper.selectByExample(example);
|
||||||
|
for (TestPlan child : children) {
|
||||||
|
scheduleService.updateIfExist(child.getId(), false, TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
||||||
|
TestPlanScheduleJob.getTriggerKey(testPlan.getId()),
|
||||||
|
TestPlanScheduleJob.class, operator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scheduleService.scheduleConfig(
|
||||||
|
scheduleConfig,
|
||||||
|
TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
||||||
|
TestPlanScheduleJob.getTriggerKey(testPlan.getId()),
|
||||||
|
TestPlanScheduleJob.class,
|
||||||
|
operator);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,14 +13,15 @@ import io.metersphere.project.request.ProjectApplicationRequest;
|
||||||
import io.metersphere.project.service.ProjectApplicationService;
|
import io.metersphere.project.service.ProjectApplicationService;
|
||||||
import io.metersphere.sdk.constants.*;
|
import io.metersphere.sdk.constants.*;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.*;
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
|
import io.metersphere.sdk.util.SubListUtils;
|
||||||
|
import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.domain.ScheduleExample;
|
import io.metersphere.system.domain.ScheduleExample;
|
||||||
import io.metersphere.system.domain.TestPlanModule;
|
import io.metersphere.system.domain.TestPlanModule;
|
||||||
import io.metersphere.system.domain.TestPlanModuleExample;
|
import io.metersphere.system.domain.TestPlanModuleExample;
|
||||||
import io.metersphere.system.domain.User;
|
import io.metersphere.system.domain.User;
|
||||||
import io.metersphere.system.dto.LogInsertModule;
|
import io.metersphere.system.dto.LogInsertModule;
|
||||||
import io.metersphere.system.dto.request.ScheduleConfig;
|
|
||||||
import io.metersphere.system.dto.request.schedule.BaseScheduleConfigRequest;
|
|
||||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
import io.metersphere.system.dto.sdk.request.PosRequest;
|
import io.metersphere.system.dto.sdk.request.PosRequest;
|
||||||
import io.metersphere.system.log.constants.OperationLogType;
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
|
@ -884,40 +885,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
||||||
return new TestPlanOperationResponse(1);
|
return new TestPlanOperationResponse(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String scheduleConfig(BaseScheduleConfigRequest request, String operator) {
|
|
||||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getResourceId());
|
|
||||||
if (testPlan == null) {
|
|
||||||
throw new MSException(Translator.get("test_plan.not.exist"));
|
|
||||||
}
|
|
||||||
ScheduleConfig scheduleConfig = ScheduleConfig.builder()
|
|
||||||
.resourceId(testPlan.getId())
|
|
||||||
.key(testPlan.getId())
|
|
||||||
.projectId(testPlan.getProjectId())
|
|
||||||
.name(testPlan.getName())
|
|
||||||
.enable(request.isEnable())
|
|
||||||
.cron(request.getCron())
|
|
||||||
.resourceType(ScheduleResourceType.TEST_PLAN.name())
|
|
||||||
.config(JSON.toJSONString(request.getRunConfig()))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
if (request.isEnable() && StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
|
|
||||||
//配置开启的测试计划组定时任务,要将组下的所有测试计划定时任务都关闭掉
|
|
||||||
List<TestPlan> children = this.selectNotArchivedChildren(testPlan.getId());
|
|
||||||
for (TestPlan child : children) {
|
|
||||||
scheduleService.updateIfExist(child.getId(), false, TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
|
||||||
TestPlanScheduleJob.getTriggerKey(testPlan.getId()),
|
|
||||||
TestPlanScheduleJob.class, operator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return scheduleService.scheduleConfig(
|
|
||||||
scheduleConfig,
|
|
||||||
TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
|
||||||
TestPlanScheduleJob.getTriggerKey(testPlan.getId()),
|
|
||||||
TestPlanScheduleJob.class,
|
|
||||||
operator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteScheduleConfig(String testPlanId) {
|
public void deleteScheduleConfig(String testPlanId) {
|
||||||
scheduleService.deleteByResourceId(testPlanId, TestPlanScheduleJob.getJobKey(testPlanId), TestPlanScheduleJob.getTriggerKey(testPlanId));
|
scheduleService.deleteByResourceId(testPlanId, TestPlanScheduleJob.getJobKey(testPlanId), TestPlanScheduleJob.getTriggerKey(testPlanId));
|
||||||
|
|
||||||
|
|
|
@ -2182,24 +2182,26 @@ public class TestPlanTests extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
@Order(303)
|
@Order(303)
|
||||||
public void testCopy() throws Exception {
|
public void testCopy() throws Exception {
|
||||||
//1. 已归档的不能再归档计划 无用例
|
// 1. 已归档的不能再归档计划 无用例
|
||||||
requestGet(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_1")).andExpect(status().is5xxServerError());
|
requestGet(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_1")).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
|
||||||
//2.计划 有用例
|
// 2.计划 有用例
|
||||||
MvcResult mvcResult1 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_4"));
|
MvcResult mvcResult1 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_4"));
|
||||||
String returnStr1 = mvcResult1.getResponse().getContentAsString();
|
String returnStr1 = mvcResult1.getResponse().getContentAsString();
|
||||||
ResultHolder holder1 = JSON.parseObject(returnStr1, ResultHolder.class);
|
ResultHolder holder1 = JSON.parseObject(returnStr1, ResultHolder.class);
|
||||||
String returnId1 = holder1.getData().toString();
|
String returnId1 = holder1.getData().toString();
|
||||||
Assertions.assertNotNull(returnId1);
|
Assertions.assertNotNull(returnId1);
|
||||||
|
|
||||||
//3.计划组 无计划
|
// 3.计划组 无计划
|
||||||
MvcResult mvcResult2 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_2"));
|
MvcResult mvcResult2 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_2"));
|
||||||
String returnStr2 = mvcResult2.getResponse().getContentAsString();
|
String returnStr2 = mvcResult2.getResponse().getContentAsString();
|
||||||
ResultHolder holder2 = JSON.parseObject(returnStr2, ResultHolder.class);
|
ResultHolder holder2 = JSON.parseObject(returnStr2, ResultHolder.class);
|
||||||
String returnId2 = holder2.getData().toString();
|
String returnId2 = holder2.getData().toString();
|
||||||
Assertions.assertNotNull(returnId2);
|
Assertions.assertNotNull(returnId2);
|
||||||
|
|
||||||
|
// 4.计划组 有子计划
|
||||||
|
this.requestGetWithOk(String.format(URL_TEST_PLAN_COPY, "oasis_test_plan_id_1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -20,8 +20,15 @@ VALUES ('wx_test_plan_id_1', 5000, 'songtianyang-fix-wx', 'NONE', '1', '测试
|
||||||
'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000,
|
'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000,
|
||||||
1714980158000, '11'),
|
1714980158000, '11'),
|
||||||
('wx_test_plan_id_7', 30000, 'songtianyang-fix-wx', 'NONE', '1', '测试组4下计划', 'COMPLETED', 'TEST_PLAN', NULL,
|
('wx_test_plan_id_7', 30000, 'songtianyang-fix-wx', 'NONE', '1', '测试组4下计划', 'COMPLETED', 'TEST_PLAN', NULL,
|
||||||
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');
|
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
|
||||||
|
('oasis_test_plan_id_1', 30000, 'songtianyang-fix-wx', 'NONE', '1', '计划组-复制', 'COMPLETED', 'GROUP', NULL,
|
||||||
|
1714980158000, 'admin', 1714980158000, 'admin', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
|
||||||
|
('oasis_test_plan_id_2', 30000, 'songtianyang-fix-wx', 'oasis_test_plan_id_1', '1', '计划-复制', 'COMPLETED', 'TEST_PLAN', NULL,
|
||||||
|
1714980158000, 'admin', 1714980158000, 'admin', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');
|
||||||
|
|
||||||
|
-- 定时任务(复制)
|
||||||
|
INSERT INTO `schedule` (`id`, `key`, `type`, `value`, `job`, `resource_type`, `enable`, `resource_id`, `create_user`, `create_time`, `update_time`, `project_id`, `name`, `config`) VALUE
|
||||||
|
('schedule-id-oasis', 'oasis_test_plan_id_2', 'CRON', '0 0 0/6 * * ?', 'io.metersphere.plan.job.TestPlanScheduleJob', 'TEST_PLAN', true, 'oasis_test_plan_id_2', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'songtianyang-fix-wx', '计划-复制', '{"runMode":"SERIAL"}');
|
||||||
|
|
||||||
INSERT INTO `test_plan_functional_case`(`id`, `test_plan_id`, `functional_case_id`, `create_time`, `create_user`, `execute_user`, `last_exec_time`, `last_exec_result`, `pos`, `test_plan_collection_id`) VALUES
|
INSERT INTO `test_plan_functional_case`(`id`, `test_plan_id`, `functional_case_id`, `create_time`, `create_user`, `execute_user`, `last_exec_time`, `last_exec_result`, `pos`, `test_plan_collection_id`) VALUES
|
||||||
('wx_tpfc_1', 'wx_test_plan_id_4', 'wx_fc_1', 1714980158000, 'admin', NULL, NULL, NULL, 1, '123'),
|
('wx_tpfc_1', 'wx_test_plan_id_4', 'wx_fc_1', 1714980158000, 'admin', NULL, NULL, NULL, 1, '123'),
|
||||||
|
|
Loading…
Reference in New Issue