feat(测试计划): 游离态测试计划以及测试计划组排序功能开发

This commit is contained in:
Jianguo-Genius 2024-06-21 16:17:57 +08:00 committed by Craftsman
parent 4e2cac42d7
commit f0f3f69b7a
23 changed files with 299 additions and 576 deletions

View File

@ -3,6 +3,49 @@ SET SESSION innodb_lock_wait_timeout = 7200;
DROP TABLE IF EXISTS functional_minder_extra_node;
-- 清洗测试计划表的pos数据
DROP PROCEDURE IF EXISTS UpdatePosForNoneGroup;
DELIMITER
$$
CREATE PROCEDURE UpdatePosForNoneGroup()
BEGIN
#声明结束标识
DECLARE done INT DEFAULT FALSE;
DECLARE testPlanUpdateId varchar(50);
DECLARE testPlanProjectId varchar(50);
DECLARE lastProjectId varchar(50) default '';
DECLARE current_pos INT DEFAULT 4096;
DECLARE updateRow CURSOR FOR SELECT id, project_id
FROM test_plan
WHERE `group_id` = 'none'
ORDER BY project_id ASC, num ASC;
#设置终止标志
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
#打开游标
OPEN updateRow;
#获取当前游标指针记录,取出值赋给自定义的变量
FETCH updateRow INTO testPlanUpdateId,testPlanProjectId;
#遍历游标
REPEAT
#判断是否是同一个项目
IF testPlanProjectId != lastProjectId THEN
SET current_pos = 4096;
SET lastProjectId = testPlanProjectId;
END IF;
#利用取到的值进行数据库的操作
update test_plan set pos = current_pos where id = testPlanUpdateId;
# 将游标中的值再赋值给变量,供下次循环使用
FETCH updateRow INTO testPlanUpdateId,testPlanProjectId;
SET current_pos = current_pos + 4096;
UNTIL done END REPEAT;
#关闭游标
CLOSE updateRow;
END
$$
DELIMITER ;
CALL UpdatePosForNoneGroup();
DROP PROCEDURE IF EXISTS UpdatePosForNoneGroup;
-- 清洗测试计划表的pos数据结束
-- set innodb lock wait timeout to default
SET SESSION innodb_lock_wait_timeout = DEFAULT;

View File

