feat(测试计划): 测试计划增加自动计算状态的功能

在关联/取消资源、 执行用例时, 进行状态自动计算
This commit is contained in:
Jianguo-Genius 2024-05-22 14:18:16 +08:00 committed by Craftsman
parent bb100c6715
commit 00455b06a8
28 changed files with 223 additions and 127 deletions

View File

@ -13,7 +13,7 @@ public enum ExecStatus {
*/ */
RUNNING, RUNNING,
/** /**
* 重新执行 * 重新执行
*/ */
RERUNNING, RERUNNING,
/** /**
@ -21,7 +21,25 @@ public enum ExecStatus {
*/ */
STOPPED, STOPPED,
/** /**
* 完成 * 完成
*/ */
COMPLETED COMPLETED,
/**
* 通过
*/
SUCCESS,
/**
* 失败
*/
ERROR,
/**
* 阻塞
*/
BLOCKED,
/**
* 误报
*/
FAKE_ERROR
} }

View File

@ -1,9 +0,0 @@
package io.metersphere.sdk.constants;
/**
* 功能用例执行状态
*/
public enum FunctionCaseExecuteStatus {
//未开始成功失败阻塞
PENDING, SUCCESS, ERROR, BLOCK
}

View File

@ -1,25 +0,0 @@
package io.metersphere.sdk.constants;
public enum FunctionalCaseExecuteResult {
/**
* 未执行
*/
PENDING,
/**
* 通过
*/
SUCCESS,
/**
* 失败
*/
ERROR,
/**
* 阻塞
*/
BLOCKED,
/**
* 误报
*/
FAKE_ERROR
}

View File

@ -10,7 +10,7 @@ import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper; import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.utils.NodeSortUtils; import io.metersphere.project.utils.NodeSortUtils;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
@ -734,7 +734,7 @@ public class FunctionalCaseMinderService {
functionalCase.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name()); functionalCase.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name());
functionalCase.setPos(functionalCaseService.getNextOrder(functionalCase.getProjectId())); functionalCase.setPos(functionalCaseService.getNextOrder(functionalCase.getProjectId()));
functionalCase.setRefId(caseId); functionalCase.setRefId(caseId);
functionalCase.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functionalCase.setLastExecuteResult(ExecStatus.PENDING.name());
functionalCase.setLatest(true); functionalCase.setLatest(true);
functionalCase.setCreateUser(userId); functionalCase.setCreateUser(userId);
functionalCase.setUpdateUser(userId); functionalCase.setUpdateUser(userId);

View File

