feat(接口测试): 测试计划用例批量执行,重跑逻辑

--task=1016918 --user=陈建星 失败重跑 https://www.tapd.cn/55049933/s/1609836
This commit is contained in:
AgAngle 2024-11-18 14:38:58 +08:00 committed by Craftsman
parent 4c692862fc
commit 9bedceefe2
14 changed files with 251 additions and 105 deletions

View File

@ -59,9 +59,12 @@ public class ApiNoticeDTO implements java.io.Serializable {
* 当测试集执行完成时标记触发下个测试集执行 * 当测试集执行完成时标记触发下个测试集执行
*/ */
private Boolean childCollectionExecuteOver; private Boolean childCollectionExecuteOver;
/** /**
* 运行配置 * 运行配置
*/ */
private ApiRunModeConfigDTO runModeConfig = new ApiRunModeConfigDTO(); private ApiRunModeConfigDTO runModeConfig = new ApiRunModeConfigDTO();
/**
* 是否是重新执行
*/
private Boolean rerun = false;
} }

View File

@ -52,12 +52,13 @@ public class ApiBatchRunBaseService {
* @param runModeConfig * @param runModeConfig
* @return * @return
*/ */
public ExecutionQueue initExecutionqueue(String queueId, List<String> resourceIds, ApiRunModeConfigDTO runModeConfig, String resourceType, String parentQueueId, String userId) { public ExecutionQueue initExecutionqueue(String queueId, List<String> resourceIds, ApiRunModeConfigDTO runModeConfig, String resourceType, String parentQueueId, String userId, boolean isRerun) {
ExecutionQueue queue = getExecutionQueue(runModeConfig, resourceType, userId); ExecutionQueue queue = getExecutionQueue(runModeConfig, resourceType, userId);
if (StringUtils.isNotBlank(queueId)) { if (StringUtils.isNotBlank(queueId)) {
queue.setQueueId(queueId); queue.setQueueId(queueId);
} }
queue.setParentQueueId(parentQueueId); queue.setParentQueueId(parentQueueId);
queue.setRerun(isRerun);
List<ExecutionQueueDetail> queueDetails = getExecutionQueueDetailsByIds(resourceIds); List<ExecutionQueueDetail> queueDetails = getExecutionQueueDetailsByIds(resourceIds);
apiExecutionQueueService.insertQueue(queue, queueDetails); apiExecutionQueueService.insertQueue(queue, queueDetails);
return queue; return queue;

View File

@ -9,6 +9,7 @@ import io.metersphere.system.dto.taskhub.request.TaskHubItemRequest;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author wx * @author wx
@ -67,4 +68,6 @@ public interface ExtExecTaskItemMapper {
void resetRerunTaskItem(@Param("taskId") String taskId, @Param("userId") String userId); void resetRerunTaskItem(@Param("taskId") String taskId, @Param("userId") String userId);
void deleteRerunTaskItemReportRelation(@Param("taskId") String taskId); void deleteRerunTaskItemReportRelation(@Param("taskId") String taskId);
Set<String> selectRerunCollectionIds(@Param("taskId") String taskId);
} }

View File

@ -322,6 +322,11 @@
</foreach> </foreach>
</if> </if>
</select> </select>
<select id="selectRerunCollectionIds" resultType="java.lang.String">
select distinct collection_id
from exec_task_item
where task_id = #{taskId} and rerun = true and deleted = false;
</select>
<update id="resetRerunTaskItem"> <update id="resetRerunTaskItem">
UPDATE exec_task_item UPDATE exec_task_item

View File

@ -108,6 +108,8 @@ public class BaseTaskHubService {
private TestResourcePoolService testResourcePoolService; private TestResourcePoolService testResourcePoolService;
@Resource @Resource
private ApiReportRelateTaskMapper apiReportRelateTaskMapper; private ApiReportRelateTaskMapper apiReportRelateTaskMapper;
@Resource
private ExecTaskService execTaskService;
private final static String GET_TASK_ITEM_ORDER_URL = "http://%s/api/task/item/order"; private final static String GET_TASK_ITEM_ORDER_URL = "http://%s/api/task/item/order";
@ -600,27 +602,9 @@ public class BaseTaskHubService {
throw new MSException(Translator.get("no_permission_to_resource")); throw new MSException(Translator.get("no_permission_to_resource"));
} }
// 更新任务状态 execTaskService.updateTaskRerunStatus(execTask, userId);
execTask.setStatus(ExecStatus.RERUNNING.name());
execTask.setCreateUser(userId);
execTask.setEndTime(null);
execTask.setResult(ExecStatus.PENDING.name());
execTaskMapper.updateByPrimaryKey(execTask);
if (BooleanUtils.isFalse(execTask.getIntegrated()) && !StringUtils.equalsAny(execTask.getTaskType(), ExecTaskType.TEST_PLAN.name(), ExecTaskType.TEST_PLAN_GROUP.name())) { Thread.startVirtualThread(() -> TaskRerunServiceInvoker.rerun(execTask, userId));
// 非集合报告和测试计划执行则删除任务和报告的关联关系
ApiReportRelateTaskExample example = new ApiReportRelateTaskExample();
example.createCriteria().andTaskResourceIdEqualTo(execTask.getId());
apiReportRelateTaskMapper.deleteByExample(example);
}
// 删除任务项和报告的关联关系
extExecTaskItemMapper.deleteRerunTaskItemReportRelation(execTask.getId());
// 更新任务项状态等
extExecTaskItemMapper.resetRerunTaskItem(execTask.getId(), userId);
TaskRerunServiceInvoker.rerun(execTask, userId);
} }
private void handleStopTaskAsync(List<String> ids) { private void handleStopTaskAsync(List<String> ids) {

View File

@ -0,0 +1,54 @@
package io.metersphere.system.service;
import io.metersphere.api.domain.ApiReportRelateTaskExample;
import io.metersphere.api.mapper.ApiReportRelateTaskMapper;
import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.ExecTaskType;
import io.metersphere.system.domain.ExecTask;
import io.metersphere.system.mapper.ExecTaskMapper;
import io.metersphere.system.mapper.ExtExecTaskItemMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* @Author: jianxing
* @CreateTime: 2024-11-18 14:17
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class ExecTaskService {
@Resource
private ExecTaskMapper execTaskMapper;
@Resource
private ExtExecTaskItemMapper extExecTaskItemMapper;
@Resource
private ApiReportRelateTaskMapper apiReportRelateTaskMapper;
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void updateTaskRerunStatus(ExecTask execTask, String userId) {
// 更新任务状态
execTask.setStatus(ExecStatus.RERUNNING.name());
execTask.setCreateUser(userId);
execTask.setEndTime(null);
execTask.setResult(ExecStatus.PENDING.name());
execTaskMapper.updateByPrimaryKey(execTask);
if (BooleanUtils.isFalse(execTask.getIntegrated()) && !StringUtils.equalsAny(execTask.getTaskType(), ExecTaskType.TEST_PLAN.name(), ExecTaskType.TEST_PLAN_GROUP.name())) {
// 非集合报告和测试计划执行则删除任务和报告的关联关系
ApiReportRelateTaskExample example = new ApiReportRelateTaskExample();
example.createCriteria().andTaskResourceIdEqualTo(execTask.getId());
apiReportRelateTaskMapper.deleteByExample(example);
}
// 删除任务项和报告的关联关系
extExecTaskItemMapper.deleteRerunTaskItemReportRelation(execTask.getId());
// 更新任务项状态等
extExecTaskItemMapper.resetRerunTaskItem(execTask.getId(), userId);
}
}

View File

@ -30,6 +30,7 @@ import io.metersphere.sdk.util.SubListUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.ExecTask; import io.metersphere.system.domain.ExecTask;
import io.metersphere.system.domain.ExecTaskItem; import io.metersphere.system.domain.ExecTaskItem;
import io.metersphere.system.mapper.ExtExecTaskItemMapper;
import io.metersphere.system.service.BaseTaskHubService; import io.metersphere.system.service.BaseTaskHubService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -74,6 +75,8 @@ public class TestPlanApiCaseBatchRunService {
private BaseTaskHubService baseTaskHubService; private BaseTaskHubService baseTaskHubService;
@Resource @Resource
private TestPlanService testPlanService; private TestPlanService testPlanService;
@Resource
private ExtExecTaskItemMapper extExecTaskItemMapper;
/** /**
* 批量执行 * 批量执行
@ -88,7 +91,20 @@ public class TestPlanApiCaseBatchRunService {
.map(TestPlanApiCaseBatchRunDTO::getTestPlanCollectionId) .map(TestPlanApiCaseBatchRunDTO::getTestPlanCollectionId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
List<TestPlanCollection> testPlanCollections = getTestPlanCollections(request.getTestPlanId()); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
// 初始化任务
ExecTask execTask = initExecTask(testPlanApiCases.size(), project, userId, request.getTestPlanId());
// 初始化任务项
initExecTaskItem(testPlanApiCases, userId, project, execTask, testPlan.getId());
Thread.startVirtualThread(() ->
doRerun(execTask, request.getTestPlanId(), project, userId, hasCaseCollections, false));
}
private void doRerun(ExecTask execTask, String testPlanId, Project project, String userId, Set<String> hasCaseCollections, boolean isRerun) {
List<TestPlanCollection> testPlanCollections = getTestPlanCollections(testPlanId);
Iterator<TestPlanCollection> iterator = testPlanCollections.iterator(); Iterator<TestPlanCollection> iterator = testPlanCollections.iterator();
TestPlanCollection rootCollection = new TestPlanCollection(); TestPlanCollection rootCollection = new TestPlanCollection();
while (iterator.hasNext()) { while (iterator.hasNext()) {
@ -108,18 +124,9 @@ public class TestPlanApiCaseBatchRunService {
.sorted(Comparator.comparingLong(TestPlanCollection::getPos)) .sorted(Comparator.comparingLong(TestPlanCollection::getPos))
.collect(Collectors.toList()); .collect(Collectors.toList());
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
// 初始化任务
ExecTask execTask = initExecTask(testPlanApiCases.size(), project, userId);
// 初始化任务项
initExecTaskItem(testPlanApiCases, userId, project, execTask, testPlan.getId());
TestPlanCollection finalRootCollection = rootCollection; TestPlanCollection finalRootCollection = rootCollection;
List<TestPlanCollection> finalTestPlanCollections = testPlanCollections; List<TestPlanCollection> finalTestPlanCollections = testPlanCollections;
Thread.startVirtualThread(() -> {
List<String> execCollectionIds = finalTestPlanCollections.stream().map(TestPlanCollection::getId).toList(); List<String> execCollectionIds = finalTestPlanCollections.stream().map(TestPlanCollection::getId).toList();
if (apiBatchRunBaseService.isParallel(finalRootCollection.getExecuteMethod())) { if (apiBatchRunBaseService.isParallel(finalRootCollection.getExecuteMethod())) {
// 记录并行执行测试集用于统计整体执行情况 // 记录并行执行测试集用于统计整体执行情况
@ -130,23 +137,22 @@ public class TestPlanApiCaseBatchRunService {
ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(finalRootCollection, collection); ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(finalRootCollection, collection);
if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) { if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) {
// 并行执行测试集中的用例 // 并行执行测试集中的用例
parallelExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), project, userId); parallelExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), project, userId, isRerun);
} else { } else {
// 串行执行测试集中的用例 // 串行执行测试集中的用例
serialExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), userId); serialExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), userId, isRerun);
} }
} }
} else { } else {
// 生成测试集队列 // 生成测试集队列
ExecutionQueue collectionQueue = apiBatchRunBaseService.initExecutionqueue(execTask.getId(), execCollectionIds, null, ExecutionQueue collectionQueue = apiBatchRunBaseService.initExecutionqueue(execTask.getId(), execCollectionIds, null,
ApiExecuteResourceType.TEST_PLAN_API_CASE.name(), null, userId); ApiExecuteResourceType.TEST_PLAN_API_CASE.name(), null, userId, isRerun);
executeNextCollection(collectionQueue.getQueueId()); executeNextCollection(collectionQueue.getQueueId(), isRerun);
} }
});
} }
public void executeNextCollection(String collectionQueueId) { public void executeNextCollection(String collectionQueueId, boolean rerun) {
ExecutionQueue collectionQueue = apiExecutionQueueService.getQueue(collectionQueueId); ExecutionQueue collectionQueue = apiExecutionQueueService.getQueue(collectionQueueId);
if (collectionQueue == null) { if (collectionQueue == null) {
// 失败停止或者执行完成更新任务状态 // 失败停止或者执行完成更新任务状态
@ -163,9 +169,9 @@ public class TestPlanApiCaseBatchRunService {
ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(collection); ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(collection);
if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) { if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) {
parallelExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, project, userId); parallelExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, project, userId, rerun);
} else { } else {
serialExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, userId); serialExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, userId, rerun);
} }
} }
@ -189,12 +195,13 @@ public class TestPlanApiCaseBatchRunService {
ApiRunModeConfigDTO runModeConfig, ApiRunModeConfigDTO runModeConfig,
String parentQueueId, String parentQueueId,
String parentSetId, String parentSetId,
String userId) { String userId,
boolean isRerun) {
// 初始化执行队列 // 初始化执行队列
ExecutionQueue queue = apiBatchRunBaseService.initExecutionQueue(taskId, taskId + '_' + collectionId, runModeConfig, ApiExecuteResourceType.TEST_PLAN_API_CASE.name(), parentQueueId, parentSetId, userId); ExecutionQueue queue = apiBatchRunBaseService.initExecutionQueue(taskId, taskId + '_' + collectionId, runModeConfig, ApiExecuteResourceType.TEST_PLAN_API_CASE.name(), parentQueueId, parentSetId, userId);
List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, false); List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, isRerun);
apiBatchRunBaseService.initQueueDetail(queue, execTaskItems); apiBatchRunBaseService.initQueueDetail(queue, execTaskItems);
@ -213,7 +220,8 @@ public class TestPlanApiCaseBatchRunService {
String parentQueueId, String parentQueueId,
String parentSetId, String parentSetId,
Project project, Project project,
String userId) { String userId,
boolean isRerun) {
TaskBatchRequestDTO taskRequest = getTaskBatchRequestDTO(project.getId(), runModeConfig); TaskBatchRequestDTO taskRequest = getTaskBatchRequestDTO(project.getId(), runModeConfig);
TaskInfo taskInfo = taskRequest.getTaskInfo(); TaskInfo taskInfo = taskRequest.getTaskInfo();
@ -229,7 +237,7 @@ public class TestPlanApiCaseBatchRunService {
taskRequest.getTaskInfo().setParentSetId(parentSetId); taskRequest.getTaskInfo().setParentSetId(parentSetId);
} }
List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, false); List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, isRerun);
SubListUtils.dealForSubList(execTaskItems, ApiBatchRunBaseService.BATCH_TASK_ITEM_SIZE, subExecTaskItems -> { SubListUtils.dealForSubList(execTaskItems, ApiBatchRunBaseService.BATCH_TASK_ITEM_SIZE, subExecTaskItems -> {
List<TaskItem> taskItems = subExecTaskItems List<TaskItem> taskItems = subExecTaskItems
@ -254,13 +262,14 @@ public class TestPlanApiCaseBatchRunService {
}); });
} }
private ExecTask initExecTask(int caseSize, Project project, String userId) { private ExecTask initExecTask(int caseSize, Project project, String userId, String testPlanId) {
ExecTask execTask = apiCommonService.newExecTask(project.getId(), userId); ExecTask execTask = apiCommonService.newExecTask(project.getId(), userId);
execTask.setCaseCount(Long.valueOf(caseSize)); execTask.setCaseCount(Long.valueOf(caseSize));
execTask.setTaskName(Translator.get("api_batch_task_name")); execTask.setTaskName(Translator.get("api_batch_task_name"));
execTask.setOrganizationId(project.getOrganizationId()); execTask.setOrganizationId(project.getOrganizationId());
execTask.setTriggerMode(TaskTriggerMode.BATCH.name()); execTask.setTriggerMode(TaskTriggerMode.BATCH.name());
execTask.setTaskType(ExecTaskType.TEST_PLAN_API_CASE_BATCH.name()); execTask.setTaskType(ExecTaskType.TEST_PLAN_API_CASE_BATCH.name());
execTask.setResourceId(testPlanId);
baseTaskHubService.insertExecTask(execTask); baseTaskHubService.insertExecTask(execTask);
return execTask; return execTask;
} }
@ -331,6 +340,7 @@ public class TestPlanApiCaseBatchRunService {
TaskRequestDTO taskRequest = getTaskRequestDTO(testPlanApiCase.getId(), apiTestCase, runModeConfig); TaskRequestDTO taskRequest = getTaskRequestDTO(testPlanApiCase.getId(), apiTestCase, runModeConfig);
taskRequest.getTaskInfo().setTaskId(queue.getTaskId()); taskRequest.getTaskInfo().setTaskId(queue.getTaskId());
taskRequest.getTaskInfo().setQueueId(queue.getQueueId()); taskRequest.getTaskInfo().setQueueId(queue.getQueueId());
taskRequest.getTaskInfo().setRerun(queue.getRerun());
taskRequest.getTaskInfo().setParentQueueId(queue.getParentQueueId()); taskRequest.getTaskInfo().setParentQueueId(queue.getParentQueueId());
taskRequest.getTaskInfo().setParentSetId(queue.getParentSetId()); taskRequest.getTaskInfo().setParentSetId(queue.getParentSetId());
taskRequest.getTaskInfo().setUserId(queue.getUserId()); taskRequest.getTaskInfo().setUserId(queue.getUserId());
@ -372,4 +382,12 @@ public class TestPlanApiCaseBatchRunService {
apiBatchRunBaseService.updateTaskCompletedStatus(parentSetId); apiBatchRunBaseService.updateTaskCompletedStatus(parentSetId);
} }
} }
public void rerun(ExecTask execTask, String userId) {
String planId = execTask.getResourceId();
Set<String> rerunCollectionIds = extExecTaskItemMapper.selectRerunCollectionIds(execTask.getId());
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
doRerun(execTask, planId, project, userId, rerunCollectionIds, true);
}
} }

View File

@ -93,7 +93,7 @@ public class TestPlanApiCaseExecuteCallbackService implements ApiExecuteCallback
@Override @Override
public void executeNextCollection(ApiNoticeDTO apiNoticeDTO, boolean isStopOnFailure) { public void executeNextCollection(ApiNoticeDTO apiNoticeDTO, boolean isStopOnFailure) {
if (StringUtils.isNotBlank(apiNoticeDTO.getParentQueueId())) { if (StringUtils.isNotBlank(apiNoticeDTO.getParentQueueId())) {
testPlanApiCaseBatchRunService.executeNextCollection(apiNoticeDTO.getParentQueueId()); testPlanApiCaseBatchRunService.executeNextCollection(apiNoticeDTO.getParentQueueId(), apiNoticeDTO.getRerun());
} else if (StringUtils.isNotBlank(apiNoticeDTO.getParentSetId())) { } else if (StringUtils.isNotBlank(apiNoticeDTO.getParentSetId())) {
String queueIdOrSetId = StringUtils.isBlank(apiNoticeDTO.getQueueId()) ? apiNoticeDTO.getSetId() : apiNoticeDTO.getQueueId(); String queueIdOrSetId = StringUtils.isBlank(apiNoticeDTO.getQueueId()) ? apiNoticeDTO.getSetId() : apiNoticeDTO.getQueueId();
String[] setIdSplit = queueIdOrSetId.split("_"); String[] setIdSplit = queueIdOrSetId.split("_");

View File

@ -29,6 +29,7 @@ import io.metersphere.sdk.util.SubListUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.ExecTask; import io.metersphere.system.domain.ExecTask;
import io.metersphere.system.domain.ExecTaskItem; import io.metersphere.system.domain.ExecTaskItem;
import io.metersphere.system.mapper.ExtExecTaskItemMapper;
import io.metersphere.system.service.BaseTaskHubService; import io.metersphere.system.service.BaseTaskHubService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -72,6 +73,8 @@ public class TestPlanApiScenarioBatchRunService {
private ApiCommonService apiCommonService; private ApiCommonService apiCommonService;
@Resource @Resource
private BaseTaskHubService baseTaskHubService; private BaseTaskHubService baseTaskHubService;
@Resource
private ExtExecTaskItemMapper extExecTaskItemMapper;
/** /**
* 批量执行 * 批量执行
@ -87,7 +90,21 @@ public class TestPlanApiScenarioBatchRunService {
.map(TestPlanApiScenarioBatchRunDTO::getTestPlanCollectionId) .map(TestPlanApiScenarioBatchRunDTO::getTestPlanCollectionId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
List<TestPlanCollection> testPlanCollections = getTestPlanCollections(request.getTestPlanId()); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
// 初始化任务
ExecTask execTask = initExecTask(testPlanApiScenarios.size(), project, userId, request.getTestPlanId());
// 初始化任务项
initExecTaskItem(testPlanApiScenarios, userId, project, execTask, testPlan.getId());
Thread.startVirtualThread(() ->
doRun(execTask, request.getTestPlanId(), project, userId, hasCaseCollections, false));
}
private void doRun(ExecTask execTask, String testPlanId, Project project, String userId, Set<String> hasCaseCollections, boolean isRerun) {
List<TestPlanCollection> testPlanCollections = getTestPlanCollections(testPlanId);
Iterator<TestPlanCollection> iterator = testPlanCollections.iterator(); Iterator<TestPlanCollection> iterator = testPlanCollections.iterator();
TestPlanCollection rootCollection = new TestPlanCollection(); TestPlanCollection rootCollection = new TestPlanCollection();
while (iterator.hasNext()) { while (iterator.hasNext()) {
@ -107,19 +124,9 @@ public class TestPlanApiScenarioBatchRunService {
.sorted(Comparator.comparingLong(TestPlanCollection::getPos)) .sorted(Comparator.comparingLong(TestPlanCollection::getPos))
.collect(Collectors.toList()); .collect(Collectors.toList());
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId());
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
// 初始化任务
ExecTask execTask = initExecTask(testPlanApiScenarios.size(), project, userId);
// 初始化任务项
initExecTaskItem(testPlanApiScenarios, userId, project, execTask, testPlan.getId());
TestPlanCollection finalRootCollection = rootCollection; TestPlanCollection finalRootCollection = rootCollection;
List<TestPlanCollection> finalTestPlanCollections = testPlanCollections; List<TestPlanCollection> finalTestPlanCollections = testPlanCollections;
Thread.startVirtualThread(() -> {
List<String> execCollectionIds = finalTestPlanCollections.stream().map(TestPlanCollection::getId).toList(); List<String> execCollectionIds = finalTestPlanCollections.stream().map(TestPlanCollection::getId).toList();
if (apiBatchRunBaseService.isParallel(finalRootCollection.getExecuteMethod())) { if (apiBatchRunBaseService.isParallel(finalRootCollection.getExecuteMethod())) {
// 记录并行执行测试集用于统计整体执行情况 // 记录并行执行测试集用于统计整体执行情况
@ -130,20 +137,19 @@ public class TestPlanApiScenarioBatchRunService {
ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(finalRootCollection, collection); ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(finalRootCollection, collection);
if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) { if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) {
// 并行执行测试集中的用例 // 并行执行测试集中的用例
parallelExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), project, userId); parallelExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), project, userId, isRerun);
} else { } else {
// 串行执行测试集中的用例 // 串行执行测试集中的用例
serialExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), userId); serialExecute(execTask.getId(), collection.getId(), runModeConfig, null, execTask.getId(), userId, isRerun);
} }
} }
} else { } else {
// 生成测试集队列 // 生成测试集队列
ExecutionQueue collectionQueue = apiBatchRunBaseService.initExecutionqueue(execTask.getId(), execCollectionIds, null, ExecutionQueue collectionQueue = apiBatchRunBaseService.initExecutionqueue(execTask.getId(), execCollectionIds, null,
ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name(), null, userId); ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name(), null, userId, isRerun);
executeNextCollection(collectionQueue.getQueueId()); executeNextCollection(collectionQueue.getQueueId(), isRerun);
} }
});
} }
private List<TestPlanCollection> getTestPlanCollections(String testPlanId) { private List<TestPlanCollection> getTestPlanCollections(String testPlanId) {
@ -165,7 +171,7 @@ public class TestPlanApiScenarioBatchRunService {
return collectionMap; return collectionMap;
} }
public void executeNextCollection(String collectionQueueId) { public void executeNextCollection(String collectionQueueId, boolean isRerun) {
ExecutionQueue collectionQueue = apiExecutionQueueService.getQueue(collectionQueueId); ExecutionQueue collectionQueue = apiExecutionQueueService.getQueue(collectionQueueId);
if (collectionQueue == null) { if (collectionQueue == null) {
// 失败停止或者执行完成更新任务状态 // 失败停止或者执行完成更新任务状态
@ -182,9 +188,9 @@ public class TestPlanApiScenarioBatchRunService {
ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(collection); ApiRunModeConfigDTO runModeConfig = testPlanApiBatchRunBaseService.getApiRunModeConfig(collection);
if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) { if (apiBatchRunBaseService.isParallel(runModeConfig.getRunMode())) {
parallelExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, project, userId); parallelExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, project, userId, isRerun);
} else { } else {
serialExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, userId); serialExecute(collectionQueueId, collectionId, runModeConfig, collectionQueueId, null, userId, isRerun);
} }
} }
@ -200,12 +206,13 @@ public class TestPlanApiScenarioBatchRunService {
ApiRunModeConfigDTO runModeConfig, ApiRunModeConfigDTO runModeConfig,
String parentQueueId, String parentQueueId,
String parentSetId, String parentSetId,
String userId) { String userId,
boolean isRerun) {
// 初始化执行队列 // 初始化执行队列
ExecutionQueue queue = apiBatchRunBaseService.initExecutionQueue(taskId, taskId + '_' + collectionId, runModeConfig, ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name(), parentQueueId, parentSetId, userId); ExecutionQueue queue = apiBatchRunBaseService.initExecutionQueue(taskId, taskId + '_' + collectionId, runModeConfig, ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name(), parentQueueId, parentSetId, userId);
List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, false); List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, isRerun);
apiBatchRunBaseService.initQueueDetail(queue, execTaskItems); apiBatchRunBaseService.initQueueDetail(queue, execTaskItems);
@ -223,7 +230,7 @@ public class TestPlanApiScenarioBatchRunService {
String parentQueueId, String parentQueueId,
String parentSetId, String parentSetId,
Project project, Project project,
String userId) { String userId, boolean isRerun) {
TaskBatchRequestDTO taskRequest = getTaskBatchRequestDTO(project.getId(), runModeConfig); TaskBatchRequestDTO taskRequest = getTaskBatchRequestDTO(project.getId(), runModeConfig);
TaskInfo taskInfo = taskRequest.getTaskInfo(); TaskInfo taskInfo = taskRequest.getTaskInfo();
@ -239,7 +246,7 @@ public class TestPlanApiScenarioBatchRunService {
taskRequest.getTaskInfo().setParentSetId(parentSetId); taskRequest.getTaskInfo().setParentSetId(parentSetId);
} }
List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, false); List<ExecTaskItem> execTaskItems = apiBatchRunBaseService.getExecTaskItemByTaskIdAndCollectionId(taskId, collectionId, isRerun);
SubListUtils.dealForSubList(execTaskItems, ApiBatchRunBaseService.BATCH_TASK_ITEM_SIZE, subExecTaskItems -> { SubListUtils.dealForSubList(execTaskItems, ApiBatchRunBaseService.BATCH_TASK_ITEM_SIZE, subExecTaskItems -> {
List<TaskItem> taskItems = subExecTaskItems List<TaskItem> taskItems = subExecTaskItems
.stream() .stream()
@ -263,13 +270,14 @@ public class TestPlanApiScenarioBatchRunService {
}); });
} }
private ExecTask initExecTask(int caseSize, Project project, String userId) { private ExecTask initExecTask(int caseSize, Project project, String userId, String testPlanId) {
ExecTask execTask = apiCommonService.newExecTask(project.getId(), userId); ExecTask execTask = apiCommonService.newExecTask(project.getId(), userId);
execTask.setCaseCount(Long.valueOf(caseSize)); execTask.setCaseCount(Long.valueOf(caseSize));
execTask.setTaskName(Translator.get("api_scenario_batch_task_name")); execTask.setTaskName(Translator.get("api_scenario_batch_task_name"));
execTask.setOrganizationId(project.getOrganizationId()); execTask.setOrganizationId(project.getOrganizationId());
execTask.setTriggerMode(TaskTriggerMode.BATCH.name()); execTask.setTriggerMode(TaskTriggerMode.BATCH.name());
execTask.setTaskType(ExecTaskType.TEST_PLAN_API_SCENARIO_BATCH.name()); execTask.setTaskType(ExecTaskType.TEST_PLAN_API_SCENARIO_BATCH.name());
execTask.setResourceId(testPlanId);
baseTaskHubService.insertExecTask(execTask); baseTaskHubService.insertExecTask(execTask);
return execTask; return execTask;
} }
@ -372,4 +380,12 @@ public class TestPlanApiScenarioBatchRunService {
apiBatchRunBaseService.updateTaskCompletedStatus(parentSetId); apiBatchRunBaseService.updateTaskCompletedStatus(parentSetId);
} }
} }
public void rerun(ExecTask execTask, String userId) {
String planId = execTask.getResourceId();
Set<String> rerunCollectionIds = extExecTaskItemMapper.selectRerunCollectionIds(execTask.getId());
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
Project project = projectMapper.selectByPrimaryKey(testPlan.getProjectId());
doRun(execTask, planId, project, userId, rerunCollectionIds, true);
}
} }

View File

@ -97,7 +97,7 @@ public class TestPlanApiScenarioExecuteCallbackService implements ApiExecuteCall
@Override @Override
public void executeNextCollection(ApiNoticeDTO apiNoticeDTO, boolean isStopOnFailure) { public void executeNextCollection(ApiNoticeDTO apiNoticeDTO, boolean isStopOnFailure) {
if (StringUtils.isNotBlank(apiNoticeDTO.getParentQueueId())) { if (StringUtils.isNotBlank(apiNoticeDTO.getParentQueueId())) {
testPlanApiScenarioBatchRunService.executeNextCollection(apiNoticeDTO.getParentQueueId()); testPlanApiScenarioBatchRunService.executeNextCollection(apiNoticeDTO.getParentQueueId(), apiNoticeDTO.getRerun());
} else if (StringUtils.isNotBlank(apiNoticeDTO.getParentSetId())) { } else if (StringUtils.isNotBlank(apiNoticeDTO.getParentSetId())) {
String queueIdOrSetId = StringUtils.isBlank(apiNoticeDTO.getQueueId()) ? apiNoticeDTO.getSetId() : apiNoticeDTO.getQueueId(); String queueIdOrSetId = StringUtils.isBlank(apiNoticeDTO.getQueueId()) ? apiNoticeDTO.getSetId() : apiNoticeDTO.getQueueId();
String[] setIdSplit = queueIdOrSetId.split("_"); String[] setIdSplit = queueIdOrSetId.split("_");

View File

@ -0,0 +1,31 @@
package io.metersphere.plan.service.rerun;
import io.metersphere.plan.service.TestPlanApiCaseBatchRunService;
import io.metersphere.sdk.constants.ExecTaskType;
import io.metersphere.system.domain.ExecTask;
import io.metersphere.system.invoker.TaskRerunServiceInvoker;
import io.metersphere.system.service.TaskRerunService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @Author: jianxing
* @CreateTime: 2024-02-06 20:47
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanApiCaseBatchRerunService implements TaskRerunService {
@Resource
private TestPlanApiCaseBatchRunService testPlanApiCaseBatchRunService;
public TestPlanApiCaseBatchRerunService() {
TaskRerunServiceInvoker.register(ExecTaskType.TEST_PLAN_API_CASE_BATCH, this);
}
@Override
public void rerun(ExecTask execTask, String userId) {
testPlanApiCaseBatchRunService.rerun(execTask, userId);
}
}

View File

@ -0,0 +1,31 @@
package io.metersphere.plan.service.rerun;
import io.metersphere.plan.service.TestPlanApiScenarioBatchRunService;
import io.metersphere.sdk.constants.ExecTaskType;
import io.metersphere.system.domain.ExecTask;
import io.metersphere.system.invoker.TaskRerunServiceInvoker;
import io.metersphere.system.service.TaskRerunService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @Author: jianxing
* @CreateTime: 2024-02-06 20:47
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanApiScenarioBatchRerunService implements TaskRerunService {
@Resource
private TestPlanApiScenarioBatchRunService testPlanApiScenarioBatchRunService;
public TestPlanApiScenarioBatchRerunService() {
TaskRerunServiceInvoker.register(ExecTaskType.TEST_PLAN_API_SCENARIO_BATCH, this);
}
@Override
public void rerun(ExecTask execTask, String userId) {
testPlanApiScenarioBatchRunService.rerun(execTask, userId);
}
}

View File

@ -25,6 +25,6 @@ public class TestPlanGroupRerunService implements TaskRerunService {
@Override @Override
public void rerun(ExecTask execTask, String userId) { public void rerun(ExecTask execTask, String userId) {
Thread.startVirtualThread(() -> testPlanExecuteService.testPlanOrGroupRerun(execTask, userId)); testPlanExecuteService.testPlanOrGroupRerun(execTask, userId);
} }
} }

View File

@ -25,6 +25,6 @@ public class TestPlanRerunService implements TaskRerunService {
@Override @Override
public void rerun(ExecTask execTask, String userId) { public void rerun(ExecTask execTask, String userId) {
Thread.startVirtualThread(() -> testPlanExecuteService.testPlanOrGroupRerun(execTask, userId)); testPlanExecuteService.testPlanOrGroupRerun(execTask, userId);
} }
} }