@ -91,6 +91,12 @@ public abstract class MoveNodeService {
return new MoveNodeSortDTO(sortRangeId, dragNode, previousNode, nextNode);
}
//判断是否存在需要提前排序的异常数据
public boolean needRefreshBeforeSort(DropNode previousNode, DropNode nextNode) {
long previousPos = previousNode == null ? -1 : previousNode.getPos();
long nextPos = nextNode == null ? -1 : nextNode.getPos();
return nextPos - previousPos <= 1 || previousPos == 0 || nextPos == 0;
}
//排序
public void sort(MoveNodeSortDTO sortDTO) {
// 获取相邻节点

View File

@ -95,7 +95,6 @@ public class TestPlanApiCaseController {
batchRequest.setTestPlanId(request.getTestPlanId());
batchRequest.setSelectIds(List.of(request.getId()));
TestPlanAssociationResponse response = testPlanApiCaseService.disassociate(batchRequest, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/case/disassociate", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
}
@ -109,7 +108,6 @@ public class TestPlanApiCaseController {
return new TestPlanAssociationResponse();
}
TestPlanAssociationResponse response = testPlanApiCaseService.disassociate(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/case/batch/disassociate", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
}

View File

@ -101,7 +101,6 @@ public class TestPlanApiScenarioController {
batchRequest.setTestPlanId(request.getTestPlanId());
batchRequest.setSelectIds(List.of(request.getId()));
TestPlanAssociationResponse response = testPlanApiScenarioService.disassociate(batchRequest, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/scenario/disassociate", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
}
@ -112,7 +111,6 @@ public class TestPlanApiScenarioController {
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public TestPlanAssociationResponse batchDisassociate(@Validated @RequestBody BasePlanCaseBatchRequest request) {
TestPlanAssociationResponse response = testPlanApiScenarioService.disassociate(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/scenario/batch/disassociate", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
}

View File

@ -6,10 +6,7 @@ import io.metersphere.plan.constants.TestPlanResourceConfig;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.dto.TestPlanExecuteHisDTO;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
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.dto.response.*;
import io.metersphere.plan.service.*;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.PermissionConstants;
@ -168,11 +165,8 @@ public class TestPlanController {
@Operation(summary = "测试计划-复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#id", resourceType = "test_plan")
public TestPlanOperationResponse copy(@PathVariable String id) {
long copyCount = testPlanService.copy(id, SessionUtils.getUserId());
//copy完成之后的刷新一下状态
testPlanService.refreshTestPlanStatus(id);
return new TestPlanOperationResponse(copyCount);
public TestPlanSingleOperationResponse copy(@PathVariable String id) {
return new TestPlanSingleOperationResponse(testPlanService.copy(id, SessionUtils.getUserId()));
}
@PostMapping("/batch-copy")
@ -208,17 +202,6 @@ public class TestPlanController {
testPlanService.batchArchived(request, SessionUtils.getUserId());
}
@PostMapping(value = "/association")
@Operation(summary = "测试计划功能用例-关联功能用例")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ASSOCIATION)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public void association(@Validated @RequestBody TestPlanAssociationRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE));
testPlanService.checkTestPlanNotArchived(request.getTestPlanId());
testPlanService.association(request, SessionUtils.getUserId());
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
}
@PostMapping("/batch-edit")
@Operation(summary = "测试计划-批量编辑")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@ -236,7 +219,7 @@ public class TestPlanController {
@CheckOwner(resourceId = "#request.getMoveId()", resourceType = "test_plan")
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()));
return testPlanService.sort(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/sort", HttpMethodConstants.POST.name()));
}
@PostMapping(value = "/schedule-config")

View File

@ -97,7 +97,6 @@ public class TestPlanFunctionalCaseController {
batchRequest.setTestPlanId(request.getTestPlanId());
batchRequest.setSelectIds(List.of(request.getId()));
TestPlanAssociationResponse response = testPlanFunctionalCaseService.disassociate(batchRequest, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/disassociate", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
}
@ -108,7 +107,6 @@ public class TestPlanFunctionalCaseController {
public TestPlanAssociationResponse batchDisassociate(@Validated @RequestBody BasePlanCaseBatchRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE));
TestPlanAssociationResponse response = testPlanFunctionalCaseService.disassociate(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/batch/disassociate", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
}
@ -144,7 +142,6 @@ public class TestPlanFunctionalCaseController {
public void run(@Validated @RequestBody TestPlanCaseRunRequest request) {
testPlanFunctionalCaseService.run(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/run", HttpMethodConstants.POST.name()));
testPlanService.setActualStartTime(request.getTestPlanId());
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
}
@PostMapping("/batch/run")
@ -154,7 +151,6 @@ public class TestPlanFunctionalCaseController {
public void batchRun(@Validated @RequestBody TestPlanCaseBatchRunRequest request) {
testPlanFunctionalCaseService.batchRun(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/batch/run", HttpMethodConstants.POST.name()));
testPlanService.setActualStartTime(request.getTestPlanId());
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
}
@PostMapping("/has/associate/bug/page")

View File

@ -0,0 +1,14 @@
package io.metersphere.plan.dto.response;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TestPlanSingleOperationResponse {
@Schema(description = "处理成功的ID")
private String operationId;
}

View File

@ -57,6 +57,8 @@ public interface ExtTestPlanMapper {
long selectMaxPosByGroupId(String groupId);
long selectMaxPosByProjectIdAndGroupId(@Param("projectId") String projectId, @Param("groupId") String groupId);
List<TestPlanResponse> selectByGroupIds(@Param("groupIds") List<String> groupIds);
List<String> selectRightfulIdsForExecute(@Param("ids") List<String> ids);

View File

@ -87,7 +87,7 @@
<foreach collection="groupIds" item="groupId" separator="," open="(" close=")">
#{groupId}
</foreach>
ORDER BY t.pos ASC
ORDER BY t.pos DESC
</select>
<sql id="queryByTableRequest">
@ -452,6 +452,12 @@
FROM test_plan
WHERE group_id = #{0}
</select>
<select id="selectMaxPosByProjectIdAndGroupId" resultType="java.lang.Long">
SELECT IF(MAX(pos) IS NULL, 0, MAX(pos)) AS pos
FROM test_plan
WHERE project_id = #{projectId}
AND group_id = #{groupId}
</select>
<select id="selectRightfulIdsForExecute" resultType="java.lang.String">
SELECT id FROM test_plan WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">

View File

@ -85,7 +85,6 @@ public class TestPlanApiCaseBatchRunService {
*/
public void asyncBatchRun(TestPlanApiCaseBatchRunRequest request, String userId) {
TestPlanService testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
testPlanService.setTestPlanUnderway(request.getTestPlanId());
testPlanService.setActualStartTime(request.getTestPlanId());
Thread.startVirtualThread(() -> batchRun(request, userId));
}

View File

@ -683,7 +683,6 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
public TaskRequestDTO run(String id, String reportId, String userId) {
TestPlanApiCase testPlanApiCase = checkResourceExist(id);
TestPlanService testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
testPlanService.setTestPlanUnderway(testPlanApiCase.getTestPlanId());
testPlanService.setActualStartTime(testPlanApiCase.getTestPlanId());
ApiTestCase apiTestCase = apiTestCaseService.checkResourceExist(testPlanApiCase.getApiCaseId());
ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(testPlanApiCase.getTestPlanCollectionId());

View File

@ -85,7 +85,6 @@ public class TestPlanApiScenarioBatchRunService {
public void asyncBatchRun(TestPlanApiScenarioBatchRunRequest request, String userId) {
TestPlanService testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
testPlanService.setActualStartTime(request.getTestPlanId());
testPlanService.setTestPlanUnderway(request.getTestPlanId());
Thread.startVirtualThread(() -> batchRun(request, userId));
}

View File

@ -287,7 +287,6 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
public TaskRequestDTO run(String id, String reportId, String userId) {
TestPlanApiScenario testPlanApiScenario = checkResourceExist(id);
TestPlanService testPlanService = CommonBeanFactory.getBean(TestPlanService.class);
testPlanService.setTestPlanUnderway(testPlanApiScenario.getTestPlanId());
testPlanService.setActualStartTime(testPlanApiScenario.getTestPlanId());
ApiScenario apiScenario = apiScenarioService.checkResourceExist(testPlanApiScenario.getApiScenarioId());
ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(testPlanApiScenario.getTestPlanCollectionId());

View File

@ -1,29 +1,17 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.dto.ResourceLogInsertModule;
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
import io.metersphere.plan.dto.request.BaseAssociateCaseRequest;
import io.metersphere.plan.dto.request.TestPlanAssociationRequest;
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.TestPlanResourceConstants;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.TestPlanModuleExample;
import io.metersphere.system.dto.LogInsertModule;
import io.metersphere.system.mapper.TestPlanModuleMapper;
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.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanBaseUtilsService {
@ -35,8 +23,6 @@ public class TestPlanBaseUtilsService {
@Resource
private ExtTestPlanMapper extTestPlanMapper;
@Resource
private TestPlanCaseService testPlanCaseService;
@Resource
private TestPlanResourceLogService testPlanResourceLogService;
/**
@ -54,58 +40,4 @@ public class TestPlanBaseUtilsService {
}
}
/**
* 获取选择的计划id集合
*
* @param request
* @return
*/
public List<String> getSelectIds(TestPlanBatchProcessRequest request) {
if (request.isSelectAll()) {
List<String> ids = extTestPlanMapper.selectIdByConditions(request);
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(request.getExcludeIds())) {
ids.removeAll(request.getExcludeIds());
}
return ids;
} else {
return request.getSelectIds();
}
}
/**
* 关联用例
*
* @param request
*/
//TODO 后续删除此方法以及调用controlle 后续改成通过计划集保存用例
public void association(TestPlanAssociationRequest request, String operator) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
handleAssociateCase(request, operator, testPlan);
}
/**
* 处理关联的用例
*
* @param request
* @return
*/
public void handleAssociateCase(BaseAssociateCaseRequest request, String operator, TestPlan testPlan) {
//关联的功能用例
handleFunctionalCase(request.getFunctionalSelectIds(), operator, testPlan);
//TODO 关联接口用例/接口场景用例 handleApi(request.getApiSelectIds(),request.getApiCaseSelectIds())
}
/**
* 关联的功能用例
*
* @param functionalSelectIds
*/
private void handleFunctionalCase(List<String> functionalSelectIds, String operator, TestPlan testPlan) {
if (CollectionUtils.isNotEmpty(functionalSelectIds)) {
TestPlanResourceAssociationParam associationParam = new TestPlanResourceAssociationParam(functionalSelectIds, testPlan.getProjectId(), testPlan.getId(), testPlan.getNum(), testPlan.getCreateUser());
testPlanCaseService.saveTestPlanResource(associationParam);
testPlanResourceLogService.saveAssociateLog(testPlan, new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, new LogInsertModule(operator, "/test-plan/association", HttpMethodConstants.POST.name())));
}
}
}

View File

@ -133,7 +133,7 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
testPlanGroupService.validateGroupCapacity(targetId, copyPlanList.size());
}
/*
此处不选择批量操作原因有两点
此处不进行批量处理原因有两点
1 测试计划内或者测试计划组内数据量不可控选择批量操作时更容易出现数据太多不走索引数据太多内存溢出等问题不批量操作可以减少这些问题出现的概率代价是速度会变慢
2 作为数据量不可控的操作如果数据量少不采用批量处理也不会消耗太多时间如果数据量多就会容易出现1的问题并且本人不建议针对不可控数据量的数据支持批量操作
*/
@ -168,15 +168,12 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
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 {
if (!StringUtils.equalsIgnoreCase(targetId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
TestPlan group = testPlanMapper.selectByPrimaryKey(targetId);
//如果目标ID是测试计划组 需要进行容量校验
if (!StringUtils.equalsIgnoreCase(targetType, ModuleConstants.NODE_TYPE_DEFAULT)) {
testPlanGroupService.validateGroupCapacity(targetId, 1);
}
pos = testPlanGroupService.getNextOrder(targetId);
moduleId = group.getModuleId();
}
groupId = targetId;
@ -196,7 +193,7 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
testPlan.setUpdateTime(operatorTime);
testPlan.setModuleId(moduleId);
testPlan.setGroupId(groupId);
testPlan.setPos(pos);
testPlan.setPos(testPlanGroupService.getNextOrder(targetId));
testPlan.setActualEndTime(null);
testPlan.setActualStartTime(null);
testPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);
@ -286,6 +283,7 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
testPlanGroup.setUpdateUser(operator);
testPlanGroup.setUpdateTime(operatorTime);
testPlanGroup.setModuleId(moduleId);
testPlanGroup.setPos(testPlanGroupService.getNextOrder(originalGroup.getGroupId()));
testPlanGroup.setActualEndTime(null);
testPlanGroup.setActualStartTime(null);
testPlanGroup.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);

View File

@ -1,110 +0,0 @@
package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanFunctionalCase;
import io.metersphere.plan.domain.TestPlanFunctionalCaseExample;
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper;
import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper;
import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanCaseService {
@Resource
private TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper;
@Resource
private ExtTestPlanFunctionalCaseMapper extTestPlanFunctionalCaseMapper;
public void saveTestPlanResource(@Validated TestPlanResourceAssociationParam associationParam) {
long pox = this.getNextOrder(associationParam.getTestPlanId());
long now = System.currentTimeMillis();
List<TestPlanFunctionalCase> testPlanFunctionalCaseList = new ArrayList<>();
List<String> associationIdList = associationParam.getResourceIdList();
// 批量添加时按照列表顺序进行展示所以这里将集合倒叙排列
Collections.reverse(associationIdList);
for (int i = 0; i < associationIdList.size(); i++) {
TestPlanFunctionalCase testPlanFunctionalCase = new TestPlanFunctionalCase();
testPlanFunctionalCase.setId(IDGenerator.nextStr());
testPlanFunctionalCase.setTestPlanId(associationParam.getTestPlanId());
testPlanFunctionalCase.setFunctionalCaseId(associationIdList.get(i));
testPlanFunctionalCase.setPos(pox);
testPlanFunctionalCase.setCreateTime(now);
testPlanFunctionalCase.setCreateUser(associationParam.getOperator());
testPlanFunctionalCase.setLastExecResult(ExecStatus.PENDING.name());
testPlanFunctionalCase.setExecuteUser(associationParam.getOperator());
testPlanFunctionalCaseList.add(testPlanFunctionalCase);
// TODO 关联逻辑后续改进 默认先写死
testPlanFunctionalCase.setTestPlanCollectionId("NONE");
pox += ServiceUtils.POS_STEP;
}
testPlanFunctionalCaseMapper.batchInsert(testPlanFunctionalCaseList);
}
public long getNextOrder(String testPlanId) {
Long maxPos = extTestPlanFunctionalCaseMapper.getMaxPosByTestPlanId(testPlanId);
if (maxPos == null) {
//默认返回POS_STEP不能直接返回0 否则无法进行前置排序
return ServiceUtils.POS_STEP;
} else {
return maxPos + ServiceUtils.POS_STEP;
}
}
/**
* 复制计划时复制功能用例
*
* @param ids
* @param testPlan
*/
public void saveTestPlanByPlanId(List<String> ids, TestPlan testPlan) {
TestPlanFunctionalCaseExample example = new TestPlanFunctionalCaseExample();
example.createCriteria().andTestPlanIdIn(ids);
List<TestPlanFunctionalCase> testPlanFunctionalCases = testPlanFunctionalCaseMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(testPlanFunctionalCases)) {
Map<String, List<TestPlanFunctionalCase>> collect = testPlanFunctionalCases.stream().collect(Collectors.groupingBy(TestPlanFunctionalCase::getTestPlanId));
List<TestPlanFunctionalCase> associateList = new ArrayList<>();
ids.forEach(id -> {
if (collect.containsKey(id)) {
saveCase(collect.get(id), associateList, testPlan, id);
}
});
testPlanFunctionalCaseMapper.batchInsert(associateList);
}
}
private void saveCase(List<TestPlanFunctionalCase> testPlanFunctionalCases, List<TestPlanFunctionalCase> associateList, TestPlan testPlan, String id) {
AtomicLong pos = new AtomicLong(this.getNextOrder(id));
testPlanFunctionalCases.forEach(item -> {
TestPlanFunctionalCase functionalCase = new TestPlanFunctionalCase();
functionalCase.setTestPlanId(testPlan.getId());
functionalCase.setId(IDGenerator.nextStr());
functionalCase.setCreateTime(System.currentTimeMillis());
functionalCase.setCreateUser(testPlan.getCreateUser());
functionalCase.setFunctionalCaseId(item.getFunctionalCaseId());
functionalCase.setPos(pos.get());
associateList.add(functionalCase);
pos.updateAndGet(v -> v + ServiceUtils.POS_STEP);
});
}
}

View File

@ -245,8 +245,6 @@ public class TestPlanCollectionMinderService {
beansOfType.forEach((k, v) -> {
v.associateCollection(request.getPlanId(), associateMap, user);
});
//更新测试计划
testPlanService.refreshTestPlanStatus(request.getPlanId());
}
private void dealEditList(TestPlanCollectionMinderEditRequest request, String userId, Map<String, List<BaseCollectionAssociateRequest>> associateMap) {

View File

@ -79,13 +79,6 @@ public class TestPlanExecuteSupportService {
postParam.setEndTime(System.currentTimeMillis());
postParam.setExecStatus(isStop ? ExecStatus.STOPPED.name() : ExecStatus.COMPLETED.name());
testPlanReportService.postHandleReport(postParam, false);
if (!isGroupReport) {
TestPlanReport testPlanReport = testPlanReportService.selectById(reportId);
if (testPlanReport != null) {
testPlanService.refreshTestPlanStatus(testPlanReport.getTestPlanId());
}
}
} catch (Exception e) {
LogUtils.error("测试计划报告汇总失败!reportId:" + reportId, e);
TestPlanReport stopReport = testPlanReportService.selectById(reportId);

View File

@ -8,7 +8,6 @@ import io.metersphere.project.dto.MoveNodeSortDTO;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.enums.MoveTypeEnum;
import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
@ -44,10 +43,18 @@ public class TestPlanGroupService extends TestPlanSortService {
}
@Override
public void refreshPos(String groupId) {
public void refreshPos(String rangeId) {
TestPlanExample testPlanExample = new TestPlanExample();
testPlanExample.createCriteria().andGroupIdEqualTo(groupId);
testPlanExample.setOrderByClause("pos asc");
if (StringUtils.contains(rangeId, "_")) {
String[] rangeIds = rangeId.split("_");
String projectId = rangeIds[0];
String testPlanGroupId = rangeIds[1];
testPlanExample.createCriteria().andProjectIdEqualTo(projectId).andGroupIdEqualTo(testPlanGroupId);
} else {
testPlanExample.createCriteria().andGroupIdEqualTo(rangeId);
}
List<TestPlan> testPlans = testPlanMapper.selectByExample(testPlanExample);
long pos = 1;
for (TestPlan testPlanItem : testPlans) {
@ -64,42 +71,50 @@ public class TestPlanGroupService extends TestPlanSortService {
validateMoveRequest(dropPlan, targetPlan, request.getMoveMode());
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
targetPlan.getGroupId(),
this.getNodeMoveRequest(request, false),
this.getNodeMoveRequest(request, true),
extTestPlanMapper::selectDragInfoById,
extTestPlanMapper::selectNodeByPosOperator
);
if (StringUtils.equalsIgnoreCase(sortDTO.getSortRangeId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
sortDTO.setSortRangeId(request.getProjectId() + "_" + TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
}
//判断是否需要刷新排序
if (this.needRefreshBeforeSort(sortDTO.getPreviousNode(), sortDTO.getNextNode())) {
this.refreshPos(sortDTO.getSortRangeId());
dropPlan = testPlanMapper.selectByPrimaryKey(request.getMoveId());
targetPlan = testPlanMapper.selectByPrimaryKey(request.getTargetId());
sortDTO = super.getNodeSortDTO(
targetPlan.getGroupId(),
this.getNodeMoveRequest(request, true),
extTestPlanMapper::selectDragInfoById,
extTestPlanMapper::selectNodeByPosOperator
);
if (StringUtils.equalsIgnoreCase(sortDTO.getSortRangeId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
sortDTO.setSortRangeId(request.getProjectId() + "_" + TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
}
}
this.sort(sortDTO);
}
private void validateMoveRequest(TestPlan dropPlan, TestPlan targetPlan, String moveType) {
//测试计划组不能进行移动操作
if (dropPlan == null || StringUtils.equalsIgnoreCase(dropPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
if (dropPlan == null) {
throw new MSException(Translator.get("test_plan.drag.node.error"));
}
if (targetPlan == null || StringUtils.equalsIgnoreCase(targetPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
if (targetPlan == null) {
throw new MSException(Translator.get("test_plan.drag.node.error"));
}
if (StringUtils.equalsIgnoreCase(MoveTypeEnum.APPEND.name(), moveType)) {
if (!StringUtils.equalsIgnoreCase(targetPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
throw new MSException(Translator.get("test_plan.drag.node.error"));
}
} else if (StringUtils.equalsAnyIgnoreCase(moveType, MoveTypeEnum.BEFORE.name(), MoveTypeEnum.AFTER.name())) {
if (StringUtils.equalsAny(TestPlanConstants.TEST_PLAN_TYPE_GROUP, dropPlan.getType())) {
throw new MSException(Translator.get("test_plan.drag.node.error"));
}
} else {
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)) {
public TestPlan validateGroupCapacity(String groupId, int size) {
// 判断测试计划组是否存在
TestPlan groupPlan = testPlanMapper.selectByPrimaryKey(groupId);
if (groupPlan == null) {
throw new MSException(Translator.get("test_plan.group.error"));
}
if (!StringUtils.equalsIgnoreCase(groupPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
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"));
@ -110,6 +125,6 @@ public class TestPlanGroupService extends TestPlanSortService {
if (testPlanMapper.countByExample(example) + size > 20) {
throw new MSException(Translator.getWithArgs("test_plan.group.children.max", MAX_CHILDREN_COUNT));
}
}
return groupPlan;
}
}

View File

@ -65,7 +65,7 @@ public class TestPlanManagementService {
public Pager<List<TestPlanResponse>> page(TestPlanTableRequest request) {
this.initDefaultFilter(request);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
MapUtils.isEmpty(request.getSort()) ? "t.num desc" : request.getSortString());
MapUtils.isEmpty(request.getSort()) ? "t.pos desc, t.id desc" : request.getSortString("id", "t"));
return PageUtils.setPageInfo(page, this.list(request));
}
@ -102,7 +102,7 @@ public class TestPlanManagementService {
public List<TestPlan> groupList(String projectId) {
TestPlanExample example = new TestPlanExample();
example.createCriteria().andTypeEqualTo(TestPlanConstants.TEST_PLAN_TYPE_GROUP).andProjectIdEqualTo(projectId).andStatusNotEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
example.setOrderByClause("num desc");
example.setOrderByClause("pos desc, id desc");
return testPlanMapper.selectByExample(example);
}

View File

@ -34,10 +34,10 @@ import io.metersphere.system.schedule.ScheduleService;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.BatchProcessUtils;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
@ -78,8 +78,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
@Resource
private TestPlanStatisticsService testPlanStatisticsService;
@Resource
private TestPlanCaseService testPlanCaseService;
@Resource
private ScheduleMapper scheduleMapper;
@Resource
SqlSessionFactory sqlSessionFactory;
@ -115,11 +113,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
//自动生成测试规划
this.initDefaultPlanCollection(testPlan.getId(), operator);
if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
//更新计划组状态
this.updateTestPlanGroupStatus(testPlan.getGroupId());
}
testPlanLogService.saveAddLog(testPlan, operator, requestUrl, requestMethod);
return testPlan;
}
@ -142,11 +135,11 @@ public class TestPlanService extends TestPlanBaseUtilsService {
TestPlan createTestPlan = new TestPlan();
BeanUtils.copyBean(createTestPlan, createOrCopyRequest);
testPlanGroupService.validateGroupCapacity(createTestPlan.getGroupId(), 1);
if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
TestPlan groupPlan = testPlanGroupService.validateGroupCapacity(createTestPlan.getGroupId(), 1);
// 判断测试计划组是否存在
createTestPlan.setModuleId(testPlanMapper.selectByPrimaryKey(createTestPlan.getGroupId()).getModuleId());
createTestPlan.setModuleId(groupPlan.getModuleId());
}
initTestPlanPos(createTestPlan);
@ -171,15 +164,21 @@ public class TestPlanService extends TestPlanBaseUtilsService {
return createTestPlan;
}
//校验测试计划
private void initTestPlanPos(TestPlan createTestPlan) {
if (!StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
createTestPlan.setPos(testPlanGroupService.getNextOrder(createTestPlan.getGroupId()));
if (StringUtils.equals(createTestPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
createTestPlan.setPos(this.getNextOrder(createTestPlan.getProjectId(), createTestPlan.getGroupId()));
} else {
createTestPlan.setPos(0L);
createTestPlan.setPos(testPlanGroupService.getNextOrder(createTestPlan.getGroupId()));
}
}
public long getNextOrder(String projectId, String groupId) {
long maxPos = extTestPlanMapper.selectMaxPosByProjectIdAndGroupId(projectId, groupId);
return maxPos + ServiceUtils.POS_STEP;
}
/**
* 删除测试计划
*/
@ -192,11 +191,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
//级联删除
TestPlanReportService testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
this.cascadeDeleteTestPlanIds(Collections.singletonList(id), testPlanReportService);
if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
//更新计划组状态
this.updateTestPlanGroupStatus(testPlan.getGroupId());
}
}
//记录日志
testPlanLogService.saveDeleteLog(testPlan, operator, requestUrl, requestMethod);
@ -319,44 +313,52 @@ public class TestPlanService extends TestPlanBaseUtilsService {
*/
public TestPlan update(TestPlanUpdateRequest request, String userId, String requestUrl, String requestMethod) {
this.checkTestPlanNotArchived(request.getId());
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getId());
String testPlanGroup = testPlan.getGroupId();
if (!ObjectUtils.allNull(request.getName(), request.getModuleId(), request.getTags(), request.getPlannedEndTime(), request.getPlannedStartTime(), request.getDescription(), request.getGroupId())) {
TestPlan updateTestPlan = new TestPlan();
updateTestPlan.setId(request.getId());
if (StringUtils.isNotBlank(request.getModuleId())) {
TestPlan originalTestPlan = testPlanMapper.selectByPrimaryKey(request.getId());
TestPlan updateTestPlan = new TestPlan();
updateTestPlan.setId(request.getId());
updateTestPlan.setName(request.getName());
updateTestPlan.setPlannedStartTime(request.getPlannedStartTime());
updateTestPlan.setPlannedEndTime(request.getPlannedEndTime());
updateTestPlan.setDescription(request.getDescription());
//判断有没有用户组的变化
if (StringUtils.isNotBlank(request.getGroupId())) {
if (!StringUtils.equalsIgnoreCase(originalTestPlan.getGroupId(), request.getGroupId())) {
//用户更换了测试计划组
TestPlan testPlanGroup = testPlanGroupService.validateGroupCapacity(request.getGroupId(), 1);
updateTestPlan.setGroupId(testPlanGroup.getId());
this.deleteScheduleConfig(request.getId());
updateTestPlan.setPos(testPlanGroupService.getNextOrder(request.getGroupId()));
updateTestPlan.setModuleId(testPlanGroup.getModuleId());
}
} else {
request.setGroupId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
if (!StringUtils.equalsIgnoreCase(originalTestPlan.getGroupId(), request.getGroupId())) {
//移出了测试计划组
this.deleteScheduleConfig(request.getId());
updateTestPlan.setPos(testPlanGroupService.getNextOrder(request.getGroupId()));
}
}
//判断有没有模块的变化
if (StringUtils.isNotBlank(request.getModuleId())) {
if (!StringUtils.equalsIgnoreCase(request.getModuleId(), originalTestPlan.getModuleId())) {
//检查模块的合法性
checkModule(request.getModuleId());
updateTestPlan.setModuleId(request.getModuleId());
//移动模块时重置GroupId
updateTestPlan.setGroupId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
}
if (StringUtils.isNotBlank(request.getGroupId()) && !StringUtils.equalsIgnoreCase(request.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
//移动测试计划到测试计划组中删除定时任务
updateTestPlan.setGroupId(request.getGroupId());
this.deleteScheduleConfig(request.getId());
}
if (StringUtils.isNotBlank(request.getName())) {
updateTestPlan.setName(request.getName());
updateTestPlan.setProjectId(testPlan.getProjectId());
}
if (CollectionUtils.isNotEmpty(request.getTags())) {
updateTestPlan.setTags(new ArrayList<>(request.getTags()));
} else {
updateTestPlan.setTags(new ArrayList<>());
}
updateTestPlan.setPlannedStartTime(request.getPlannedStartTime());
updateTestPlan.setPlannedEndTime(request.getPlannedEndTime());
updateTestPlan.setDescription(request.getDescription());
if (CollectionUtils.isNotEmpty(request.getTags())) {
List<String> tags = new ArrayList<>(request.getTags());
this.checkTagsLength(tags);
updateTestPlan.setTags(tags);
}
updateTestPlan.setType(testPlan.getType());
testPlanMapper.updateByPrimaryKeySelective(updateTestPlan);
}
//判断标签的变化
if (CollectionUtils.isNotEmpty(request.getTags())) {
List<String> tags = new ArrayList<>(request.getTags());
this.checkTagsLength(tags);
updateTestPlan.setTags(tags);
} else {
updateTestPlan.setTags(new ArrayList<>());
}
testPlanMapper.updateByPrimaryKeySelective(updateTestPlan);
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(updateTestPlan.getId());
if (!ObjectUtils.allNull(request.getAutomaticStatusUpdate(), request.getRepeatCase(), request.getPassThreshold(), request.getTestPlanning())) {
TestPlanConfig testPlanConfig = new TestPlanConfig();
testPlanConfig.setTestPlanId(request.getId());
@ -366,11 +368,8 @@ public class TestPlanService extends TestPlanBaseUtilsService {
testPlanConfigMapper.updateByPrimaryKeySelective(testPlanConfig);
}
if (!StringUtils.equalsIgnoreCase(testPlanGroup, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
this.updateTestPlanGroupStatus(testPlanGroup);
}
testPlanLogService.saveUpdateLog(testPlan, testPlanMapper.selectByPrimaryKey(request.getId()), testPlan.getProjectId(), userId, requestUrl, requestMethod);
return testPlan;
return updateTestPlan;
}
@ -466,7 +465,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
/**
* 复制测试计划
*/
public long copy(String testPlanId, String userId) {
public String copy(String testPlanId, String userId) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(testPlanId);
TestPlan copyPlan = null;
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
@ -475,7 +474,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
copyPlan = testPlanBatchOperationService.copyPlan(testPlan, testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_TYPE_GROUP, System.currentTimeMillis(), userId);
}
testPlanLogService.copyLog(copyPlan, userId);
return 1;
return copyPlan.getId();
}
/**
@ -573,15 +572,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
}
public String getModuleName(String id) {
if (ModuleConstants.DEFAULT_NODE_ID.equals(id)) {
return Translator.get("unplanned.plan");
}
TestPlanModule module = testPlanModuleMapper.selectByPrimaryKey(id);
return module == null ? StringUtils.EMPTY : module.getName();
}
/**
* 批量复制 计划/计划组
*
@ -636,7 +626,9 @@ public class TestPlanService extends TestPlanBaseUtilsService {
moveTestPlanList = moveTestPlanList.stream().filter(
item -> StringUtils.equalsIgnoreCase(item.getType(), TestPlanConstants.TEST_PLAN_TYPE_PLAN) && !StringUtils.equalsIgnoreCase(item.getGroupId(), request.getTargetId())
).collect(Collectors.toList());
testPlanGroupService.validateGroupCapacity(request.getTargetId(), moveTestPlanList.size());
if (!StringUtils.equalsIgnoreCase(request.getTargetId(), TestPlanConstants.DEFAULT_PARENT_ID)) {
testPlanGroupService.validateGroupCapacity(request.getTargetId(), moveTestPlanList.size());
}
moveCount = testPlanBatchOperationService.batchMoveGroup(moveTestPlanList, request.getTargetId(), userId);
} else {
moveCount = testPlanBatchOperationService.batchMoveModule(moveTestPlanList, request.getTargetId(), userId);
@ -769,10 +761,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
@Autowired
private ApplicationContext applicationContext;
public void setTestPlanUnderway(String testPlanId) {
this.updateTestPlanStatusAndGroupStatus(testPlanId, TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY);
}
public void setActualStartTime(String testPlanId) {
long actualStartTime = System.currentTimeMillis();
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(testPlanId);
@ -784,92 +772,38 @@ public class TestPlanService extends TestPlanBaseUtilsService {
}
}
private void updateTestPlanStatusAndGroupStatus(String testPlanId, String testPlanStatus) {
TestPlan testPlan = new TestPlan();
testPlan.setId(testPlanId);
testPlan.setStatus(testPlanStatus);
testPlanMapper.updateByPrimaryKeySelective(testPlan);
testPlan = testPlanMapper.selectByPrimaryKey(testPlanId);
if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
this.updateTestPlanGroupStatus(testPlan.getGroupId());
}
}
// private void updateTestPlanStatus(String testPlanId) {
// Map<String, Long> caseExecResultCount = new HashMap<>();
// Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
// beansOfType.forEach((k, v) -> {
// Map<String, Long> map = v.caseExecResultCount(testPlanId);
// map.forEach((key, value) -> {
// if (value != 0) {
// caseExecResultCount.merge(key, value, Long::sum);
// }
// });
// });
//
// String testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY;
// if (MapUtils.isEmpty(caseExecResultCount)) {
// // 没有任何执行结果 状态是未开始
// testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
// extTestPlanMapper.clearActualEndTime(testPlanId);
// } else if (caseExecResultCount.size() == 1 && caseExecResultCount.containsKey(ExecStatus.PENDING.name()) && caseExecResultCount.get(ExecStatus.PENDING.name()) > 0) {
// // 执行结果只有未开始 状态是未开始
// testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
// extTestPlanMapper.clearActualEndTime(testPlanId);
// } else if (!caseExecResultCount.containsKey(ExecStatus.PENDING.name())) {
// // 执行结果没有未开始 已完成
// testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_COMPLETED;
// extTestPlanMapper.setActualEndTime(testPlanId, System.currentTimeMillis());
// }
//
// this.updateTestPlanStatusAndGroupStatus(testPlanId, testPlanFinalStatus);
// }
private void updateTestPlanGroupStatus(String testPlanGroupId) {
//该测试计划是测试计划组内的子计划 要同步计算测试计划组的状态
List<TestPlan> childPlan = this.selectNotArchivedChildren(testPlanGroupId);
String groupStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
// 未开始:计划组为空组内所有计划都是未开始状态
// 已完成:组内计划均为已完成状态
// 进行中:组内计划有未完成的状态
if (CollectionUtils.isNotEmpty(childPlan)) {
List<String> testPlanStatus = childPlan.stream().map(TestPlan::getStatus).distinct().toList();
if (testPlanStatus.size() == 1) {
if (StringUtils.equals(testPlanStatus.getFirst(), TestPlanConstants.TEST_PLAN_STATUS_COMPLETED)) {
groupStatus = TestPlanConstants.TEST_PLAN_STATUS_COMPLETED;
} else if (StringUtils.equals(testPlanStatus.getFirst(), TestPlanConstants.TEST_PLAN_STATUS_PREPARED)) {
groupStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
} else if (StringUtils.equals(testPlanStatus.getFirst(), TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY)) {
groupStatus = TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY;
}
} else {
groupStatus = TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY;
}
}
TestPlanExample testPlanExample = new TestPlanExample();
testPlanExample.createCriteria().andIdEqualTo(testPlanGroupId).andStatusNotEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
TestPlan updateGroupPlan = new TestPlan();
updateGroupPlan.setStatus(groupStatus);
testPlanMapper.updateByExampleSelective(updateGroupPlan, testPlanExample);
if (StringUtils.equalsIgnoreCase(updateGroupPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_COMPLETED)) {
extTestPlanMapper.setActualEndTime(testPlanGroupId, System.currentTimeMillis());
}
}
public void refreshTestPlanStatus(String testPlanId) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(testPlanId);
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_PLAN)) {
this.updateTestPlanStatus(testPlanId);
} else {
if (!StringUtils.equalsIgnoreCase(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
this.updateTestPlanGroupStatus(testPlan.getGroupId());
}
}
}
private void updateTestPlanStatus(String testPlanId) {
Map<String, Long> caseExecResultCount = new HashMap<>();
Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
beansOfType.forEach((k, v) -> {
Map<String, Long> map = v.caseExecResultCount(testPlanId);
map.forEach((key, value) -> {
if (value != 0) {
caseExecResultCount.merge(key, value, Long::sum);
}
});
});
String testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY;
if (MapUtils.isEmpty(caseExecResultCount)) {
// 没有任何执行结果 状态是未开始
testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
extTestPlanMapper.clearActualEndTime(testPlanId);
} else if (caseExecResultCount.size() == 1 && caseExecResultCount.containsKey(ExecStatus.PENDING.name()) && caseExecResultCount.get(ExecStatus.PENDING.name()) > 0) {
// 执行结果只有未开始 状态是未开始
testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
extTestPlanMapper.clearActualEndTime(testPlanId);
} else if (!caseExecResultCount.containsKey(ExecStatus.PENDING.name())) {
// 执行结果没有未开始 已完成
testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_COMPLETED;
extTestPlanMapper.setActualEndTime(testPlanId, System.currentTimeMillis());
}
this.updateTestPlanStatusAndGroupStatus(testPlanId, testPlanFinalStatus);
}
public TestPlanOperationResponse sortInGroup(PosRequest request, LogInsertModule logInsertModule) {
public TestPlanOperationResponse sort(PosRequest request, LogInsertModule logInsertModule) {
testPlanGroupService.sort(request);
testPlanLogService.saveMoveLog(testPlanMapper.selectByPrimaryKey(request.getMoveId()), request.getMoveId(), logInsertModule);
return new TestPlanOperationResponse(1);
@ -920,7 +854,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
public List<TestPlan> selectNotArchivedChildren(String testPlanGroupId) {
TestPlanExample example = new TestPlanExample();
example.createCriteria().andGroupIdEqualTo(testPlanGroupId).andStatusNotEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
example.setOrderByClause("pos asc");
example.setOrderByClause("pos desc");
return testPlanMapper.selectByExample(example);
}
@ -1023,7 +957,6 @@ public class TestPlanService extends TestPlanBaseUtilsService {
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
public void setExecuteConfig(String testPlanId, String testPlanReportId) {
this.setActualStartTime(testPlanId);
this.setTestPlanUnderway(testPlanId);
if (StringUtils.isNotBlank(testPlanReportId)) {
testPlanReportService.updateExecuteTimeAndStatus(testPlanReportId);
}

View File

@ -4,7 +4,10 @@ import io.metersphere.api.domain.ApiScenario;
import io.metersphere.api.domain.ApiTestCase;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.plan.constants.TestPlanResourceConfig;
import io.metersphere.plan.domain.*;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanConfig;
import io.metersphere.plan.domain.TestPlanExample;
import io.metersphere.plan.domain.TestPlanReport;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
import io.metersphere.plan.dto.response.TestPlanResponse;
@ -18,8 +21,10 @@ import io.metersphere.plan.utils.TestPlanTestUtils;
import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.filemanagement.request.FileModuleCreateRequest;
import io.metersphere.project.dto.filemanagement.request.FileModuleUpdateRequest;
import io.metersphere.project.utils.NodeSortUtils;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON;
@ -122,7 +127,6 @@ public class TestPlanTests extends BaseTest {
private static final String URL_POST_TEST_PLAN_SCHEDULE_DELETE = "/test-plan/schedule-config-delete/%s";
//测试计划资源-功能用例
private static final String URL_POST_RESOURCE_CASE_ASSOCIATION = "/test-plan/association";
private static final String URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT = "/test-plan/functional/case/sort";
private static final String URL_TEST_PLAN_EDIT_FOLLOWER = "/test-plan/edit/follower";
@ -577,10 +581,10 @@ public class TestPlanTests extends BaseTest {
groupTestPlanId15 = returnId;
} else if (i == 35) {
groupTestPlanId35 = returnId;
} else if (i > 700 && i < 750) {
} else if (i > 700 && i < 725) {
// 701-749 要创建测试计划报告 每个测试计划创建250个报告
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestPlanReportMapper batchInsert = sqlSession.getMapper(TestPlanReportMapper.class);
// 701-749 要创建测试计划报告 每个测试计划创建250个报告
for (int reportCount = 0; reportCount < 250; reportCount++) {
TestPlanReport testPlanReport = new TestPlanReport();
testPlanReport.setId(IDGenerator.nextStr());
@ -633,11 +637,6 @@ public class TestPlanTests extends BaseTest {
testPlanTestService.checkTestPlanByAddTest();
simpleTestPlan = testPlanTestService.selectTestPlanByName("testPlan_13");
repeatCaseTestPlan = testPlanTestService.selectTestPlanByName("testPlan_123");
//测试继续创建10个
for (int i = 0; i < 10; i++) {
request.setName("testPlan_1000_" + i);
this.requestPost(URL_POST_TEST_PLAN_ADD, request);
}
//在groupTestPlanId7groupTestPlanId15下面各创建20条数据并且校验第21条不能创建成功
for (int i = 0; i < 21; i++) {
@ -702,8 +701,8 @@ public class TestPlanTests extends BaseTest {
request.setModuleId(IDGenerator.nextStr());
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError());
request.setModuleId(a1Node.getId());
request.setGroupId(testPlanTestService.selectTestPlanByName("testPlan_60").getGroupId());
this.requestPost(URL_POST_TEST_PLAN_ADD, request);
request.setGroupId(testPlanTestService.selectTestPlanByName("testPlan_60").getId());
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError());
request.setGroupId(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID);
request.setPassThreshold(100.11);
this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().isBadRequest());
@ -715,6 +714,7 @@ public class TestPlanTests extends BaseTest {
request.setPassThreshold(100);
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_ADD, URL_POST_TEST_PLAN_ADD, request);
this.checkTestPlanSortWithOutGroup();
this.checkTestPlanSortInGroup(groupTestPlanId7);
this.checkTestPlanMoveToGroup();
this.checkTestPlanGroupArchived(groupTestPlanId7);
@ -729,6 +729,65 @@ public class TestPlanTests extends BaseTest {
TestPlanResponse.class);
}
protected void checkTestPlanSortWithOutGroup() throws Exception {
TestPlanTableRequest dataRequest = new TestPlanTableRequest();
dataRequest.setProjectId(project.getId());
dataRequest.setType("ALL");
dataRequest.setPageSize(10);
dataRequest.setCurrent(1);
//提前校验
List<TestPlanResponse> tableList = testPlanTestService.getTestPlanResponse(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8));
Assertions.assertTrue(tableList.get(0).getId().equals(rootPlanIds.getLast()));
/*
排序校验用例设计
1.第一个移动到最后一个
2.最后一个移动到第一个还原为原来的顺序
3.第三个移动到第二个
4.修改第一个和第二个之间的pos差小于2将第三个移动到第二个还原为原来的顺序并检查pos有没有初始化
*/
// 1.第一个移动到最后一个
PosRequest posRequest = new PosRequest(project.getId(), rootPlanIds.getLast(), rootPlanIds.getFirst(), MoveTypeEnum.AFTER.name());
this.requestPostWithOk(URL_POST_TEST_PLAN_SORT, posRequest);
tableList = testPlanTestService.getTestPlanResponse(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8));
Assertions.assertTrue(tableList.get(0).getId().equals(rootPlanIds.get(rootPlanIds.size() - 2)));
// 2.最后一个移动到第一个还原为原来的顺序
posRequest.setTargetId(tableList.getFirst().getId());
posRequest.setMoveMode(MoveTypeEnum.BEFORE.name());
this.requestPostWithOk(URL_POST_TEST_PLAN_SORT, posRequest);
tableList = testPlanTestService.getTestPlanResponse(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8));
Assertions.assertTrue(tableList.get(0).getId().equals(rootPlanIds.getLast()));
// 3.第三个移动到第二个
posRequest = new PosRequest(project.getId(), rootPlanIds.get(rootPlanIds.size() - 3), rootPlanIds.get(rootPlanIds.size() - 2), MoveTypeEnum.BEFORE.name());
this.requestPostWithOk(URL_POST_TEST_PLAN_SORT, posRequest);
tableList = testPlanTestService.getTestPlanResponse(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8));
Assertions.assertTrue(tableList.get(0).getId().equals(rootPlanIds.getLast()));
Assertions.assertTrue(tableList.get(1).getId().equals(posRequest.getMoveId()));
Assertions.assertTrue(tableList.get(2).getId().equals(posRequest.getTargetId()));
// 4.修改第一个只比第二个大1将第三个移动到第二个还原为原来的顺序并检查pos有没有初始化
TestPlan updatePlan = new TestPlan();
updatePlan.setId(rootPlanIds.getLast());
updatePlan.setPos(tableList.get(1).getPos() + 1);
testPlanMapper.updateByPrimaryKeySelective(updatePlan);
posRequest.setMoveId(rootPlanIds.get(rootPlanIds.size() - 2));
posRequest.setTargetId(rootPlanIds.get(rootPlanIds.size() - 3));
posRequest.setMoveMode(MoveTypeEnum.BEFORE.name());
this.requestPostWithOk(URL_POST_TEST_PLAN_SORT, posRequest);
tableList = testPlanTestService.getTestPlanResponse(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8));
Assertions.assertTrue(tableList.get(0).getId().equals(rootPlanIds.getLast()));
Assertions.assertTrue(tableList.get(1).getId().equals(posRequest.getMoveId()));
Assertions.assertTrue(tableList.get(2).getId().equals(posRequest.getTargetId()));
}
protected void checkTestPlanSortInGroup(String groupId) throws Exception {
/*
排序校验用例设计
@ -812,7 +871,7 @@ public class TestPlanTests extends BaseTest {
targetPlan = lastTestPlanInGroup.get(1);
TestPlan updatePlan = new TestPlan();
updatePlan.setId(targetPlan.getId());
updatePlan.setPos(lastTestPlanInGroup.get(0).getPos() + 2);
updatePlan.setPos(lastTestPlanInGroup.get(0).getPos() - 2);
testPlanMapper.updateByPrimaryKeySelective(updatePlan);
posRequest = new PosRequest(project.getId(), movePlan.getId(), targetPlan.getId(), MoveTypeEnum.BEFORE.name());
@ -826,11 +885,9 @@ public class TestPlanTests extends BaseTest {
newTestPlanInGroup = this.selectByGroupId(groupId);
Assertions.assertEquals(response.getOperationCount(), 1);
Assertions.assertEquals(newTestPlanInGroup.size(), lastTestPlanInGroup.size());
long lastPos = 0;
for (int newListIndex = 0; newListIndex < newTestPlanInGroup.size(); newListIndex++) {
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getId(), defaultTestPlanInGroup.get(newListIndex).getId());
Assertions.assertTrue(newTestPlanInGroup.get(newListIndex).getPos() == (lastPos + NodeSortUtils.DEFAULT_NODE_INTERVAL_POS));
lastPos = newTestPlanInGroup.get(newListIndex).getPos();
Assertions.assertEquals(newTestPlanInGroup.get(newListIndex).getPos(), defaultTestPlanInGroup.get(newListIndex).getPos());
}
//测试权限
@ -958,12 +1015,15 @@ public class TestPlanTests extends BaseTest {
BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(preliminaryTreeNodes, "a1-b1");
assert a1Node != null & a2Node != null & a3Node != null & a1a1Node != null & a1b1Node != null;
TestPlanExample example = new TestPlanExample();
example.createCriteria().andProjectIdEqualTo(project.getId()).andGroupIdEqualTo("NONE").andStatusEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
long count = testPlanMapper.countByExample(example);
//此时有一个归档的
testPlanTestService.checkTestPlanPage(this.requestPostWithOkAndReturn(
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
dataRequest.getCurrent(),
dataRequest.getPageSize(),
1010 - 1);
999 - 1);
//查询归档的
dataRequest.setFilter(new HashMap<>() {{
this.put("status", Collections.singletonList(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED));
@ -984,7 +1044,7 @@ public class TestPlanTests extends BaseTest {
URL_POST_TEST_PLAN_PAGE, onlyPlanRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
dataRequest.getCurrent(),
dataRequest.getPageSize(),
1007);
996);
//按照名称倒叙
dataRequest.setSort(new HashMap<>() {{
@ -995,7 +1055,7 @@ public class TestPlanTests extends BaseTest {
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
dataRequest.getCurrent(),
dataRequest.getPageSize(),
1010 - 1);
999 - 1);
//指定模块ID查询 (查询count时不会因为选择了模块而更改了总量
@ -1008,7 +1068,7 @@ public class TestPlanTests extends BaseTest {
URL_POST_TEST_PLAN_PAGE, dataRequest).getResponse().getContentAsString(StandardCharsets.UTF_8),
dataRequest.getCurrent(),
dataRequest.getPageSize(),
910 - 1);
899 - 1);
//测试根据名称模糊查询 Plan_2 预期结果 a1Node下有11条testPlan_2,testPlan_20~testPlan_29), a1b1Node下有100条testPlan_200~testPlan_299
dataRequest.setModuleIds(null);
@ -1183,11 +1243,11 @@ public class TestPlanTests extends BaseTest {
//修改a2节点下的数据91,92的所属测试计划组
updateRequest = testPlanTestService.generateUpdateRequest(testPlanTestService.selectTestPlanByName("testPlan_91").getId());
updateRequest.setGroupId(groupTestPlanId7);
updateRequest.setGroupId(groupTestPlanId35);
this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest);
a2NodeCount--;
updateRequest = testPlanTestService.generateUpdateRequest(testPlanTestService.selectTestPlanByName("testPlan_92").getId());
updateRequest.setGroupId(groupTestPlanId7);
updateRequest.setGroupId(groupTestPlanId35);
this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest);
a2NodeCount--;
@ -1195,7 +1255,6 @@ public class TestPlanTests extends BaseTest {
updatePlan.setId(groupTestPlanId7);
updatePlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_UNDERWAY);
testPlanMapper.updateByPrimaryKeySelective(updatePlan);
//修改测试计划组信息
updateRequest = testPlanTestService.generateUpdateRequest(groupTestPlanId7);
updateRequest.setName(IDGenerator.nextStr());
@ -1239,137 +1298,6 @@ public class TestPlanTests extends BaseTest {
}
@Test
@Order(21)
public void testPlanAssociationFunctionCase() throws Exception {
if (ObjectUtils.anyNull(simpleTestPlan, repeatCaseTestPlan)) {
this.testPlanAddTest();
}
//创建20个功能测试用例
FUNCTIONAL_CASES.addAll(testPlanTestService.createFunctionCase(20, project.getId()));
//测试不开启用例重复的测试计划多次关联
TestPlanAssociationRequest request = new TestPlanAssociationRequest();
request.setTestPlanId(simpleTestPlan.getId());
request.setFunctionalSelectIds(FUNCTIONAL_CASES.stream().map(FunctionalCase::getId).collect(Collectors.toList()));
MvcResult result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
String returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
//先测试一下没有开启模块时能否使用
testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "caseManagement");
this.requestPost(URL_POST_RESOURCE_CASE_ASSOCIATION, request).andExpect(status().is5xxServerError());
//恢复
testPlanTestService.resetProjectModule(project, PROJECT_MODULE);
result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
//测试开启用例重复的测试计划多次关联
request.setTestPlanId(repeatCaseTestPlan.getId());
result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
}
@Test
@Order(22)
public void testPlanFunctionCaseSort() throws Exception {
if (FUNCTIONAL_CASES.isEmpty()) {
this.testPlanAssociationFunctionCase();
}
String collectionId = IDGenerator.nextStr();
List<TestPlanFunctionalCase> funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId());
funcList.forEach(item -> {
TestPlanFunctionalCase updateModel = new TestPlanFunctionalCase();
updateModel.setId(item.getId());
updateModel.setTestPlanCollectionId(collectionId);
testPlanFunctionalCaseMapper.updateByPrimaryKeySelective(updateModel);
});
//将第30个移动到第一位之前
ResourceSortRequest request = new ResourceSortRequest();
request.setTestCollectionId(funcList.getFirst().getTestPlanCollectionId());
request.setProjectId(DEFAULT_PROJECT_ID);
request.setMoveId(funcList.get(29).getId());
request.setTargetId(funcList.get(0).getId());
request.setMoveMode(MoveTypeEnum.BEFORE.name());
//恢复
testPlanTestService.resetProjectModule(project, PROJECT_MODULE);
MvcResult result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request);
ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
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());
LOG_CHECK_LIST.add(
new CheckLogModel(request.getMoveId(), OperationLogType.UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT)
);
//将这时的第30个放到第一位之后
request.setMoveId(funcList.get(29).getId());
request.setTargetId(funcList.get(0).getId());
request.setMoveMode(MoveTypeEnum.AFTER.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()), 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());
LOG_CHECK_LIST.add(
new CheckLogModel(request.getMoveId(), OperationLogType.UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT)
);
//再将这时的第30个放到第一位之前,但是第一个的pos为2检查能否触发ref操作
request.setMoveId(funcList.get(29).getId());
request.setTargetId(funcList.get(0).getId());
request.setMoveMode(MoveTypeEnum.BEFORE.name());
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()), 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());
LOG_CHECK_LIST.add(
new CheckLogModel(request.getMoveId(), OperationLogType.UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT)
);
//反例测试集为空
request.setTestCollectionId(null);
this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().isBadRequest());
//反例拖拽的节点不存在
request.setTestCollectionId(funcList.getFirst().getTestPlanCollectionId());
request.setMoveId(null);
this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().isBadRequest());
//反例目标节点不存在
request.setMoveId(funcList.get(29).getId());
request.setTargetId(null);
this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().isBadRequest());
//反例 节点重复
request.setTargetId(request.getMoveId());
this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().is5xxServerError());
//测试权限
request.setMoveMode(MoveTypeEnum.BEFORE.name());
this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request);
}
@Test
@Order(61)
public void scheduleTest() throws Exception {
@ -2276,20 +2204,6 @@ public class TestPlanTests extends BaseTest {
}
@Test
@Order(305)
public void testAssociation() throws Exception {
TestPlanAssociationRequest request = new TestPlanAssociationRequest();
request.setTestPlanId("wx_test_plan_id_2");
this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
request.setFunctionalSelectIds(Arrays.asList("my_test_1", "my_test_2", "my_test_3"));
this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
//测试归档的关联会报错
request.setTestPlanId("wx_test_plan_id_1");
this.requestPost(URL_POST_RESOURCE_CASE_ASSOCIATION, request).andExpect(status().is5xxServerError());
}
@Test
@Order(306)
public void testStatistics() throws Exception {

View File

@ -10,6 +10,7 @@ import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.request.TestPlanUpdateRequest;
import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.job.TestPlanScheduleJob;
import io.metersphere.plan.mapper.*;
import io.metersphere.project.domain.Project;
@ -434,6 +435,13 @@ public class TestPlanTestService {
});
}
public List<TestPlanResponse> getTestPlanResponse(String returnData) {
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Pager<Object> result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
List<TestPlanResponse> returnList = JSON.parseArray(JSON.toJSONString(result.getList()), TestPlanResponse.class);
return returnList;
}
public void checkTestPlanPage(String returnData, long current, long pageSize, long allData) {
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Pager<Object> result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);