feat(测试计划): 批量移动和复 制功能开发

This commit is contained in:
Jianguo-Genius 2024-06-04 19:03:50 +08:00 committed by Craftsman
parent 99328a50e5
commit 74c44e8459
29 changed files with 607 additions and 326 deletions

View File

@ -5,6 +5,7 @@ test_plan.id.not_blank=测试计划id不能为空
test_plan.project_id.length_range=测试计划所属项目id长度过长
test_plan.project_id.not_blank=测试计划所属项目id不能为空
test_plan.module_id.not_blank=测试计划模块ID不能为空
test_plan.target_id.not_blank=目标ID不能为空
test_plan.parent_id.length_range=测试计划父id长度过长
test_plan.parent_id.not_blank=测试计划父id不能为空
test_plan.name.length_range=测试计划名称长度过长
@ -109,6 +110,7 @@ test_plan.report_id.not_blank=测试计划报告ID不能为空
test_plan.report.share_id.not_blank=测试计划报告分享ID不能为空
no_plan_to_archive=没有可归档的计划/计划组
test_plan.is.archived=测试计划已归档
test_plan.cannot.archived=测试计划不符合归档操作条件
test_plan_module_already_exists=同名模块已存在
test_plan_report_name_length_range=报告名称长度过长
test_plan_allocation_type_param_error=测试集所属分类参数错误

View File

@ -5,6 +5,7 @@ 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.not_blank=Test plan project id cannot be empty
test_plan.module_id.not_blank=Test plan module id cannot be empty
test_plan.target_id.not_blank=Target id cannot be empty
test_plan.parent_id.length_range=Test plan parent id length too long
test_plan.parent_id.not_blank=Test plan parent id cannot be empty
test_plan.name.length_range=Test plan name length too long
@ -110,6 +111,7 @@ test_plan.report_id.not_blank=The test plan report ID cannot be empty
test_plan.report.share_id.not_blank=The test plan report share ID cannot be empty
no_plan_to_archive=No plans/plan groups to archive
test_plan.is.archived=Test plan has been archived
test_plan.cannot.archived=Test plan cannot be archived
test_plan_module_already_exists=The module with the same name already exists
test_plan_report_name_length_range=The report name is too long
test_plan_allocation_type_param_error=The parameter of the allocation type is not correct

View File

@ -5,6 +5,7 @@ test_plan.id.not_blank=测试计划id不能为空
test_plan.project_id.length_range=测试计划所属项目id长度过长
test_plan.project_id.not_blank=测试计划所属项目id不能为空
test_plan.module_id.not_blank=测试计划模块ID不能为空
test_plan.target_id.not_blank=目标ID不能为空
test_plan.parent_id.length_range=测试计划父id长度过长
test_plan.parent_id.not_blank=测试计划父id不能为空
test_plan.name.length_range=测试计划名称长度过长
@ -110,6 +111,7 @@ test_plan.report_id.not_blank=测试计划报告ID不能为空
test_plan.report.share_id.not_blank=测试计划报告分享ID不能为空
no_plan_to_archive=没有可归档的计划/计划组
test_plan.is.archived=测试计划已归档
test_plan.cannot.archived=测试计划不符合归档操作条件
test_plan_module_already_exists=同名模块已存在
test_plan_report_name_length_range=报告名称长度过长
test_plan_allocation_type_param_error=测试集所属分类参数错误

View File

@ -110,6 +110,7 @@ test_plan.report_id.not_blank=測試計劃報告ID不能爲空
test_plan.report.share_id.not_blank=測試計劃報告分享ID不能爲空
no_plan_to_archive=沒有可歸檔的計劃/計劃組
test_plan.is.archived=測試計劃已歸檔
test_plan.cannot.archived=測試計劃不符合歸檔操作條件
test_plan_module_already_exists=同名模塊已存在
test_plan_report_name_length_range=报告名称长度过长
test_plan_allocation_type_param_error=測試集所屬分類參數錯誤

View File