@ -289,7 +289,7 @@ public class FunctionalCaseService {
functionalCase.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name()); functionalCase.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name());
functionalCase.setPos(getNextOrder(request.getProjectId())); functionalCase.setPos(getNextOrder(request.getProjectId()));
functionalCase.setRefId(caseId); functionalCase.setRefId(caseId);
functionalCase.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functionalCase.setLastExecuteResult(ExecStatus.PENDING.name());
functionalCase.setLatest(true); functionalCase.setLatest(true);
functionalCase.setCreateUser(userId); functionalCase.setCreateUser(userId);
functionalCase.setUpdateUser(userId); functionalCase.setUpdateUser(userId);
@ -818,7 +818,7 @@ public class FunctionalCaseService {
functional.setName(getCopyName(functionalCase.getName(), num, functional.getNum())); functional.setName(getCopyName(functionalCase.getName(), num, functional.getNum()));
functional.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name()); functional.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name());
functional.setPos(nextOrder.get()); functional.setPos(nextOrder.get());
functional.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functional.setLastExecuteResult(ExecStatus.PENDING.name());
functional.setCreateUser(userId); functional.setCreateUser(userId);
functional.setUpdateUser(userId); functional.setUpdateUser(userId);
functional.setCreateTime(System.currentTimeMillis()); functional.setCreateTime(System.currentTimeMillis());
@ -987,8 +987,9 @@ public class FunctionalCaseService {
List<ModuleCountDTO> moduleCountDTOList = extFunctionalCaseMapper.countModuleIdByRequest(request, delete); List<ModuleCountDTO> moduleCountDTOList = extFunctionalCaseMapper.countModuleIdByRequest(request, delete);
Map<String, Long> moduleCountMap = functionalCaseModuleService.getModuleCountMap(request.getProjectId(), moduleCountDTOList); Map<String, Long> moduleCountMap = functionalCaseModuleService.getModuleCountMap(request.getProjectId(), moduleCountDTOList);
//查出全部用例数量 //查出全部用例数量
long allCount = extFunctionalCaseMapper.caseCount(request, delete); AtomicLong allCount = new AtomicLong(0);
moduleCountMap.put(CASE_MODULE_COUNT_ALL, allCount); moduleCountDTOList.forEach(item -> allCount.addAndGet(item.getDataCount()));
moduleCountMap.put(CASE_MODULE_COUNT_ALL, allCount.get());
return moduleCountMap; return moduleCountMap;
} }
@ -1135,7 +1136,7 @@ public class FunctionalCaseService {
functionalCase.setPos(nextOrder); functionalCase.setPos(nextOrder);
functionalCase.setVersionId(request.getVersionId()); functionalCase.setVersionId(request.getVersionId());
functionalCase.setRefId(caseId); functionalCase.setRefId(caseId);
functionalCase.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functionalCase.setLastExecuteResult(ExecStatus.PENDING.name());
functionalCase.setLatest(true); functionalCase.setLatest(true);
functionalCase.setCreateUser(userId); functionalCase.setCreateUser(userId);
functionalCase.setUpdateUser(userId); functionalCase.setUpdateUser(userId);

View File

@ -11,7 +11,7 @@ import io.metersphere.functional.request.FunctionalCaseModuleUpdateRequest;
import io.metersphere.functional.service.FunctionalCaseModuleService; import io.metersphere.functional.service.FunctionalCaseModuleService;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
@ -763,7 +763,7 @@ public class FunctionalCaseModuleControllerTests extends BaseTest {
functionalCase.setPos(500L); functionalCase.setPos(500L);
functionalCase.setVersionId("12335"); functionalCase.setVersionId("12335");
functionalCase.setRefId(functionalCase.getId()); functionalCase.setRefId(functionalCase.getId());
functionalCase.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functionalCase.setLastExecuteResult(ExecStatus.PENDING.name());
functionalCase.setPublicCase(false); functionalCase.setPublicCase(false);
functionalCase.setLatest(true); functionalCase.setLatest(true);
functionalCase.setCreateUser("gyq"); functionalCase.setCreateUser("gyq");

View File

@ -25,7 +25,7 @@ import io.metersphere.provider.BaseAssociateApiProvider;
import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.provider.BaseAssociateScenarioProvider; import io.metersphere.provider.BaseAssociateScenarioProvider;
import io.metersphere.request.*; import io.metersphere.request.*;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
@ -450,7 +450,7 @@ public class FunctionalTestCaseControllerTests extends BaseTest {
functionalCase.setPos(500L); functionalCase.setPos(500L);
functionalCase.setVersionId("12335"); functionalCase.setVersionId("12335");
functionalCase.setRefId(functionalCase.getId()); functionalCase.setRefId(functionalCase.getId());
functionalCase.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functionalCase.setLastExecuteResult(ExecStatus.PENDING.name());
functionalCase.setPublicCase(false); functionalCase.setPublicCase(false);
functionalCase.setLatest(true); functionalCase.setLatest(true);
functionalCase.setCreateUser("gyq"); functionalCase.setCreateUser("gyq");

View File

@ -119,7 +119,7 @@ public class TestPlanController {
@PostMapping("/copy") @PostMapping("/copy")
@Operation(summary = "测试计划-复制测试计划") @Operation(summary = "测试计划-复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
@Log(type = OperationLogType.COPY, expression = "#msClass.copyLog(#request)", msClass = TestPlanLogService.class) @Log(type = OperationLogType.COPY, expression = "#msClass.copyLog(#request)", msClass = TestPlanLogService.class)
public TestPlan copy(@Validated @RequestBody TestPlanCopyRequest request) { public TestPlan copy(@Validated @RequestBody TestPlanCopyRequest request) {
@ -140,13 +140,12 @@ public class TestPlanController {
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void delete(@Validated @RequestBody TestPlanBatchProcessRequest request) throws Exception { public void delete(@Validated @RequestBody TestPlanBatchProcessRequest request) throws Exception {
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
testPlanService.filterArchivedIds(request);
testPlanService.batchDelete(request, SessionUtils.getUserId(), "/test-plan/batch-delete", HttpMethodConstants.POST.name()); testPlanService.batchDelete(request, SessionUtils.getUserId(), "/test-plan/batch-delete", HttpMethodConstants.POST.name());
} }
@PostMapping("/batch-copy") @PostMapping("/batch-copy")
@Operation(summary = "测试计划-批量复制测试计划") @Operation(summary = "测试计划-批量复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchCopy(@Validated @RequestBody TestPlanBatchRequest request) { public void batchCopy(@Validated @RequestBody TestPlanBatchRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
@ -181,6 +180,7 @@ public class TestPlanController {
testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE)); testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE));
testPlanService.checkTestPlanNotArchived(request.getTestPlanId()); testPlanService.checkTestPlanNotArchived(request.getTestPlanId());
testPlanService.association(request); testPlanService.association(request);
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
} }
@PostMapping("/batch-edit") @PostMapping("/batch-edit")

View File

@ -9,6 +9,7 @@ import io.metersphere.plan.dto.response.*;
import io.metersphere.plan.service.TestPlanCaseLogService; import io.metersphere.plan.service.TestPlanCaseLogService;
import io.metersphere.plan.service.TestPlanFunctionalCaseService; import io.metersphere.plan.service.TestPlanFunctionalCaseService;
import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanManagementService;
import io.metersphere.plan.service.TestPlanService;
import io.metersphere.request.AssociateBugPageRequest; import io.metersphere.request.AssociateBugPageRequest;
import io.metersphere.request.BugPageProviderRequest; import io.metersphere.request.BugPageProviderRequest;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
@ -40,6 +41,8 @@ import java.util.Map;
@RequestMapping("/test-plan/functional/case") @RequestMapping("/test-plan/functional/case")
public class TestPlanFunctionalCaseController { public class TestPlanFunctionalCaseController {
@Resource
private TestPlanService testPlanService;
@Resource @Resource
private TestPlanManagementService testPlanManagementService; private TestPlanManagementService testPlanManagementService;
@Resource @Resource
@ -88,7 +91,9 @@ public class TestPlanFunctionalCaseController {
BasePlanCaseBatchRequest batchRequest = new BasePlanCaseBatchRequest(); BasePlanCaseBatchRequest batchRequest = new BasePlanCaseBatchRequest();
batchRequest.setTestPlanId(request.getTestPlanId()); batchRequest.setTestPlanId(request.getTestPlanId());
batchRequest.setSelectIds(List.of(request.getId())); batchRequest.setSelectIds(List.of(request.getId()));
return testPlanFunctionalCaseService.disassociate(batchRequest, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/association", HttpMethodConstants.POST.name())); TestPlanAssociationResponse response = testPlanFunctionalCaseService.disassociate(batchRequest, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/association", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
} }
@PostMapping("/batch/disassociate") @PostMapping("/batch/disassociate")
@ -97,7 +102,9 @@ public class TestPlanFunctionalCaseController {
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public TestPlanAssociationResponse batchDisassociate(@Validated @RequestBody BasePlanCaseBatchRequest request) { public TestPlanAssociationResponse batchDisassociate(@Validated @RequestBody BasePlanCaseBatchRequest request) {
testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE)); testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE));
return testPlanFunctionalCaseService.disassociate(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/association", HttpMethodConstants.POST.name())); TestPlanAssociationResponse response = testPlanFunctionalCaseService.disassociate(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/association", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
return response;
} }
@PostMapping("/associate/bug/page") @PostMapping("/associate/bug/page")
@ -130,7 +137,8 @@ public class TestPlanFunctionalCaseController {
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public void run(@Validated @RequestBody TestPlanCaseRunRequest request) { public void run(@Validated @RequestBody TestPlanCaseRunRequest request) {
testPlanFunctionalCaseService.run(request, SessionUtils.getCurrentOrganizationId(), new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/run", HttpMethodConstants.POST.name())); testPlanFunctionalCaseService.run(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/run", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
} }
@PostMapping("/batch/run") @PostMapping("/batch/run")
@ -138,7 +146,8 @@ public class TestPlanFunctionalCaseController {
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public void batchRun(@Validated @RequestBody TestPlanCaseBatchRunRequest request) { public void batchRun(@Validated @RequestBody TestPlanCaseBatchRunRequest request) {
testPlanFunctionalCaseService.batchRun(request, SessionUtils.getCurrentOrganizationId(), new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/batch/run", HttpMethodConstants.POST.name())); testPlanFunctionalCaseService.batchRun(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/batch/run", HttpMethodConstants.POST.name()));
testPlanService.refreshTestPlanStatus(request.getTestPlanId());
} }
@PostMapping("/has/associate/bug/page") @PostMapping("/has/associate/bug/page")

View File

@ -10,10 +10,7 @@ import io.metersphere.plan.dto.ReportDetailCasePageDTO;
import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanReportDetailResponse; import io.metersphere.plan.dto.response.TestPlanReportDetailResponse;
import io.metersphere.plan.dto.response.TestPlanReportPageResponse; import io.metersphere.plan.dto.response.TestPlanReportPageResponse;
import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.*;
import io.metersphere.plan.service.TestPlanReportLogService;
import io.metersphere.plan.service.TestPlanReportNoticeService;
import io.metersphere.plan.service.TestPlanReportService;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
@ -46,6 +43,8 @@ public class TestPlanReportController {
private TestPlanManagementService testPlanManagementService; private TestPlanManagementService testPlanManagementService;
@Resource @Resource
private TestPlanReportService testPlanReportService; private TestPlanReportService testPlanReportService;
@Resource
private TestPlanService testPlanService;
@PostMapping("/page") @PostMapping("/page")
@Operation(summary = "测试计划-报告-表格分页查询") @Operation(summary = "测试计划-报告-表格分页查询")
@ -90,6 +89,7 @@ public class TestPlanReportController {
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
public TestPlanReport genReportByManual(@Validated @RequestBody TestPlanReportGenRequest request) { public TestPlanReport genReportByManual(@Validated @RequestBody TestPlanReportGenRequest request) {
testPlanService.checkTestPlanNotArchived(request.getTestPlanId());
return testPlanReportService.genReportByManual(request, SessionUtils.getUserId()); return testPlanReportService.genReportByManual(request, SessionUtils.getUserId());
} }

View File

@ -0,0 +1,9 @@
package io.metersphere.plan.dto;
import lombok.Data;
@Data
public class TestPlanCaseRunResultCount {
private String result;
private Long resultCount;
}

View File

@ -2,6 +2,7 @@ package io.metersphere.plan.mapper;
import io.metersphere.plan.dto.AssociationNode; import io.metersphere.plan.dto.AssociationNode;
import io.metersphere.plan.dto.ResourceSelectParam; import io.metersphere.plan.dto.ResourceSelectParam;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.project.dto.NodeSortQueryParam; import io.metersphere.project.dto.NodeSortQueryParam;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -20,4 +21,6 @@ public interface ExtTestPlanApiCaseMapper {
AssociationNode selectDragInfoById(String id); AssociationNode selectDragInfoById(String id);
AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam); AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
List<TestPlanCaseRunResultCount> selectCaseExecResultCount(String testPlanId);
} }

View File

@ -69,4 +69,10 @@
</if> </if>
LIMIT 1 LIMIT 1
</select> </select>
<select id="selectCaseExecResultCount" resultType="io.metersphere.plan.dto.TestPlanCaseRunResultCount">
select last_exec_result as result, count(id) as resultCount
from test_plan_api_case
where test_plan_id = #{0}
group by last_exec_result;
</select>
</mapper> </mapper>

View File

@ -2,6 +2,7 @@ package io.metersphere.plan.mapper;
import io.metersphere.plan.dto.AssociationNode; import io.metersphere.plan.dto.AssociationNode;
import io.metersphere.plan.dto.ResourceSelectParam; import io.metersphere.plan.dto.ResourceSelectParam;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.project.dto.NodeSortQueryParam; import io.metersphere.project.dto.NodeSortQueryParam;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -20,4 +21,6 @@ public interface ExtTestPlanApiScenarioMapper {
AssociationNode selectDragInfoById(String id); AssociationNode selectDragInfoById(String id);
AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam); AssociationNode selectNodeByPosOperator(NodeSortQueryParam nodeSortQueryParam);
List<TestPlanCaseRunResultCount> selectCaseExecResultCount(String testPlanId);
} }

View File

@ -67,4 +67,10 @@
</if> </if>
LIMIT 1 LIMIT 1
</select> </select>
<select id="selectCaseExecResultCount" resultType="io.metersphere.plan.dto.TestPlanCaseRunResultCount">
select last_exec_result as result, count(id) as resultCount
from test_plan_api_scenario
where test_plan_id = #{0}
group by last_exec_result;
</select>
</mapper> </mapper>

View File

@ -6,6 +6,7 @@ import io.metersphere.functional.dto.ProjectOptionDTO;
import io.metersphere.plan.domain.TestPlanFunctionalCase; import io.metersphere.plan.domain.TestPlanFunctionalCase;
import io.metersphere.plan.dto.AssociationNode; import io.metersphere.plan.dto.AssociationNode;
import io.metersphere.plan.dto.ResourceSelectParam; import io.metersphere.plan.dto.ResourceSelectParam;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest; import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest;
import io.metersphere.plan.dto.request.TestPlanCaseRequest; import io.metersphere.plan.dto.request.TestPlanCaseRequest;
import io.metersphere.plan.dto.response.TestPlanCasePageResponse; import io.metersphere.plan.dto.response.TestPlanCasePageResponse;
@ -53,4 +54,6 @@ public interface ExtTestPlanFunctionalCaseMapper {
void batchUpdate(@Param("ids") List<String> ids, @Param("lastExecResult") String lastExecResult, @Param("lastExecTime") long lastExecTime, @Param("userId") String userId); void batchUpdate(@Param("ids") List<String> ids, @Param("lastExecResult") String lastExecResult, @Param("lastExecTime") long lastExecTime, @Param("userId") String userId);
void batchUpdateExecutor(@Param("ids") List<String> ids, @Param("userId") String userId); void batchUpdateExecutor(@Param("ids") List<String> ids, @Param("userId") String userId);
List<TestPlanCaseRunResultCount> selectCaseExecResultCount(String testPlanId);
} }

View File

@ -490,6 +490,12 @@
</if> </if>
</where> </where>
</select> </select>
<select id="selectCaseExecResultCount" resultType="io.metersphere.plan.dto.TestPlanCaseRunResultCount">
select last_exec_result as result, count(id) as resultCount
from test_plan_functional_case
where test_plan_id = #{0}
group by last_exec_result;
</select>
<update id="batchUpdate"> <update id="batchUpdate">

View File

@ -1,6 +1,7 @@
package io.metersphere.plan.service; package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlanApiCaseExample; import io.metersphere.plan.domain.TestPlanApiCaseExample;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper; import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper;
import io.metersphere.plan.mapper.TestPlanApiCaseMapper; import io.metersphere.plan.mapper.TestPlanApiCaseMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -9,6 +10,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -21,10 +24,10 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
private ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper; private ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper;
@Override @Override
public int deleteBatchByTestPlanId(List<String> testPlanIdList) { public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanApiCaseExample example = new TestPlanApiCaseExample(); TestPlanApiCaseExample example = new TestPlanApiCaseExample();
example.createCriteria().andTestPlanIdIn(testPlanIdList); example.createCriteria().andTestPlanIdIn(testPlanIdList);
return testPlanApiCaseMapper.deleteByExample(example); testPlanApiCaseMapper.deleteByExample(example);
} }
@Override @Override
@ -34,21 +37,27 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
@Override @Override
public void updatePos(String id, long pos) { public void updatePos(String id, long pos) {
// TODO // todo
//extTestPlanApiCaseMapper.updatePos(id, pos); // extTestPlanApiCaseMapper.updatePos(id, pos);
}
@Override
public Map<String, Long> caseExecResultCount(String testPlanId) {
List<TestPlanCaseRunResultCount> runResultCounts = extTestPlanApiCaseMapper.selectCaseExecResultCount(testPlanId);
return runResultCounts.stream().collect(Collectors.toMap(TestPlanCaseRunResultCount::getResult, TestPlanCaseRunResultCount::getResultCount));
} }
@Override @Override
public void refreshPos(String testPlanId) { public void refreshPos(String testPlanId) {
// TODO // todo
/*List<String> caseIdList = extTestPlanApiCaseMapper.selectIdByTestPlanIdOrderByPos(testPlanId); // List<String> caseIdList = extTestPlanApiCaseMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); // SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class); // ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
for (int i = 0; i < caseIdList.size(); i++) { // for (int i = 0; i < caseIdList.size(); i++) {
batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS); // batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS);
} // }
sqlSession.flushStatements(); // sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);*/ // SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }

View File

@ -1,6 +1,7 @@
package io.metersphere.plan.service; package io.metersphere.plan.service;
import io.metersphere.plan.domain.TestPlanApiScenarioExample; import io.metersphere.plan.domain.TestPlanApiScenarioExample;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.mapper.ExtTestPlanApiScenarioMapper; import io.metersphere.plan.mapper.ExtTestPlanApiScenarioMapper;
import io.metersphere.plan.mapper.TestPlanApiScenarioMapper; import io.metersphere.plan.mapper.TestPlanApiScenarioMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -9,6 +10,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -21,10 +24,10 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper; private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper;
@Override @Override
public int deleteBatchByTestPlanId(List<String> testPlanIdList) { public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria().andTestPlanIdIn(testPlanIdList); example.createCriteria().andTestPlanIdIn(testPlanIdList);
return testPlanApiScenarioMapper.deleteByExample(example); testPlanApiScenarioMapper.deleteByExample(example);
} }
@Override @Override
@ -34,21 +37,27 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
@Override @Override
public void updatePos(String id, long pos) { public void updatePos(String id, long pos) {
// TODO // todo
//extTestPlanApiScenarioMapper.updatePos(id, pos); // extTestPlanApiScenarioMapper.updatePos(id, pos);
}
@Override
public Map<String, Long> caseExecResultCount(String testPlanId) {
List<TestPlanCaseRunResultCount> runResultCounts = extTestPlanApiScenarioMapper.selectCaseExecResultCount(testPlanId);
return runResultCounts.stream().collect(Collectors.toMap(TestPlanCaseRunResultCount::getResult, TestPlanCaseRunResultCount::getResultCount));
} }
@Override @Override
public void refreshPos(String testPlanId) { public void refreshPos(String testPlanId) {
// TODO // todo
/* List<String> caseIdList = extTestPlanApiScenarioMapper.selectIdByTestPlanIdOrderByPos(testPlanId); // List<String> caseIdList = extTestPlanApiScenarioMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); // SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class); // ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
for (int i = 0; i < caseIdList.size(); i++) { // for (int i = 0; i < caseIdList.size(); i++) {
batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS); // batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS);
} // }
sqlSession.flushStatements(); // sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);*/ // SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }

View File

@ -45,7 +45,7 @@ public class TestPlanBugService extends TestPlanResourceService {
} }
@Override @Override
public int deleteBatchByTestPlanId(List<String> testPlanIdList) { public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
BugRelationCaseExample example = new BugRelationCaseExample(); BugRelationCaseExample example = new BugRelationCaseExample();
example.createCriteria().andTestPlanIdIn(testPlanIdList); example.createCriteria().andTestPlanIdIn(testPlanIdList);
List<BugRelationCase> bugRelationCases = bugRelationCaseMapper.selectByExample(example); List<BugRelationCase> bugRelationCases = bugRelationCaseMapper.selectByExample(example);
@ -66,7 +66,11 @@ public class TestPlanBugService extends TestPlanResourceService {
deleteExample.createCriteria().andIdIn(relateIdsByPlan); deleteExample.createCriteria().andIdIn(relateIdsByPlan);
bugRelationCaseMapper.deleteByExample(deleteExample); bugRelationCaseMapper.deleteByExample(deleteExample);
} }
return bugRelationCases.size(); }
@Override
public Map<String, Long> caseExecResultCount(String testPlanId) {
return Map.of();
} }

View File

@ -6,7 +6,7 @@ import io.metersphere.plan.domain.TestPlanFunctionalCaseExample;
import io.metersphere.plan.dto.TestPlanResourceAssociationParam; import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper; import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper;
import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper; import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils; import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -47,7 +47,7 @@ public class TestPlanCaseService {
testPlanFunctionalCase.setPos(pox); testPlanFunctionalCase.setPos(pox);
testPlanFunctionalCase.setCreateTime(now); testPlanFunctionalCase.setCreateTime(now);
testPlanFunctionalCase.setCreateUser(associationParam.getOperator()); testPlanFunctionalCase.setCreateUser(associationParam.getOperator());
testPlanFunctionalCase.setLastExecResult(FunctionalCaseExecuteResult.PENDING.name()); testPlanFunctionalCase.setLastExecResult(ExecStatus.PENDING.name());
testPlanFunctionalCase.setExecuteUser(associationParam.getOperator()); testPlanFunctionalCase.setExecuteUser(associationParam.getOperator());
testPlanFunctionalCaseList.add(testPlanFunctionalCase); testPlanFunctionalCaseList.add(testPlanFunctionalCase);
pox += ServiceUtils.POS_STEP; pox += ServiceUtils.POS_STEP;

View File

@ -19,6 +19,7 @@ import io.metersphere.functional.service.FunctionalCaseService;
import io.metersphere.plan.domain.*; import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.AssociationNodeSortDTO; import io.metersphere.plan.dto.AssociationNodeSortDTO;
import io.metersphere.plan.dto.ResourceLogInsertModule; import io.metersphere.plan.dto.ResourceLogInsertModule;
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
import io.metersphere.plan.dto.TestPlanResourceAssociationParam; import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.*; import io.metersphere.plan.dto.response.*;
@ -29,7 +30,7 @@ import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.request.AssociateBugPageRequest; import io.metersphere.request.AssociateBugPageRequest;
import io.metersphere.request.BugPageProviderRequest; import io.metersphere.request.BugPageProviderRequest;
import io.metersphere.sdk.constants.CaseType; import io.metersphere.sdk.constants.CaseType;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.TestPlanResourceConstants; import io.metersphere.sdk.constants.TestPlanResourceConstants;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
@ -122,7 +123,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
private static final String CHECK_OWNER_CASE = "check_owner_case"; private static final String CHECK_OWNER_CASE = "check_owner_case";
@Override @Override
public int deleteBatchByTestPlanId(List<String> testPlanIdList) { public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanFunctionalCaseExample testPlanFunctionalCaseExample = new TestPlanFunctionalCaseExample(); TestPlanFunctionalCaseExample testPlanFunctionalCaseExample = new TestPlanFunctionalCaseExample();
testPlanFunctionalCaseExample.createCriteria().andTestPlanIdIn(testPlanIdList); testPlanFunctionalCaseExample.createCriteria().andTestPlanIdIn(testPlanIdList);
testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample); testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample);
@ -132,7 +133,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
bugRelationCaseMapper.deleteByExample(example); bugRelationCaseMapper.deleteByExample(example);
// todo:song.tianyang 删除执行历史 // todo:song.tianyang 删除执行历史
return testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample); testPlanFunctionalCaseMapper.deleteByExample(testPlanFunctionalCaseExample);
} }
@ -146,6 +147,11 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
extTestPlanFunctionalCaseMapper.updatePos(id, pos); extTestPlanFunctionalCaseMapper.updatePos(id, pos);
} }
@Override
public Map<String, Long> caseExecResultCount(String testPlanId) {
List<TestPlanCaseRunResultCount> runResultCounts = extTestPlanFunctionalCaseMapper.selectCaseExecResultCount(testPlanId);
return runResultCounts.stream().collect(Collectors.toMap(TestPlanCaseRunResultCount::getResult, TestPlanCaseRunResultCount::getResultCount));
}
@Override @Override
public void refreshPos(String testPlanId) { public void refreshPos(String testPlanId) {
List<String> functionalCaseIdList = extTestPlanFunctionalCaseMapper.selectIdByTestPlanIdOrderByPos(testPlanId); List<String> functionalCaseIdList = extTestPlanFunctionalCaseMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
@ -388,7 +394,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
* @param request * @param request
* @param logInsertModule * @param logInsertModule
*/ */
public void run(TestPlanCaseRunRequest request, String organizationId, LogInsertModule logInsertModule) { public void run(TestPlanCaseRunRequest request, LogInsertModule logInsertModule) {
TestPlanFunctionalCase functionalCase = new TestPlanFunctionalCase(); TestPlanFunctionalCase functionalCase = new TestPlanFunctionalCase();
functionalCase.setLastExecResult(request.getLastExecResult()); functionalCase.setLastExecResult(request.getLastExecResult());
functionalCase.setLastExecTime(System.currentTimeMillis()); functionalCase.setLastExecTime(System.currentTimeMillis());
@ -397,8 +403,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
testPlanFunctionalCaseMapper.updateByPrimaryKeySelective(functionalCase); testPlanFunctionalCaseMapper.updateByPrimaryKeySelective(functionalCase);
//更新用例表执行状态 //更新用例表执行状态
updateFunctionalCaseStatus(Arrays.asList(request.getCaseId()), request.getLastExecResult()); updateFunctionalCaseStatus(Collections.singletonList(request.getCaseId()), request.getLastExecResult());
//执行记录 //执行记录
TestPlanCaseExecuteHistory executeHistory = buildHistory(request, logInsertModule.getOperator()); TestPlanCaseExecuteHistory executeHistory = buildHistory(request, logInsertModule.getOperator());
@ -455,15 +460,15 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
* @param request * @param request
* @param logInsertModule * @param logInsertModule
*/ */
public void batchRun(TestPlanCaseBatchRunRequest request, String organizationId, LogInsertModule logInsertModule) { public void batchRun(TestPlanCaseBatchRunRequest request, LogInsertModule logInsertModule) {
List<String> ids = doSelectIds(request); List<String> ids = doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) { if (CollectionUtils.isNotEmpty(ids)) {
handleBatchRun(ids, organizationId, request, logInsertModule); handleBatchRun(ids, request, logInsertModule);
} }
} }
private void handleBatchRun(List<String> ids, String organizationId, TestPlanCaseBatchRunRequest request, LogInsertModule logInsertModule) { private void handleBatchRun(List<String> ids, TestPlanCaseBatchRunRequest request, LogInsertModule logInsertModule) {
//更新状态 //更新状态
extTestPlanFunctionalCaseMapper.batchUpdate(ids, request.getLastExecResult(), System.currentTimeMillis(), logInsertModule.getOperator()); extTestPlanFunctionalCaseMapper.batchUpdate(ids, request.getLastExecResult(), System.currentTimeMillis(), logInsertModule.getOperator());
@ -514,12 +519,12 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
testPlanSendNoticeService.sendNoticeCase(relatedUsers, userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_AT, testPlanId); testPlanSendNoticeService.sendNoticeCase(relatedUsers, userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_AT, testPlanId);
} }
if (StringUtils.equalsIgnoreCase(lastExecResult, FunctionalCaseExecuteResult.SUCCESS.name())) { if (StringUtils.equalsIgnoreCase(lastExecResult, ExecStatus.SUCCESS.name())) {
//成功 发送通知 //成功 发送通知
testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.EXECUTE_PASSED, testPlanId); testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.EXECUTE_PASSED, testPlanId);
} }
if (StringUtils.equalsIgnoreCase(lastExecResult, FunctionalCaseExecuteResult.ERROR.name())) { if (StringUtils.equalsIgnoreCase(lastExecResult, ExecStatus.ERROR.name())) {
//失败 发送通知 //失败 发送通知
testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.EXECUTE_FAIL, testPlanId); testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.EXECUTE_FAIL, testPlanId);
} }