@ -4,7 +4,7 @@ import io.metersphere.plan.constants.TestPlanResourceConfig;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
import io.metersphere.plan.dto.response.TestPlanResourceSortResponse;
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
import io.metersphere.plan.service.*;
@ -129,14 +129,6 @@ public class TestPlanController {
testPlanService.archived(id, userId);
}
@PostMapping("/copy")
@Operation(summary = "测试计划-复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
@Log(type = OperationLogType.COPY, expression = "#msClass.copyLog(#request)", msClass = TestPlanLogService.class)
public TestPlan copy(@Validated @RequestBody TestPlanCopyRequest request) {
return testPlanService.copy(request, SessionUtils.getUserId());
}
@GetMapping("/{id}")
@Operation(summary = "测试计划-抽屉详情(单个测试计划获取详情用于编辑)")
@ -155,24 +147,38 @@ public class TestPlanController {
testPlanService.batchDelete(request, SessionUtils.getUserId(), "/test-plan/batch-delete", HttpMethodConstants.POST.name());
}
@GetMapping("/copy/{id}")
@Operation(summary = "测试计划-复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#id", resourceType = "test_plan")
public TestPlanOperationResponse copy(@PathVariable String id) {
return new TestPlanOperationResponse(
testPlanService.copy(id, SessionUtils.getUserId())
);
}
@PostMapping("/batch-copy")
@Operation(summary = "测试计划-批量复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchCopy(@Validated @RequestBody TestPlanBatchRequest request) {
public TestPlanOperationResponse TestPlanOperationResponse(@Validated @RequestBody TestPlanBatchRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
testPlanService.filterArchivedIds(request);
testPlanService.batchCopy(request, SessionUtils.getUserId(), "/test-plan/batch-copy", HttpMethodConstants.POST.name());
return new TestPlanOperationResponse(
testPlanService.batchCopy(request, SessionUtils.getUserId(), "/test-plan/batch-copy", HttpMethodConstants.POST.name())
);
}
@PostMapping("/batch-move")
@Operation(summary = "测试计划-批量移动测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchMove(@Validated @RequestBody TestPlanBatchRequest request) {
public TestPlanOperationResponse batchMove(@Validated @RequestBody TestPlanBatchRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
testPlanService.filterArchivedIds(request);
testPlanService.batchMove(request, SessionUtils.getUserId(), "/test-plan/batch-move", HttpMethodConstants.POST.name());
return new TestPlanOperationResponse(
testPlanService.batchMove(request, SessionUtils.getUserId(), "/test-plan/batch-move", HttpMethodConstants.POST.name())
);
}
@PostMapping("/batch-archived")
@ -210,7 +216,7 @@ public class TestPlanController {
@Operation(summary = "测试计划移动(测试计划拖进、拖出到测试计划组、测试计划在测试计划组内的排序")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getMoveId()", resourceType = "test_plan")
public TestPlanResourceSortResponse sortTestPlan(@Validated @RequestBody PosRequest request) {
public TestPlanOperationResponse sortTestPlan(@Validated @RequestBody PosRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getMoveId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
return testPlanService.sortInGroup(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/move", HttpMethodConstants.POST.name()));
}

View File

@ -52,7 +52,7 @@ public class TestPlanFunctionalCaseController {
@Operation(summary = "测试计划功能用例-功能用例拖拽排序")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public TestPlanResourceSortResponse sortNode(@Validated @RequestBody ResourceSortRequest request) {
public TestPlanOperationResponse sortNode(@Validated @RequestBody ResourceSortRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE));
return testPlanFunctionalCaseService.sortNode(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/sort", HttpMethodConstants.POST.name()));
}

View File

@ -20,7 +20,6 @@ public class TestPlanBatchProcessRequest extends TableBatchProcessDTO {
private List<String> moduleIds;
@Schema(description = "类型", allowableValues = {"ALL", "TEST_PLAN", "GROUP"}, requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan.type.not_blank}")
private String type;
private String type = "ALL";
}

View File

@ -1,5 +1,6 @@
package io.metersphere.plan.dto.request;
import io.metersphere.sdk.constants.ModuleConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@ -10,7 +11,10 @@ import lombok.Data;
@Data
public class TestPlanBatchRequest extends TestPlanBatchProcessRequest {
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan.module_id.not_blank}")
private String moduleId;
@Schema(description = "目标ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan.target_id.not_blank}")
private String targetId;
@Schema(description = "移动类型 MODULE / GROUP)", requiredMode = Schema.RequiredMode.REQUIRED)
private String moveType = ModuleConstants.NODE_TYPE_DEFAULT;
}

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TestPlanResourceSortResponse {
@Schema(description = "本次排序的数量")
private long sortNodeNum;
public class TestPlanOperationResponse {
@Schema(description = "处理成功的数量")
private long operationCount;
}

View File

@ -2,6 +2,7 @@ package io.metersphere.plan.mapper;
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
import io.metersphere.plan.domain.TestPlanApiCase;
import io.metersphere.plan.dto.ResourceSelectParam;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
@ -38,4 +39,6 @@ public interface ExtTestPlanApiCaseMapper {
List<String> selectIdByProjectIdAndTestPlanId(@Param("projectId") String projectId, @Param("testPlanId") String testPlanId);
long caseCount(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
List<TestPlanApiCase> selectByTestPlanIdAndNotDeleted(String testPlanId);
}

View File

@ -426,6 +426,13 @@
and t.test_plan_id = #{request.testPlanId}
<include refid="queryApiCaseWhereCondition"/>
</select>
<select id="selectByTestPlanIdAndNotDeleted" resultType="io.metersphere.plan.domain.TestPlanApiCase">
SELECT t.*
FROM test_plan_api_case t
INNER JOIN api_test_case atc ON t.api_case_id = atc.id
WHERE t.test_plan_id = #{0}
AND atc.deleted = false
</select>
<sql id="queryApiCaseWhereCondition">

View File

@ -1,5 +1,6 @@
package io.metersphere.plan.mapper;
import io.metersphere.plan.domain.TestPlanApiScenario;
import io.metersphere.plan.dto.ResourceSelectParam;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.project.dto.DropNode;
@ -23,4 +24,6 @@ public interface ExtTestPlanApiScenarioMapper {
DropNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
List<TestPlanCaseRunResultCount> selectCaseExecResultCount(String testPlanId);
List<TestPlanApiScenario> selectByTestPlanIdAndNotDeleted(String testPlanId);
}

View File

@ -75,4 +75,11 @@
AND api_scenario.deleted = false
group by last_exec_result
</select>
<select id="selectByTestPlanIdAndNotDeleted" resultType="io.metersphere.plan.domain.TestPlanApiScenario">
SELECT t.*
FROM test_plan_api_scenario t
INNER JOIN api_scenario a ON t.api_scenario_id = a.id
WHERE t.test_plan_id = #{0}
AND a.deleted = false
</select>
</mapper>

View File

@ -33,6 +33,8 @@ public interface ExtTestPlanFunctionalCaseMapper {
List<TestPlanCasePageResponse> getCasePage(@Param("request") TestPlanCaseRequest request, @Param("deleted") boolean deleted, @Param("sort") String sort);
List<TestPlanFunctionalCase> selectByTestPlanIdAndNotDeleted(String testPlanId);
List<ProjectOptionDTO> selectRootIdByTestPlanId(@Param("testPlanId") String testPlanId);
List<FunctionalCaseModuleDTO> selectBaseByProjectIdAndTestPlanId(@Param("testPlanId") String testPlanId);

View File

@ -496,6 +496,14 @@
AND functional_case.deleted = false
group by last_exec_result
</select>
<select id="selectByTestPlanIdAndNotDeleted"
resultType="io.metersphere.plan.domain.TestPlanFunctionalCase">
SELECT t.*
from test_plan_functional_case t
INNER JOIN functional_case f ON t.functional_case_id = f.id
WHERE test_plan_id = #{0}
AND f.deleted = false
</select>
<update id="batchUpdate">

View File

@ -33,7 +33,7 @@ public interface ExtTestPlanMapper {
void batchUpdateStatus(@Param("status") String status, @Param("userId") String userId, @Param("updateTime") Long updateTime, @Param("ids") List<String> ids);
void batchMove(@Param("ids") List<String> ids, @Param("moduleId") String moduleId, @Param("userId") String userId, @Param("updateTime") long updateTime);
long batchMove(@Param("ids") List<String> ids, @Param("moduleId") String moduleId, @Param("userId") String userId, @Param("updateTime") long updateTime);
List<TestPlan> getTagsByIds(@Param("ids") List<String> ids);

View File

@ -6,6 +6,7 @@ import io.metersphere.api.service.definition.ApiDefinitionModuleService;
import io.metersphere.api.service.definition.ApiDefinitionService;
import io.metersphere.api.service.definition.ApiTestCaseService;
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
import io.metersphere.plan.domain.TestPlanApiCase;
import io.metersphere.plan.domain.TestPlanApiCaseExample;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
@ -25,9 +26,14 @@ import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.service.UserLoginService;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -57,7 +63,8 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
@Resource
private ApiDefinitionModuleService apiDefinitionModuleService;
private static final String CASE_MODULE_COUNT_ALL = "all";
@Resource
private SqlSessionFactory sqlSessionFactory;
@Override
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
@ -82,6 +89,30 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
return runResultCounts.stream().collect(Collectors.toMap(TestPlanCaseRunResultCount::getResult, TestPlanCaseRunResultCount::getResultCount));
}
@Override
public long copyResource(String originalTestPlanId, String newTestPlanId, String operator, long operatorTime) {
List<TestPlanApiCase> copyList = new ArrayList<>();
extTestPlanApiCaseMapper.selectByTestPlanIdAndNotDeleted(originalTestPlanId).forEach(originalCase -> {
TestPlanApiCase newCase = new TestPlanApiCase();
BeanUtils.copyBean(newCase, originalCase);
newCase.setId(IDGenerator.nextStr());
newCase.setTestPlanId(newTestPlanId);
newCase.setCreateTime(operatorTime);
newCase.setCreateUser(operator);
newCase.setLastExecTime(0L);
newCase.setLastExecResult(null);
newCase.setLastExecReportId(null);
copyList.add(newCase);
});
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanApiCaseMapper batchInsertMapper = sqlSession.getMapper(TestPlanApiCaseMapper.class);
copyList.forEach(item -> batchInsertMapper.insert(item));
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
return copyList.size();
}
@Override
public void refreshPos(String testPlanId) {
// todo

View File

@ -1,14 +1,21 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlanApiScenario;
import io.metersphere.plan.domain.TestPlanApiScenarioExample;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.mapper.ExtTestPlanApiScenarioMapper;
import io.metersphere.plan.mapper.TestPlanApiScenarioMapper;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -47,6 +54,30 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
return runResultCounts.stream().collect(Collectors.toMap(TestPlanCaseRunResultCount::getResult, TestPlanCaseRunResultCount::getResultCount));
}
@Override
public long copyResource(String originalTestPlanId, String newTestPlanId, String operator, long operatorTime) {
List<TestPlanApiScenario> copyList = new ArrayList<>();
extTestPlanApiScenarioMapper.selectByTestPlanIdAndNotDeleted(originalTestPlanId).forEach(originalCase -> {
TestPlanApiScenario newCase = new TestPlanApiScenario();
BeanUtils.copyBean(newCase, originalCase);
newCase.setId(IDGenerator.nextStr());
newCase.setTestPlanId(newTestPlanId);
newCase.setCreateTime(operatorTime);
newCase.setCreateUser(operator);
newCase.setLastExecTime(0L);
newCase.setLastExecResult(null);
newCase.setLastExecReportId(null);
copyList.add(newCase);
});
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanApiScenarioMapper batchInsertMapper = sqlSession.getMapper(TestPlanApiScenarioMapper.class);
copyList.forEach(item -> batchInsertMapper.insert(item));
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
return copyList.size();
}
@Override
public void refreshPos(String testPlanId) {
// todo

View File

@ -72,19 +72,16 @@ public class TestPlanBaseUtilsService {
}
}
/**
* 关联用例
*
* @param request
* @return
*/
public void association(TestPlanAssociationRequest request, String operator) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
handleAssociateCase(request, operator, testPlan);
}
/**
* 处理关联的用例
*

View File

@ -1,125 +0,0 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
import io.metersphere.plan.dto.request.TestPlanBatchRequest;
import io.metersphere.plan.mapper.TestPlanAllocationMapper;
import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanBatchCopyService {
@Resource
private TestPlanConfigMapper testPlanConfigMapper;
@Resource
private TestPlanAllocationMapper testPlanAllocationMapper;
@Resource
private TestPlanMapper testPlanMapper;
public void batchCopy(Map<String, List<TestPlan>> plans, TestPlanBatchRequest request, String userId) {
batchCopyGroup(plans, request, userId);
batchCopyPlan(plans, request, userId);
}
/**
* 批量复制组
*
* @param plans
*/
private void batchCopyGroup(Map<String, List<TestPlan>> plans, TestPlanBatchProcessRequest request, String userId) {
//TODO 批量复制计划组
}
/**
* 批量复制计划
*
* @param plans
*/
private void batchCopyPlan(Map<String, List<TestPlan>> plans, TestPlanBatchRequest request, String userId) {
if (plans.containsKey(TestPlanConstants.TEST_PLAN_TYPE_PLAN)) {
List<TestPlan> testPlans = plans.get(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
List<String> ids = testPlans.stream().map(TestPlan::getId).collect(Collectors.toList());
//额外信息
TestPlanConfigExample configExample = new TestPlanConfigExample();
configExample.createCriteria().andTestPlanIdIn(ids);
List<TestPlanConfig> testPlanConfigs = testPlanConfigMapper.selectByExample(configExample);
//测试规划配置信息
TestPlanAllocationExample allocationExample = new TestPlanAllocationExample();
allocationExample.createCriteria().andTestPlanIdIn(ids);
List<TestPlanAllocation> testPlanAllocations = testPlanAllocationMapper.selectByExample(allocationExample);
batchInsertPlan(testPlans, testPlanConfigs, testPlanAllocations, request, userId);
}
}
private void batchInsertPlan(List<TestPlan> testPlans, List<TestPlanConfig> testPlanConfigs, List<TestPlanAllocation> testPlanAllocations, TestPlanBatchRequest request, String userId) {
Map<String, List<TestPlanConfig>> configs = testPlanConfigs.stream().collect(Collectors.groupingBy(TestPlanConfig::getTestPlanId));
Map<String, List<TestPlanAllocation>> allocationsList = testPlanAllocations.stream().collect(Collectors.groupingBy(TestPlanAllocation::getTestPlanId));
List<TestPlanConfig> newConfigs = new ArrayList<>();
List<TestPlanAllocation> newAllocations = new ArrayList<>();
testPlans.forEach(testPlan -> {
List<TestPlanConfig> config = configs.get(testPlan.getId());
List<TestPlanAllocation> allocations = allocationsList.get(testPlan.getId());
Long num = testPlan.getNum();
testPlan.setId(IDGenerator.nextStr());
testPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);
testPlan.setNum(NumGenerator.nextNum(testPlan.getProjectId(), ApplicationNumScope.TEST_PLAN));
testPlan.setName(getCopyName(testPlan.getName(), num, testPlan.getNum()));
testPlan.setModuleId(request.getModuleId());
testPlan.setCreateTime(System.currentTimeMillis());
testPlan.setUpdateTime(System.currentTimeMillis());
testPlan.setCreateUser(userId);
testPlan.setUpdateUser(userId);
if (CollectionUtils.isNotEmpty(config)) {
TestPlanConfig testPlanConfig = config.get(0);
testPlanConfig.setTestPlanId(testPlan.getId());
newConfigs.add(testPlanConfig);
}
if (CollectionUtils.isNotEmpty(allocations)) {
TestPlanAllocation testPlanAllocation = allocations.get(0);
testPlanAllocation.setTestPlanId(testPlan.getId());
testPlanAllocation.setId(IDGenerator.nextStr());
newAllocations.add(testPlanAllocation);
}
});
testPlanMapper.batchInsert(testPlans);
if (CollectionUtils.isNotEmpty(newConfigs)) {
testPlanConfigMapper.batchInsert(newConfigs);
}
if (CollectionUtils.isNotEmpty(newAllocations)) {
testPlanAllocationMapper.batchInsert(newAllocations);
}
}
private String getCopyName(String name, long oldNum, long newNum) {
if (!StringUtils.startsWith(name, "copy_")) {
name = "copy_" + name;
}
if (name.length() > 250) {
name = name.substring(0, 200) + "...";
}
if (StringUtils.endsWith(name, "_" + oldNum)) {
name = StringUtils.substringBeforeLast(name, "_" + oldNum);
}
name = name + "_" + newNum;
return name;
}
}

View File

@ -1,57 +0,0 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
import io.metersphere.plan.dto.request.TestPlanBatchRequest;
import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.sdk.constants.TestPlanConstants;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanBatchMoveService extends TestPlanBaseUtilsService {
@Resource
private ExtTestPlanMapper extTestPlanMapper;
public void batchMove(Map<String, List<TestPlan>> plans, TestPlanBatchRequest request, String userId) {
batchMoveGroup(plans, request, userId);
batchMovePlan(plans, request, userId);
}
/**
* 批量移动组
*
* @param plans
*/
private void batchMoveGroup(Map<String, List<TestPlan>> plans, TestPlanBatchProcessRequest request, String userId) {
//TODO 批量移动计划组
}
/**
* 批量移动计划
*
* @param plans
*/
private void batchMovePlan(Map<String, List<TestPlan>> plans, TestPlanBatchRequest request, String userId) {
if (plans.containsKey(TestPlanConstants.TEST_PLAN_TYPE_PLAN)) {
List<TestPlan> testPlans = plans.get(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
testPlans.forEach(testPlan -> {
testPlan.setModuleId(request.getModuleId());
// 5.21查询需求文档测试用例测试计划名称允许重复
// validateTestPlan(testPlan);
});
List<String> ids = testPlans.stream().map(TestPlan::getId).collect(Collectors.toList());
extTestPlanMapper.batchMove(ids, request.getModuleId(), userId, System.currentTimeMillis());
}
}
}

View File

@ -0,0 +1,260 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanConfig;
import io.metersphere.plan.domain.TestPlanExample;
import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.project.utils.NodeSortUtils;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
@Resource
private ExtTestPlanMapper extTestPlanMapper;
@Resource
private TestPlanMapper testPlanMapper;
@Resource
private TestPlanGroupService testPlanGroupService;
@Resource
private TestPlanConfigMapper testPlanConfigMapper;
@Autowired
private ApplicationContext applicationContext;
public long batchMoveModule(List<TestPlan> testPlanList, String moduleId, String userId) {
List<String> movePlanIds = new ArrayList<>();
for (TestPlan testPlan : testPlanList) {
// 已归档的测试计划无法操作
if (StringUtils.equalsIgnoreCase(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
continue;
}
if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
// 测试计划组下的测试计划不单独处理 如果勾选了他的测试计划组会在下面进行逻辑补足
continue;
}
movePlanIds.add(testPlan.getId());
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
List<TestPlanResponse> testPlanItemList = extTestPlanMapper.selectByGroupIds(Collections.singletonList(testPlan.getId()));
for (TestPlanResponse item : testPlanItemList) {
movePlanIds.add(item.getId());
}
}
}
movePlanIds = movePlanIds.stream().distinct().toList();
return batchMovePlan(movePlanIds, moduleId, userId);
}
public long batchMoveGroup(List<TestPlan> testPlanList, String groupId, String userId) {
// 判断测试计划组是否存在
String groupModuleId = null;
if (!StringUtils.equalsIgnoreCase(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"));
}
groupModuleId = groupPlan.getModuleId();
}
List<String> movePlanIds = new ArrayList<>();
for (TestPlan testPlan : testPlanList) {
// 已归档的测试计划无法操作 测试计划组无法操作
if (StringUtils.equalsIgnoreCase(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)
|| StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
continue;
}
movePlanIds.add(testPlan.getId());
}
long nextPos = testPlanGroupService.getNextOrder(groupId);
long operationTimestamp = System.currentTimeMillis();
int index = 0;
for (TestPlan testPlan : testPlanList) {
TestPlan updatePlan = new TestPlan();
updatePlan.setId(testPlan.getId());
updatePlan.setUpdateTime(operationTimestamp);
updatePlan.setGroupId(groupId);
updatePlan.setModuleId(StringUtils.isBlank(groupModuleId) ? testPlan.getModuleId() : groupModuleId);
updatePlan.setPos(nextPos + index * NodeSortUtils.DEFAULT_NODE_INTERVAL_POS);
updatePlan.setUpdateUser(userId);
testPlanMapper.updateByPrimaryKeySelective(updatePlan);
}
return testPlanList.size();
}
/**
* 批量移动计划
*/
private long batchMovePlan(List<String> ids, String moduleId, String userId) {
if (CollectionUtils.isNotEmpty(ids)) {
return extTestPlanMapper.batchMove(ids, moduleId, userId, System.currentTimeMillis());
} else {
return 0;
}
}
public long batchCopy(List<TestPlan> copyPlanList, String targetId, String targetType, String userId) {
long copyCount = 0;
long operatorTime = System.currentTimeMillis();
/*
此处不选择批量操作原因有两点
1 测试计划内或者测试计划组内数据量不可控选择批量操作时更容易出现数据太多不走索引数据太多内存溢出等问题不批量操作可以减少这些问题出现的概率代价是速度会变慢
2 作为数据量不可控的操作如果数据量少不采用批量处理也不会消耗太多时间如果数据量多就会容易出现1的问题并且本人不建议针对不可控数据量的数据支持批量操作
*/
for (TestPlan copyPlan : copyPlanList) {
if (StringUtils.equalsIgnoreCase(copyPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
copyCount += this.copyPlanGroup(copyPlan, targetId, targetType, operatorTime, userId);
} else {
copyCount += this.copyPlan(copyPlan, targetId, targetType, operatorTime, userId);
}
}
return copyCount;
}
/**
* 复制测试计划
*
* @param originalTestPlan 原始测试计划
* @param targetId 目标ID
* @param targetType 目标类型
* @param operatorTime 操作时间
* @param operator 操作人
* @return 复制的数量
*/
public int copyPlan(TestPlan originalTestPlan, String targetId, String targetType, long operatorTime, String operator) {
//已归档的无法操作
if (StringUtils.equalsIgnoreCase(originalTestPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
return 0;
}
String moduleId = originalTestPlan.getModuleId();
String groupId = originalTestPlan.getGroupId();
long pos = originalTestPlan.getPos();
if (StringUtils.equals(targetType, TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
if (StringUtils.equalsIgnoreCase(targetId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
pos = 0L;
} else {
TestPlan group = testPlanMapper.selectByPrimaryKey(targetId);
//已归档的无法操作
if (group == null || StringUtils.equalsIgnoreCase(group.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)
|| !StringUtils.equalsIgnoreCase(group.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
throw new MSException(Translator.get("test_plan.group.error"));
}
pos = testPlanGroupService.getNextOrder(targetId);
moduleId = group.getId();
}
groupId = targetId;
} else {
super.checkModule(targetId);
moduleId = targetId;
}
TestPlan testPlan = new TestPlan();
BeanUtils.copyBean(testPlan, originalTestPlan);
testPlan.setId(IDGenerator.nextStr());
testPlan.setNum(NumGenerator.nextNum(testPlan.getProjectId(), ApplicationNumScope.TEST_PLAN));
testPlan.setName(this.getCopyName(originalTestPlan.getName(), originalTestPlan.getNum(), testPlan.getNum()));
testPlan.setCreateUser(operator);
testPlan.setCreateTime(operatorTime);
testPlan.setUpdateUser(operator);
testPlan.setUpdateTime(operatorTime);
testPlan.setModuleId(moduleId);
testPlan.setGroupId(groupId);
testPlan.setPos(pos);
testPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);
testPlanMapper.insert(testPlan);
//测试配置信息
TestPlanConfig originalTestPlanConfig = testPlanConfigMapper.selectByPrimaryKey(originalTestPlan.getId());
if (originalTestPlanConfig != null) {
TestPlanConfig newTestPlanConfig = new TestPlanConfig();
BeanUtils.copyBean(newTestPlanConfig, originalTestPlanConfig);
newTestPlanConfig.setTestPlanId(testPlan.getId());
testPlanConfigMapper.insert(newTestPlanConfig);
}
//todo 测试规划信息
//测试用例信息
Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
beansOfType.forEach((k, v) -> {
v.copyResource(originalTestPlan.getId(), testPlan.getId(), operator, operatorTime);
});
return 1;
}
public int copyPlanGroup(TestPlan originalGroup, String targetId, String targetType, long operatorTime, String operator) {
//测试计划组复制的时候只支持targetType为module的操作. 已归档的无法操作
if (StringUtils.equalsIgnoreCase(targetType, TestPlanConstants.TEST_PLAN_TYPE_GROUP)
|| StringUtils.equalsIgnoreCase(originalGroup.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
return 0;
}
super.checkModule(targetId);
String moduleId = targetId;
TestPlanExample example = new TestPlanExample();
example.createCriteria().andGroupIdEqualTo(originalGroup.getId());
example.setOrderByClause("pos asc");
List<TestPlan> childList = testPlanMapper.selectByExample(example);
int copyCount = 0;
TestPlan testPlanGroup = new TestPlan();
BeanUtils.copyBean(testPlanGroup, originalGroup);
testPlanGroup.setId(IDGenerator.nextStr());
testPlanGroup.setNum(NumGenerator.nextNum(testPlanGroup.getProjectId(), ApplicationNumScope.TEST_PLAN));
testPlanGroup.setName(this.getCopyName(originalGroup.getName(), originalGroup.getNum(), testPlanGroup.getNum()));
testPlanGroup.setCreateUser(operator);
testPlanGroup.setCreateTime(operatorTime);
testPlanGroup.setUpdateUser(operator);
testPlanGroup.setUpdateTime(operatorTime);
testPlanGroup.setModuleId(moduleId);
testPlanGroup.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);
copyCount += testPlanMapper.insert(testPlanGroup);
for (TestPlan child : childList) {
copyCount += copyPlan(child, testPlanGroup.getId(), TestPlanConstants.TEST_PLAN_TYPE_GROUP, operatorTime, operator);
}
return copyCount;
}
private String getCopyName(String name, long oldNum, long newNum) {
if (!StringUtils.startsWith(name, "copy_")) {
name = "copy_" + name;
}
if (name.length() > 250) {
name = name.substring(0, 200) + "...";
}
if (StringUtils.endsWith(name, "_" + oldNum)) {
name = StringUtils.substringBeforeLast(name, "_" + oldNum);
}
name = name + "_" + newNum;
return name;
}
}

View File

@ -54,9 +54,14 @@ public class TestPlanBugService extends TestPlanResourceService {
return Map.of();
}
@Override
public long copyResource(String originalTestPlanId, String newTestPlanId, String operator, long operatorTime) {
return 0;
}
@Override
public long getNextOrder(String projectId) {
public long getNextOrder(String testPlanId) {
return 0;
}

View File

@ -112,15 +112,38 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
private ExtUserMapper extUserMapper;
private static final String CASE_MODULE_COUNT_ALL = "all";
public long copyResource(String originalTestPlanId, String newTestPlanId, String operator, long operatorTime) {
List<TestPlanFunctionalCase> copyList = new ArrayList<>();
extTestPlanFunctionalCaseMapper.selectByTestPlanIdAndNotDeleted(originalTestPlanId).forEach(originalCase -> {
TestPlanFunctionalCase newCase = new TestPlanFunctionalCase();
BeanUtils.copyBean(newCase, originalCase);
newCase.setId(IDGenerator.nextStr());
newCase.setTestPlanId(newTestPlanId);
newCase.setCreateTime(operatorTime);
newCase.setCreateUser(operator);
newCase.setLastExecTime(0L);
newCase.setLastExecResult(null);
copyList.add(newCase);
});
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanFunctionalCaseMapper batchInsertMapper = sqlSession.getMapper(TestPlanFunctionalCaseMapper.class);
copyList.forEach(item -> batchInsertMapper.insert(item));
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
return copyList.size();
}
@Override
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanFunctionalCaseExample testPlanFunctionalCaseExample = new TestPlanFunctionalCaseExample();
testPlanFunctionalCaseExample.createCriteria().andTestPlanIdIn(testPlanIdList);
testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample);
// todo:song.tianyang 删除执行历史
if (CollectionUtils.isNotEmpty(testPlanIdList)) {
TestPlanFunctionalCaseExample testPlanFunctionalCaseExample = new TestPlanFunctionalCaseExample();
testPlanFunctionalCaseExample.createCriteria().andTestPlanIdIn(testPlanIdList);
testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample);
testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample);
TestPlanCaseExecuteHistoryExample testPlanCaseExecuteHistoryExample = new TestPlanCaseExecuteHistoryExample();
testPlanCaseExecuteHistoryExample.createCriteria().andTestPlanIdIn(testPlanIdList);
testPlanCaseExecuteHistoryMapper.deleteByExample(testPlanCaseExecuteHistoryExample);
}
}
@ -164,13 +187,13 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
extTestPlanCaseExecuteHistoryMapper.updateDeleted(associationParam.getResourceIdList(), true);
}
public TestPlanResourceSortResponse sortNode(ResourceSortRequest request, LogInsertModule logInsertModule) {
public TestPlanOperationResponse sortNode(ResourceSortRequest request, LogInsertModule logInsertModule) {
TestPlanFunctionalCase dragNode = testPlanFunctionalCaseMapper.selectByPrimaryKey(request.getMoveId());
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
if (dragNode == null) {
throw new MSException(Translator.get("test_plan.drag.node.error"));
}
TestPlanResourceSortResponse response = new TestPlanResourceSortResponse();
TestPlanOperationResponse response = new TestPlanOperationResponse();
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
request.getTestPlanId(),
super.getNodeMoveRequest(request, true),
@ -178,7 +201,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
extTestPlanFunctionalCaseMapper::selectNodeByPosOperator
);
super.sort(sortDTO);
response.setSortNodeNum(1);
response.setOperationCount(1);
testPlanResourceLogService.saveSortLog(testPlan, request.getMoveId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, logInsertModule));
return response;
}

View File

@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -113,7 +114,7 @@ public class TestPlanManagementService {
}
public List<TestPlanResponse> selectByGroupId(String groupId) {
return extTestPlanMapper.selectByGroupIds(List.of(groupId));
return extTestPlanMapper.selectByGroupIds(Collections.singletonList(groupId));
}

View File

@ -51,4 +51,6 @@ public abstract class TestPlanResourceService extends TestPlanSortService {
}
return response;
}
public abstract long copyResource(String originalTestPlanId, String newTestPlanId, String operator, long operatorTime);
}

View File

@ -3,7 +3,7 @@ package io.metersphere.plan.service;
import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
import io.metersphere.plan.dto.response.TestPlanResourceSortResponse;
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
import io.metersphere.plan.mapper.*;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.exception.MSException;
@ -64,9 +64,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
@Resource
private TestPlanAllocationMapper testPlanAllocationMapper;
@Resource
private TestPlanBatchCopyService testPlanBatchCopyService;
@Resource
private TestPlanBatchMoveService testPlanBatchMoveService;
private TestPlanBatchOperationService testPlanBatchOperationService;
@Resource
private TestPlanBatchArchivedService testPlanBatchArchivedService;
@Resource
@ -381,6 +379,8 @@ public class TestPlanService extends TestPlanBaseUtilsService {
//检查模块的合法性
checkModule(request.getModuleId());
updateTestPlan.setModuleId(request.getModuleId());
//移动模块时重置GroupId
updateTestPlan.setGroupId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
}
if (StringUtils.isNotBlank(request.getName())) {
updateTestPlan.setName(request.getName());
@ -443,12 +443,14 @@ public class TestPlanService extends TestPlanBaseUtilsService {
if (StringUtils.equalsAnyIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
//测试计划组归档
updateGroupStatus(testPlan.getId(), userId);
} else if (StringUtils.equals(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_COMPLETED)) {
} else if (StringUtils.equals(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_COMPLETED) && StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
//测试计划
testPlan.setStatus(TEST_PLAN_STATUS_ARCHIVED);
testPlan.setUpdateUser(userId);
testPlan.setUpdateTime(System.currentTimeMillis());
testPlanMapper.updateByPrimaryKeySelective(testPlan);
} else {
throw new MSException(Translator.get("test_plan.cannot.archived"));
}
}
@ -494,14 +496,15 @@ public class TestPlanService extends TestPlanBaseUtilsService {
/**
* 复制测试计划
*
* @param request
* @param userId
* @return
*/
public TestPlan copy(TestPlanCopyRequest request, String userId) {
TestPlan testPlan = savePlanDTO(request, userId, request.getId());
return testPlan;
public long copy(String testPlanId, String userId) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(testPlanId);
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
return testPlanBatchOperationService.copyPlanGroup(testPlan, testPlan.getModuleId(), ModuleConstants.NODE_TYPE_DEFAULT, System.currentTimeMillis(), userId);
} else {
return testPlanBatchOperationService.copyPlan(testPlan, testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_TYPE_GROUP, System.currentTimeMillis(), userId);
}
}
@ -619,20 +622,27 @@ public class TestPlanService extends TestPlanBaseUtilsService {
* @param url 请求URL
* @param method 请求方法
*/
public void batchCopy(TestPlanBatchRequest request, String userId, String url, String method) {
public long batchCopy(TestPlanBatchRequest request, String userId, String url, String method) {
// 目前计划的批量操作不支持全选所有页
List<String> copyIds = request.getSelectIds();
long copyCount = 0;
if (CollectionUtils.isNotEmpty(copyIds)) {
TestPlanExample example = new TestPlanExample();
example.createCriteria().andIdIn(copyIds);
List<TestPlan> copyTestPlanList = testPlanMapper.selectByExample(example);
//批量复制时不允许存在测试计划组下的测试计划
copyTestPlanList = copyTestPlanList.stream().filter(item -> !StringUtils.equalsIgnoreCase(item.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID))
.collect(Collectors.toList());
//日志
if (CollectionUtils.isNotEmpty(copyTestPlanList)) {
Map<String, List<TestPlan>> plans = copyTestPlanList.stream().collect(Collectors.groupingBy(TestPlan::getType));
testPlanBatchCopyService.batchCopy(plans, request, userId);
//日志
copyCount = testPlanBatchOperationService.batchCopy(copyTestPlanList, request.getTargetId(), request.getMoveType(), userId);
testPlanLogService.saveBatchLog(copyTestPlanList, userId, url, method, OperationLogType.COPY.name(), "copy");
}
}
return copyCount;
}
/**
@ -640,25 +650,32 @@ public class TestPlanService extends TestPlanBaseUtilsService {
*
* @param request 批量请求参数
* @param userId 当前登录用户
* @param url 请求URL
* @param operationUrl 请求URL
* @param method 请求方法
*/
public void batchMove(TestPlanBatchRequest request, String userId, String url, String method) {
public long batchMove(TestPlanBatchRequest request, String userId, String operationUrl, String method) {
// 目前计划的批量操作不支持全选所有页
List<String> moveIds = request.getSelectIds();
long moveCount = 0;
if (CollectionUtils.isNotEmpty(moveIds)) {
TestPlanExample example = new TestPlanExample();
example.createCriteria().andIdIn(moveIds);
List<TestPlan> moveTestPlanList = testPlanMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(moveTestPlanList)) {
Map<String, List<TestPlan>> plans = moveTestPlanList.stream().collect(Collectors.groupingBy(TestPlan::getType));
testPlanBatchMoveService.batchMove(plans, request, userId);
//日志
testPlanLogService.saveBatchLog(moveTestPlanList, userId, url, method, OperationLogType.UPDATE.name(), "update");
}
}
}
//判断移动的是测试计划组还是模块
if (StringUtils.equalsIgnoreCase(request.getMoveType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
moveTestPlanList = moveTestPlanList.stream().filter(item -> StringUtils.equalsIgnoreCase(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_PLAN))
.collect(Collectors.toList());
moveCount = testPlanBatchOperationService.batchMoveGroup(moveTestPlanList, request.getTargetId(), userId);
} else {
moveCount = testPlanBatchOperationService.batchMoveModule(moveTestPlanList, request.getTargetId(), userId);
}
//日志
testPlanLogService.saveBatchLog(moveTestPlanList, userId, operationUrl, method, OperationLogType.UPDATE.name(), "update");
}
return moveCount;
}
/**
* 批量编辑
@ -796,10 +813,10 @@ public class TestPlanService extends TestPlanBaseUtilsService {
testPlanMapper.updateByPrimaryKeySelective(testPlan);
}
public TestPlanResourceSortResponse sortInGroup(PosRequest request, LogInsertModule logInsertModule) {
public TestPlanOperationResponse sortInGroup(PosRequest request, LogInsertModule logInsertModule) {
testPlanGroupService.sort(request);
testPlanLogService.saveMoveLog(testPlanMapper.selectByPrimaryKey(request.getMoveId()), request.getMoveId(), logInsertModule);
return new TestPlanResourceSortResponse(1);
return new TestPlanOperationResponse(1);
}

View File

@ -8,7 +8,7 @@ import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.TestPlanAllocationTypeDTO;
import io.metersphere.plan.dto.TestPlanCollectionInitDTO;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanResourceSortResponse;
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.enums.ExecuteMethod;
import io.metersphere.plan.mapper.*;
@ -128,7 +128,7 @@ public class TestPlanTests extends BaseTest {
private static final String URL_TEST_PLAN_EDIT_FOLLOWER = "/test-plan/edit/follower";
private static final String URL_TEST_PLAN_ARCHIVED = "/test-plan/archived/%s";
private static final String URL_TEST_PLAN_COPY = "/test-plan/copy";
private static final String URL_TEST_PLAN_COPY = "/test-plan/copy/%s";
private static final String URL_TEST_PLAN_DETAIL = "/test-plan/%s";
private static final String URL_TEST_PLAN_BATCH_COPY = "/test-plan/batch-copy";
private static final String URL_TEST_PLAN_BATCH_MOVE = "/test-plan/batch-move";
@ -138,6 +138,8 @@ public class TestPlanTests extends BaseTest {
private static String groupTestPlanId7 = null;
private static String groupTestPlanId15 = null;
private static List<String> rootPlanIds = new ArrayList<>();
//普通测试计划
private static TestPlan simpleTestPlan;
//允许重复添加用例的测试计划
@ -173,7 +175,6 @@ public class TestPlanTests extends BaseTest {
}
}
private static long a1NodeCount = 0;
private static long a2NodeCount = 0;
private static long a3NodeCount = 0;
@ -577,8 +578,6 @@ public class TestPlanTests extends BaseTest {
} else if (i == 15) {
groupTestPlanId15 = returnId;
} else if (i > 700 && i < 750) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanReportMapper batchInsert = sqlSession.getMapper(TestPlanReportMapper.class);
// 701-749 要创建测试计划报告 每个测试计划创建250个报告
@ -603,7 +602,9 @@ public class TestPlanTests extends BaseTest {
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
rootPlanIds.add(returnId);
} else {
rootPlanIds.add(returnId);
}
//操作日志检查
@ -695,8 +696,9 @@ public class TestPlanTests extends BaseTest {
request.setPassThreshold(100);
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_ADD, URL_POST_TEST_PLAN_ADD, request);
this.checkTestPlanSortInGroup(groupTestPlanId7);
this.checkTestPlanMoveToGroup(groupTestPlanId7);
this.checkTestPlanGroupArchived(groupTestPlanId7);
}
private List<TestPlanResponse> selectByGroupId(String groupId) throws Exception {
@ -720,7 +722,7 @@ public class TestPlanTests extends BaseTest {
List<TestPlanResponse> lastTestPlanInGroup = defaultTestPlanInGroup;
TestPlanResponse movePlan, targetPlan = null;
PosRequest posRequest = null;
TestPlanResourceSortResponse response = null;
TestPlanOperationResponse response = null;
// 第一个移动到最后一个
movePlan = lastTestPlanInGroup.getFirst();
@ -731,10 +733,10 @@ public class TestPlanTests extends BaseTest {
JSON.parseObject(
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
.getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class);
TestPlanOperationResponse.class);
//位置校验
List<TestPlanResponse> newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(response.getOperationCount(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
int oldListIndex = newListIndex == newTestPlanInGroup.size() - 1 ? 0 : newListIndex + 1;
@ -751,10 +753,10 @@ public class TestPlanTests extends BaseTest {
JSON.parseObject(
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
.getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class);
TestPlanOperationResponse.class);
//位置校验
newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(response.getOperationCount(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), defaultTestPlanInGroup.get(newListIndex).getId());
@ -770,10 +772,10 @@ public class TestPlanTests extends BaseTest {
JSON.parseObject(
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
.getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class);
TestPlanOperationResponse.class);
//位置校验
newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(response.getOperationCount(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
int oldListIndex = newListIndex;
@ -800,10 +802,10 @@ public class TestPlanTests extends BaseTest {
JSON.parseObject(
this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_SORT, posRequest)
.getResponse().getContentAsString(), ResultHolder.class).getData()),
TestPlanResourceSortResponse.class);
TestPlanOperationResponse.class);
//位置校验
newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getSortNodeNum(), 1);
Assertions.assertEquals(response.getOperationCount(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
long lastPos = 0;
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
@ -811,7 +813,64 @@ public class TestPlanTests extends BaseTest {
Assertions.assertTrue(newTestPlanInGroup.get(newListIndex).getPos() == (lastPos + NodeSortUtils.DEFAULT_NODE_INTERVAL_POS));
lastPos = newTestPlanInGroup.get(newListIndex).getPos();
}
//测试权限
posRequest.setProjectId(DEFAULT_PROJECT_ID);
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_UPDATE, URL_POST_TEST_PLAN_SORT, posRequest);
}
protected void checkTestPlanMoveToGroup(String groupId) throws Exception {
List<String> movePlanIds = rootPlanIds.subList(rootPlanIds.size() - 21, rootPlanIds.size() - 1);
TestPlanBatchRequest request = new TestPlanBatchRequest();
request.setProjectId(project.getId());
request.setSelectIds(movePlanIds);
request.setMoveType(TestPlanConstants.TEST_PLAN_TYPE_GROUP);
request.setTargetId(groupId);
this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_MOVE, request);
List<TestPlanResponse> groups = this.selectByGroupId(groupId);
List<String> checkList = new ArrayList<>(movePlanIds);
for (TestPlanResponse response : groups) {
checkList.remove(response.getId());
}
Assertions.assertTrue(CollectionUtils.isEmpty(checkList));
//移动出来
request.setTargetId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_MOVE, request);
List<TestPlanResponse> nextGroups = this.selectByGroupId(groupId);
groups.removeAll(nextGroups);
for (TestPlanResponse response : groups) {
movePlanIds.remove(response.getId());
}
Assertions.assertTrue(CollectionUtils.isEmpty(movePlanIds));
//权限
request.setProjectId(DEFAULT_PROJECT_ID);
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_UPDATE, URL_TEST_PLAN_BATCH_MOVE, request);
}
private void checkTestPlanGroupArchived(String groupId) throws Exception {
// 测试计划组内的测试计划不能归档
List<TestPlanResponse> testPlanResponseList = this.selectByGroupId(groupId);
TestPlanResponse cannotArchivedPlan = testPlanResponseList.getFirst();
testPlanMapper.updateByPrimaryKeySelective(new TestPlan() {{
this.setId(cannotArchivedPlan.getId());
this.setStatus(TestPlanConstants.TEST_PLAN_STATUS_COMPLETED);
}});
this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, cannotArchivedPlan.getId())).andExpect(status().is5xxServerError());
//归档测试组内的测试计划
for (TestPlanResponse testPlanResponse : testPlanResponseList) {
testPlanMapper.updateByPrimaryKeySelective(new TestPlan() {{
this.setId(testPlanResponse.getId());
this.setStatus(TestPlanConstants.TEST_PLAN_STATUS_COMPLETED);
}});
}
this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, groupId));
}
@Test
@Order(12)
public void testPlanPageCountTest() throws Exception {
@ -1200,8 +1259,8 @@ public class TestPlanTests extends BaseTest {
MvcResult result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request);
ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
TestPlanResourceSortResponse response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class);
Assertions.assertEquals(response.getSortNodeNum(), 1);
TestPlanOperationResponse response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanOperationResponse.class);
Assertions.assertEquals(response.getOperationCount(), 1);
funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId());
Assertions.assertEquals(funcList.get(0).getId(), request.getMoveId());
Assertions.assertEquals(funcList.get(1).getId(), request.getTargetId());
@ -1215,8 +1274,8 @@ public class TestPlanTests extends BaseTest {
request.setMoveMode(MoveTypeEnum.BEFORE.name());
result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request);
resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class);
Assertions.assertEquals(response.getSortNodeNum(), 1);
response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanOperationResponse.class);
Assertions.assertEquals(response.getOperationCount(), 1);
funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId());
Assertions.assertEquals(funcList.get(0).getId(), request.getTargetId());
Assertions.assertEquals(funcList.get(1).getId(), request.getMoveId());
@ -1232,8 +1291,8 @@ public class TestPlanTests extends BaseTest {
testPlanTestService.setResourcePos(funcList.get(0).getId(), TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, 2);
result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request);
resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class);
Assertions.assertEquals(response.getSortNodeNum(), 1);
response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanOperationResponse.class);
Assertions.assertEquals(response.getOperationCount(), 1);
funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId());
Assertions.assertEquals(funcList.get(0).getId(), request.getMoveId());
Assertions.assertEquals(funcList.get(1).getId(), request.getTargetId());
@ -1890,7 +1949,7 @@ public class TestPlanTests extends BaseTest {
@Order(302)
public void testArchived() throws Exception {
//计划 -- 首先状态不是已完成
this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_1"));
this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_1")).andExpect(status().is5xxServerError());
//更改状态再归档
TestPlan testPlan = new TestPlan();
testPlan.setId("wx_test_plan_id_1");
@ -1898,9 +1957,8 @@ public class TestPlanTests extends BaseTest {
testPlanMapper.updateByPrimaryKeySelective(testPlan);
this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_1"));
//计划组
this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_2"));
this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_3"));
//计划组没有可归档的测试计划
this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_2")).andExpect(status().is5xxServerError());
this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_5"));
}
@ -1909,60 +1967,34 @@ public class TestPlanTests extends BaseTest {
@Order(303)
public void testCopy() throws Exception {
//1.计划 无用例
TestPlanCopyRequest copyRequest = new TestPlanCopyRequest();
copyRequest.setId("wx_test_plan_id_1");
copyRequest.setProjectId("123");
copyRequest.setName("测试计划复制");
copyRequest.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_TEST_PLAN_COPY, copyRequest);
MvcResult mvcResult = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_1"));
String returnStr = mvcResult.getResponse().getContentAsString();
ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class);
String returnId = holder.getData().toString();
Assertions.assertNotNull(returnId);
//2.计划 有用例
TestPlanCopyRequest copyRequest1 = new TestPlanCopyRequest();
copyRequest1.setId("wx_test_plan_id_4");
copyRequest1.setProjectId("123");
copyRequest1.setName("测试计划复制有用例");
copyRequest1.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
MvcResult mvcResult1 = this.requestPostWithOkAndReturn(URL_TEST_PLAN_COPY, copyRequest1);
MvcResult mvcResult1 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_4"));
String returnStr1 = mvcResult1.getResponse().getContentAsString();
ResultHolder holder1 = JSON.parseObject(returnStr1, ResultHolder.class);
String returnId1 = holder1.getData().toString();
Assertions.assertNotNull(returnId1);
//3.计划组 无计划
TestPlanCopyRequest copyRequest2 = new TestPlanCopyRequest();
copyRequest2.setId("wx_test_plan_id_2");
copyRequest2.setProjectId("123");
copyRequest2.setName("测试计划组复制无计划");
copyRequest2.setType(TestPlanConstants.TEST_PLAN_TYPE_GROUP);
MvcResult mvcResult2 = this.requestPostWithOkAndReturn(URL_TEST_PLAN_COPY, copyRequest2);
MvcResult mvcResult2 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_2"));
String returnStr2 = mvcResult2.getResponse().getContentAsString();
ResultHolder holder2 = JSON.parseObject(returnStr2, ResultHolder.class);
String returnId2 = holder2.getData().toString();
Assertions.assertNotNull(returnId2);
//4.计划组 有计划
TestPlanCopyRequest copyRequest3 = new TestPlanCopyRequest();
copyRequest3.setId("wx_test_plan_id_5");
copyRequest3.setProjectId("123");
copyRequest3.setName("测试计划组复制有计划");
copyRequest3.setType(TestPlanConstants.TEST_PLAN_TYPE_GROUP);
MvcResult mvcResult3 = this.requestPostWithOkAndReturn(URL_TEST_PLAN_COPY, copyRequest3);
MvcResult mvcResult3 = this.requestGetWithOkAndReturn(String.format(URL_TEST_PLAN_COPY, "wx_test_plan_id_5"));
String returnStr3 = mvcResult3.getResponse().getContentAsString();
ResultHolder holder3 = JSON.parseObject(returnStr3, ResultHolder.class);
String returnId3 = holder3.getData().toString();
Assertions.assertNotNull(returnId3);
}
@Test
@Order(303)
public void testDetail() throws Exception {
@ -1994,9 +2026,9 @@ public class TestPlanTests extends BaseTest {
@Order(304)
public void testBatchCopy() throws Exception {
TestPlanBatchRequest request = new TestPlanBatchRequest();
request.setProjectId("123");
request.setProjectId("songtianyang-fix-wx");
request.setType("ALL");
request.setModuleId("2");
request.setTargetId("2");
request.setSelectIds(Arrays.asList("wx_test_plan_id_1", "wx_test_plan_id_2"));
this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_COPY, request);
@ -2007,22 +2039,22 @@ public class TestPlanTests extends BaseTest {
@Order(304)
public void testBatchMove() throws Exception {
TestPlanBatchRequest request = new TestPlanBatchRequest();
request.setProjectId("123");
request.setProjectId("songtianyang-fix-wx");
request.setType("ALL");
request.setModuleId("3");
request.setTargetId("3");
request.setSelectIds(Arrays.asList("wx_test_plan_id_3", "wx_test_plan_id_4"));
request.setMoveType(ModuleConstants.NODE_TYPE_DEFAULT);
this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_MOVE, request);
}
@Test
@Order(305)
public void testBatchArchived() throws Exception {
TestPlanBatchRequest request = new TestPlanBatchRequest();
request.setProjectId("123");
request.setProjectId("songtianyang-fix-wx");
request.setType("ALL");
request.setModuleId("3");
request.setTargetId("3");
request.setSelectIds(List.of("wx_test_plan_id_2"));
this.requestPost(URL_TEST_PLAN_BATCH_ARCHIVED, request, status().is5xxServerError());
request.setSelectIds(List.of("wx_test_plan_id_7"));
@ -2058,7 +2090,7 @@ public class TestPlanTests extends BaseTest {
request.setTags(Arrays.asList("tag1", "tag2"));
request.setAppend(true);
request.setType("ALL");
request.setProjectId("123");
request.setProjectId("songtianyang-fix-wx");
request.setSelectIds(Arrays.asList("wx_test_plan_id_1"));
this.requestPostWithOk(URL_TEST_PLAN_BATCH_EDIT, request);
request.setAppend(false);

View File

@ -1,12 +1,26 @@
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time,
module_setting)
VALUES ('songtianyang-fix-wx', 97, 1, 'songtianyang-fix-wx', 'songtianyang-fix-wx', 'admin', 'admin',
unix_timestamp() * 1000, unix_timestamp() * 1000,
'["bugManagement","caseManagement","apiTest","testPlan"]');
INSERT INTO `test_plan`(`id`, `num`, `project_id`, `group_id`, `module_id`, `name`, `status`, `type`, `tags`, `create_time`, `create_user`, `update_time`, `update_user`, `planned_start_time`, `planned_end_time`, `actual_start_time`, `actual_end_time`, `description`)
VALUES
('wx_test_plan_id_1', 5000, '123', 'NONE', '1', '测试一下计划', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_2', 10000, '123', 'NONE', '1', '测试一下组', 'PREPARED', 'GROUP', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_3', 15000, '123', 'NONE', '1', '测试一下组2', 'PREPARED', 'GROUP', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_4', 20000, '123', 'wx_test_plan_id_3', '1', '测试一下计划2', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_5', 25000, '123', 'NONE', '1', '测试一下组3', 'PREPARED', 'GROUP', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_6', 30000, '123', 'wx_test_plan_id_5', '1', '测试组3下计划', 'COMPLETED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_7', 30000, '123', 'NONE', '1', '测试组4下计划', 'COMPLETED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');
VALUES ('wx_test_plan_id_1', 5000, 'songtianyang-fix-wx', 'NONE', '1', '测试一下计划', 'PREPARED', 'TEST_PLAN', NULL,
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_2', 10000, 'songtianyang-fix-wx', 'NONE', '1', '测试一下组', 'PREPARED', 'GROUP', NULL,
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_3', 15000, 'songtianyang-fix-wx', 'NONE', '1', '测试一下组2', 'PREPARED', 'GROUP', NULL,
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_4', 20000, 'songtianyang-fix-wx', 'wx_test_plan_id_3', '1', '测试一下计划2', 'PREPARED',
'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000,
1714980158000, '11'),
('wx_test_plan_id_5', 25000, 'songtianyang-fix-wx', 'NONE', '1', '测试一下组3', 'PREPARED', 'GROUP', NULL,
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'),
('wx_test_plan_id_6', 30000, 'songtianyang-fix-wx', 'wx_test_plan_id_5', '1', '测试组3下计划', 'COMPLETED',
'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000,
1714980158000, '11'),
('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');
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`) VALUES
@ -26,8 +40,7 @@ INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, r
INSERT INTO `test_plan_module`(`id`, `project_id`, `name`, `parent_id`, `pos`, `create_time`, `update_time`, `create_user`, `update_user`)
VALUES
('1', '123', 'wx_测试模块名称', 'ROOT', 1, 1714980158000, 1714980158000, 'admin', 'admin');
VALUES ('1', 'songtianyang-fix-wx', 'wx_测试模块名称', 'ROOT', 1, 1714980158000, 1714980158000, 'admin', 'admin');
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`)
@ -43,8 +56,13 @@ VALUES ('1', 'wx_test_plan_id_1', '111', b'0', 'scenario', '10', '1000', b'0');
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES
('my_test_1', 1, '1', '123', '100001', '1111', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
('my_test_2', 2, '1', '123', '100001', '2222', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
('my_test_3', 3, 'root', '123', '100001', '3333', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL);
VALUES ('my_test_1', 1, '1', 'songtianyang-fix-wx', '100001', '1111', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0',
'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559,
1698058347559, NULL),
('my_test_2', 2, '1', 'songtianyang-fix-wx', '100001', '2222', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0',
'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559,
1698058347559, NULL),
('my_test_3', 3, 'root', 'songtianyang-fix-wx', '100001', '3333', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0',
'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559,
1698058347559, NULL);