View File

@ -411,11 +411,10 @@ public class TestPlanReportService {
List<CaseStatusCountMap> functionalCaseCountMap = extTestPlanReportFunctionalCaseMapper.countExecuteResult(reportDetail.getId()); List<CaseStatusCountMap> functionalCaseCountMap = extTestPlanReportFunctionalCaseMapper.countExecuteResult(reportDetail.getId());
Map<String, Long> functionalCaseResultMap = functionalCaseCountMap.stream().collect(Collectors.toMap(CaseStatusCountMap::getStatus, CaseStatusCountMap::getCount)); Map<String, Long> functionalCaseResultMap = functionalCaseCountMap.stream().collect(Collectors.toMap(CaseStatusCountMap::getStatus, CaseStatusCountMap::getCount));
TestPlanReportDetailResponse.CaseCount functionalCaseCount = new TestPlanReportDetailResponse.CaseCount(); TestPlanReportDetailResponse.CaseCount functionalCaseCount = new TestPlanReportDetailResponse.CaseCount();
functionalCaseCount.setSuccess(functionalCaseResultMap.getOrDefault(FunctionalCaseExecuteResult.SUCCESS.name(), 0L).intValue()); functionalCaseCount.setSuccess(functionalCaseResultMap.getOrDefault(ExecStatus.SUCCESS.name(), 0L).intValue());
functionalCaseCount.setError(functionalCaseResultMap.getOrDefault(FunctionalCaseExecuteResult.ERROR.name(), 0L).intValue()); functionalCaseCount.setError(functionalCaseResultMap.getOrDefault(ExecStatus.ERROR.name(), 0L).intValue());
functionalCaseCount.setPending(functionalCaseResultMap.getOrDefault(FunctionalCaseExecuteResult.PENDING.name(), 0L).intValue()); functionalCaseCount.setPending(functionalCaseResultMap.getOrDefault(ExecStatus.PENDING.name(), 0L).intValue());
functionalCaseCount.setBlock(functionalCaseResultMap.getOrDefault(FunctionalCaseExecuteResult.BLOCKED.name(), 0L).intValue()); functionalCaseCount.setBlock(functionalCaseResultMap.getOrDefault(ExecStatus.BLOCKED.name(), 0L).intValue());
// TODO: 接口用例, 场景用例 // TODO: 接口用例, 场景用例

View File

@ -24,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@ -43,7 +44,9 @@ public abstract class TestPlanResourceService extends MoveNodeService {
public abstract void refreshPos(String testPlanId); public abstract void refreshPos(String testPlanId);
public abstract int deleteBatchByTestPlanId(List<String> testPlanIdList); public abstract void deleteBatchByTestPlanId(List<String> testPlanIdList);
public abstract Map<String, Long> caseExecResultCount(String testPlanId);
private static final String MOVE_POS_OPERATOR_LESS = "lessThan"; private static final String MOVE_POS_OPERATOR_LESS = "lessThan";
private static final String MOVE_POS_OPERATOR_MORE = "moreThan"; private static final String MOVE_POS_OPERATOR_MORE = "moreThan";

View File

@ -4,10 +4,7 @@ import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanDetailResponse; import io.metersphere.plan.dto.response.TestPlanDetailResponse;
import io.metersphere.plan.mapper.*; import io.metersphere.plan.mapper.*;
import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory; import io.metersphere.sdk.util.CommonBeanFactory;
@ -27,12 +24,15 @@ import io.metersphere.system.utils.BatchProcessUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils; import org.mybatis.spring.SqlSessionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -142,14 +142,8 @@ public class TestPlanService extends TestPlanBaseUtilsService {
/** /**
* 删除测试计划 * 删除测试计划
*
* @param id
* @param operator
* @param requestUrl
* @param requestMethod
*/ */
public void delete(String id, String operator, String requestUrl, String requestMethod) { public void delete(String id, String operator, String requestUrl, String requestMethod) {
this.checkTestPlanNotArchived(id);
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id);
if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) { if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
// 计划组的删除暂时预留 // 计划组的删除暂时预留
@ -682,4 +676,36 @@ public class TestPlanService extends TestPlanBaseUtilsService {
throw new MSException(Translator.get("test_plan.is.archived")); throw new MSException(Translator.get("test_plan.is.archived"));
} }
} }
@Autowired
private ApplicationContext applicationContext;
public void refreshTestPlanStatus(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;
} else if (caseExecResultCount.size() == 1 && caseExecResultCount.containsKey(ExecStatus.PENDING.name()) && caseExecResultCount.get(ExecStatus.PENDING.name()) > 0) {
// 执行结果只有未开始 状态是未开始
testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_PREPARED;
} else if (!caseExecResultCount.containsKey(ExecStatus.PENDING.name())) {
// 执行结果没有未开始 已完成
testPlanFinalStatus = TestPlanConstants.TEST_PLAN_STATUS_COMPLETED;
}
TestPlan testPlan = new TestPlan();
testPlan.setId(testPlanId);
testPlan.setStatus(testPlanFinalStatus);
testPlanMapper.updateByPrimaryKeySelective(testPlan);
}
} }

View File

@ -7,7 +7,7 @@ import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper; import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper;
import io.metersphere.plan.mapper.TestPlanConfigMapper; import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.utils.RateCalculateUtils; import io.metersphere.plan.utils.RateCalculateUtils;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; import io.metersphere.sdk.constants.ExecStatus;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -86,12 +86,12 @@ public class TestPlanStatisticsService {
statisticsResponse.setFunctionalCaseCount(CollectionUtils.isNotEmpty(functionalCases) ? functionalCases.size() : 0); statisticsResponse.setFunctionalCaseCount(CollectionUtils.isNotEmpty(functionalCases) ? functionalCases.size() : 0);
// 根据执行结果分组(为空, 默认为未执行) // 根据执行结果分组(为空, 默认为未执行)
Map<String, List<TestPlanFunctionalCase>> functionalCaseResultMap = CollectionUtils.isEmpty(functionalCases) ? new HashMap<>(16) : functionalCases.stream().collect( Map<String, List<TestPlanFunctionalCase>> functionalCaseResultMap = CollectionUtils.isEmpty(functionalCases) ? new HashMap<>(16) : functionalCases.stream().collect(
Collectors.groupingBy(functionalCase -> Optional.ofNullable(functionalCase.getLastExecResult()).orElse(FunctionalCaseExecuteResult.PENDING.name()))); Collectors.groupingBy(functionalCase -> Optional.ofNullable(functionalCase.getLastExecResult()).orElse(ExecStatus.PENDING.name())));
success += functionalCaseResultMap.containsKey(FunctionalCaseExecuteResult.SUCCESS.name()) ? functionalCaseResultMap.get(FunctionalCaseExecuteResult.SUCCESS.name()).size() : 0; success += functionalCaseResultMap.containsKey(ExecStatus.SUCCESS.name()) ? functionalCaseResultMap.get(ExecStatus.SUCCESS.name()).size() : 0;
error += functionalCaseResultMap.containsKey(FunctionalCaseExecuteResult.ERROR.name()) ? functionalCaseResultMap.get(FunctionalCaseExecuteResult.ERROR.name()).size() : 0; error += functionalCaseResultMap.containsKey(ExecStatus.ERROR.name()) ? functionalCaseResultMap.get(ExecStatus.ERROR.name()).size() : 0;
fakeError += functionalCaseResultMap.containsKey(FunctionalCaseExecuteResult.FAKE_ERROR.name()) ? functionalCaseResultMap.get(FunctionalCaseExecuteResult.FAKE_ERROR.name()).size() : 0; fakeError += functionalCaseResultMap.containsKey(ExecStatus.FAKE_ERROR.name()) ? functionalCaseResultMap.get(ExecStatus.FAKE_ERROR.name()).size() : 0;
block += functionalCaseResultMap.containsKey(FunctionalCaseExecuteResult.BLOCKED.name()) ? functionalCaseResultMap.get(FunctionalCaseExecuteResult.BLOCKED.name()).size() : 0; block += functionalCaseResultMap.containsKey(ExecStatus.BLOCKED.name()) ? functionalCaseResultMap.get(ExecStatus.BLOCKED.name()).size() : 0;
pending += functionalCaseResultMap.containsKey(FunctionalCaseExecuteResult.PENDING.name()) ? functionalCaseResultMap.get(FunctionalCaseExecuteResult.PENDING.name()).size() : 0; pending += functionalCaseResultMap.containsKey(ExecStatus.PENDING.name()) ? functionalCaseResultMap.get(ExecStatus.PENDING.name()).size() : 0;
// TODO: 接口用例统计开始 // TODO: 接口用例统计开始

View File

@ -1041,7 +1041,7 @@ public class TestPlanTests extends BaseTest {
@Test @Test
@Order(22) @Order(22)
public void testPlanFunctionCaseSort() throws Exception { public void testPlanFunctionCaseSort() throws Exception {
if (FUNCTIONAL_CASES.size() == 0) { if (FUNCTIONAL_CASES.isEmpty()) {
this.testPlanAssociationFunctionCase(); this.testPlanAssociationFunctionCase();
} }
List<TestPlanFunctionalCase> funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId()); List<TestPlanFunctionalCase> funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId());
@ -1751,8 +1751,15 @@ public class TestPlanTests extends BaseTest {
@Test @Test
@Order(302) @Order(302)
public void testArchived() throws Exception { public void testArchived() throws Exception {
//计划 //计划 -- 首先状态不是已完成
this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_1")); this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_1"));
//更改状态再归档
TestPlan testPlan = new TestPlan();
testPlan.setId("wx_test_plan_id_1");
testPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_COMPLETED);
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_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_3"));
@ -1889,10 +1896,14 @@ public class TestPlanTests extends BaseTest {
@Order(305) @Order(305)
public void testAssociation() throws Exception { public void testAssociation() throws Exception {
TestPlanAssociationRequest request = new TestPlanAssociationRequest(); TestPlanAssociationRequest request = new TestPlanAssociationRequest();
request.setTestPlanId("wx_test_plan_id_1"); request.setTestPlanId("wx_test_plan_id_2");
this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request); this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request);
request.setFunctionalSelectIds(Arrays.asList("my_test_1", "my_test_2", "my_test_3")); request.setFunctionalSelectIds(Arrays.asList("my_test_1", "my_test_2", "my_test_3"));
this.requestPostWithOkAndReturn(URL_POST_RESOURCE_CASE_ASSOCIATION, request); 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 @Test

View File

@ -150,7 +150,7 @@ public class TestPlanTestService {
functionalCase.setReviewStatus("UN_REVIEWED"); functionalCase.setReviewStatus("UN_REVIEWED");
functionalCase.setPos((long) (i * 64)); functionalCase.setPos((long) (i * 64));
functionalCase.setRefId(functionalCase.getId()); functionalCase.setRefId(functionalCase.getId());
functionalCase.setLastExecuteResult(FunctionalCaseExecuteResult.PENDING.name()); functionalCase.setLastExecuteResult(ExecStatus.PENDING.name());
functionalCase.setLatest(true); functionalCase.setLatest(true);
functionalCase.setCreateUser("admin"); functionalCase.setCreateUser("admin");
functionalCase.setCreateTime(System.currentTimeMillis()); functionalCase.setCreateTime(System.currentTimeMillis());