feat(测试计划): 功能用例批量执行
This commit is contained in:
parent
26dfcd3fcb
commit
e8c29ee662
|
@ -88,7 +88,7 @@ public class TestPlanFunctionalCaseController {
|
|||
testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE));
|
||||
BasePlanCaseBatchRequest batchRequest = new BasePlanCaseBatchRequest();
|
||||
batchRequest.setTestPlanId(request.getTestPlanId());
|
||||
batchRequest.setSelectIds(List.of(request.getRefId()));
|
||||
batchRequest.setSelectIds(List.of(request.getId()));
|
||||
return testPlanFunctionalCaseService.disassociate(batchRequest, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/association", HttpMethodConstants.POST.name()));
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,16 @@ public class TestPlanFunctionalCaseController {
|
|||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
|
||||
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
|
||||
public void run(@Validated @RequestBody TestPlanCaseRunRequest request) {
|
||||
testPlanFunctionalCaseService.run(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/run", HttpMethodConstants.POST.name()));
|
||||
testPlanFunctionalCaseService.run(request, SessionUtils.getCurrentOrganizationId(), new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/run", HttpMethodConstants.POST.name()));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/batch/run")
|
||||
@Operation(summary = "测试计划-计划详情-功能用例-批量执行")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
|
||||
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
|
||||
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()));
|
||||
}
|
||||
|
||||
@PostMapping("/has/associate/bug/page")
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package io.metersphere.plan.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author wx
|
||||
*/
|
||||
@Data
|
||||
public class TestPlanCaseBatchRunRequest extends BasePlanCaseBatchRequest {
|
||||
|
||||
@Schema(description = "项目Id")
|
||||
@NotBlank(message = "{test_plan.project_id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "最终执行结果")
|
||||
@NotBlank(message = "{test_plan.last_exec_result.not_blank}")
|
||||
private String lastExecResult;
|
||||
|
||||
@Schema(description = "执行内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "评论@的人的Id, 多个以';'隔开")
|
||||
private String notifier;
|
||||
|
||||
@Schema(description = "测试计划执行评论副文本的文件id集合")
|
||||
private List<String> planCommentFileIds;
|
||||
|
||||
|
||||
}
|
|
@ -10,5 +10,5 @@ public class TestPlanDisassociationRequest {
|
|||
private String testPlanId;
|
||||
|
||||
@Schema(description = "测试计划用例关系ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String refId;
|
||||
private String id;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,13 @@ public interface ExtTestPlanFunctionalCaseMapper {
|
|||
|
||||
/**
|
||||
* 获取计划下的功能用例集合
|
||||
*
|
||||
* @param planIds 测试计划ID集合
|
||||
* @return 计划功能用例集合
|
||||
*/
|
||||
List<TestPlanFunctionalCase> getPlanFunctionalCaseByIds(@Param("planIds") List<String> planIds);
|
||||
|
||||
List<String> selectIdByConditions(@Param("request") BasePlanCaseBatchRequest request, @Param("projectId") String projectId);
|
||||
|
||||
void batchUpdate(@Param("ids") List<String> ids, @Param("lastExecResult") String lastExecResult, @Param("lastExecTime") long lastExecTime, @Param("userId") String userId);
|
||||
}
|
||||
|
|
|
@ -479,4 +479,68 @@
|
|||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectIdByConditions" resultType="java.lang.String">
|
||||
SELECT
|
||||
test_plan_functional_case.id
|
||||
FROM test_plan_functional_case
|
||||
join functional_case on test_plan_functional_case.functional_case_id = functional_case.id
|
||||
WHERE functional_case.project_id = #{projectId}
|
||||
and functional_case.deleted = false
|
||||
and test_plan_functional_case.test_plan_id = #{request.testPlanId}
|
||||
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
||||
</select>
|
||||
|
||||
|
||||
<sql id="queryWhereConditionByBaseQueryRequest">
|
||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||
and functional_case.module_id in
|
||||
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
|
||||
#{moduleId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="request.condition.keyword != null and request.condition.keyword != ''">
|
||||
and (
|
||||
functional_case.name like concat('%', #{request.condition.keyword},'%')
|
||||
or functional_case.num like concat('%', #{request.condition.keyword},'%')
|
||||
or functional_case.tags like concat('%', #{request.condition.keyword},'%')
|
||||
)
|
||||
</if>
|
||||
<include refid="filters">
|
||||
<property name="filter" value="request.condition.filter"/>
|
||||
</include>
|
||||
<choose>
|
||||
<when test='request.condition.searchMode == "AND"'>
|
||||
AND <include refid="baseQueryCombine"/>
|
||||
</when>
|
||||
<when test='request.condition.searchMode == "OR"'>
|
||||
and (
|
||||
<include refid="baseQueryCombine"/>
|
||||
)
|
||||
</when>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<sql id="baseQueryCombine">
|
||||
<if test="request.condition.combine != null">
|
||||
<include refid="combine">
|
||||
<property name="condition" value="request.condition.combine"/>
|
||||
<property name="searchMode" value="request.condition.searchMode"/>
|
||||
</include>
|
||||
</if>
|
||||
1=1
|
||||
</sql>
|
||||
|
||||
|
||||
<update id="batchUpdate">
|
||||
update test_plan_functional_case
|
||||
set last_exec_result = #{lastExecResult},
|
||||
last_exec_time = #{lastExecTime},
|
||||
execute_user = #{userId}
|
||||
where id in
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</update>
|
||||
</mapper>
|
|
@ -9,11 +9,14 @@ import io.metersphere.bug.mapper.BugRelationCaseMapper;
|
|||
import io.metersphere.bug.mapper.ExtBugRelateCaseMapper;
|
||||
import io.metersphere.dto.BugProviderDTO;
|
||||
import io.metersphere.functional.constants.CaseFileSourceType;
|
||||
import io.metersphere.functional.domain.FunctionalCase;
|
||||
import io.metersphere.functional.domain.FunctionalCaseExample;
|
||||
import io.metersphere.functional.domain.FunctionalCaseModule;
|
||||
import io.metersphere.functional.dto.FunctionalCaseCustomFieldDTO;
|
||||
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
||||
import io.metersphere.functional.dto.FunctionalCaseModuleDTO;
|
||||
import io.metersphere.functional.dto.ProjectOptionDTO;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseMapper;
|
||||
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
||||
import io.metersphere.functional.service.FunctionalCaseModuleService;
|
||||
import io.metersphere.functional.service.FunctionalCaseService;
|
||||
|
@ -44,11 +47,13 @@ import io.metersphere.sdk.util.JSON;
|
|||
import io.metersphere.sdk.util.SubListUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.LogInsertModule;
|
||||
import io.metersphere.system.dto.builder.LogDTOBuilder;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.log.aspect.OperationLogAspect;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.service.UserLoginService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
|
@ -107,6 +112,10 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
|||
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
|
||||
@Resource
|
||||
private TestPlanSendNoticeService testPlanSendNoticeService;
|
||||
@Resource
|
||||
private FunctionalCaseMapper functionalCaseMapper;
|
||||
@Resource
|
||||
private OperationLogService operationLogService;
|
||||
private static final String CASE_MODULE_COUNT_ALL = "all";
|
||||
|
||||
@Override
|
||||
|
@ -363,7 +372,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
|||
* @param request
|
||||
* @param logInsertModule
|
||||
*/
|
||||
public void run(TestPlanCaseRunRequest request, LogInsertModule logInsertModule) {
|
||||
public void run(TestPlanCaseRunRequest request, String organizationId, LogInsertModule logInsertModule) {
|
||||
TestPlanFunctionalCase functionalCase = new TestPlanFunctionalCase();
|
||||
functionalCase.setLastExecResult(request.getLastExecResult());
|
||||
functionalCase.setLastExecTime(System.currentTimeMillis());
|
||||
|
@ -375,26 +384,10 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
|||
TestPlanCaseExecuteHistory executeHistory = buildHistory(request, logInsertModule.getOperator());
|
||||
testPlanCaseExecuteHistoryMapper.insert(executeHistory);
|
||||
|
||||
//富文本评论的处理
|
||||
functionalCaseAttachmentService.uploadMinioFile(request.getCaseId(), request.getProjectId(), request.getPlanCommentFileIds(), logInsertModule.getOperator(), CaseFileSourceType.PLAN_COMMENT.toString());
|
||||
|
||||
//发通知
|
||||
if (StringUtils.isNotBlank(request.getNotifier())) {
|
||||
List<String> relatedUsers = Arrays.asList(request.getNotifier().split(";"));
|
||||
testPlanSendNoticeService.sendNoticeCase(relatedUsers, logInsertModule.getOperator(), request.getCaseId(), NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.REVIEW_AT, request.getTestPlanId());
|
||||
}
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(request.getLastExecResult(), FunctionalCaseExecuteResult.SUCCESS.name())) {
|
||||
//成功 发送通知
|
||||
testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), logInsertModule.getOperator(), request.getCaseId(), NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.EXECUTE_PASSED, request.getTestPlanId());
|
||||
}
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(request.getLastExecResult(), FunctionalCaseExecuteResult.ERROR.name())) {
|
||||
//失败 发送通知
|
||||
testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), logInsertModule.getOperator(), request.getCaseId(), NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.EXECUTE_FAIL, request.getTestPlanId());
|
||||
}
|
||||
|
||||
//TODO 日志
|
||||
Map<String, String> idsMap = new HashMap<>();
|
||||
idsMap.put(request.getId(), request.getCaseId());
|
||||
List<LogDTO> logDTOList = runLog(idsMap, Arrays.asList(request.getCaseId()), request.getProjectId(), organizationId, new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, logInsertModule));
|
||||
operationLogService.batchAdd(logDTOList);
|
||||
}
|
||||
|
||||
|
||||
|
@ -416,4 +409,118 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
|||
public List<BugProviderDTO> hasAssociateBugPage(AssociateBugPageRequest request) {
|
||||
return baseAssociateBugProvider.hasTestPlanAssociateBugPage(request);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 批量执行功能用例
|
||||
*
|
||||
* @param request
|
||||
* @param logInsertModule
|
||||
*/
|
||||
public void batchRun(TestPlanCaseBatchRunRequest request, String organizationId, LogInsertModule logInsertModule) {
|
||||
List<String> ids = doSelectIds(request, request.getProjectId());
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
handleBatchRun(ids, organizationId, request, logInsertModule);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleBatchRun(List<String> ids, String organizationId, TestPlanCaseBatchRunRequest request, LogInsertModule logInsertModule) {
|
||||
//更新状态
|
||||
extTestPlanFunctionalCaseMapper.batchUpdate(ids, request.getLastExecResult(), System.currentTimeMillis(), logInsertModule.getOperator());
|
||||
|
||||
//执行记录
|
||||
TestPlanFunctionalCaseExample example = new TestPlanFunctionalCaseExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
List<TestPlanFunctionalCase> functionalCases = testPlanFunctionalCaseMapper.selectByExample(example);
|
||||
List<String> caseIds = functionalCases.stream().map(TestPlanFunctionalCase::getFunctionalCaseId).collect(Collectors.toList());
|
||||
Map<String, String> idsMap = functionalCases.stream().collect(Collectors.toMap(TestPlanFunctionalCase::getId, TestPlanFunctionalCase::getFunctionalCaseId));
|
||||
List<TestPlanCaseExecuteHistory> historyList = getExecHistory(ids, request, logInsertModule, idsMap);
|
||||
testPlanCaseExecuteHistoryMapper.batchInsert(historyList);
|
||||
|
||||
List<LogDTO> logDTOList = runLog(idsMap, caseIds, request.getProjectId(), organizationId, new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, logInsertModule));
|
||||
operationLogService.batchAdd(logDTOList);
|
||||
}
|
||||
|
||||
private List<TestPlanCaseExecuteHistory> getExecHistory(List<String> ids, TestPlanCaseBatchRunRequest request, LogInsertModule logInsertModule, Map<String, String> idsMap) {
|
||||
|
||||
List<TestPlanCaseExecuteHistory> historyList = new ArrayList<>();
|
||||
ids.forEach(id -> {
|
||||
TestPlanCaseExecuteHistory executeHistory = new TestPlanCaseExecuteHistory();
|
||||
executeHistory.setId(IDGenerator.nextStr());
|
||||
executeHistory.setTestPlanCaseId(id);
|
||||
executeHistory.setCaseId(idsMap.get(id));
|
||||
executeHistory.setStatus(request.getLastExecResult());
|
||||
executeHistory.setContent(request.getContent().getBytes());
|
||||
executeHistory.setDeleted(false);
|
||||
executeHistory.setNotifier(request.getNotifier());
|
||||
executeHistory.setCreateUser(logInsertModule.getOperator());
|
||||
executeHistory.setCreateTime(System.currentTimeMillis());
|
||||
historyList.add(executeHistory);
|
||||
|
||||
handleFileAndNotice(idsMap.get(id), request.getProjectId(), request.getPlanCommentFileIds(), logInsertModule.getOperator(), CaseFileSourceType.PLAN_COMMENT.toString(), request.getNotifier(), request.getTestPlanId(), request.getLastExecResult());
|
||||
|
||||
|
||||
});
|
||||
return historyList;
|
||||
}
|
||||
|
||||
private void handleFileAndNotice(String caseId, String projectId, List<String> uploadFileIds, String userId, String fileSource, String notifier, String testPlanId, String lastExecResult) {
|
||||
//富文本评论的处理
|
||||
functionalCaseAttachmentService.uploadMinioFile(caseId, projectId, uploadFileIds, userId, fileSource);
|
||||
|
||||
//发通知
|
||||
if (StringUtils.isNotBlank(notifier)) {
|
||||
List<String> relatedUsers = Arrays.asList(notifier.split(";"));
|
||||
testPlanSendNoticeService.sendNoticeCase(relatedUsers, userId, caseId, NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.REVIEW_AT, testPlanId);
|
||||
}
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(lastExecResult, FunctionalCaseExecuteResult.SUCCESS.name())) {
|
||||
//成功 发送通知
|
||||
testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.EXECUTE_PASSED, testPlanId);
|
||||
}
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(lastExecResult, FunctionalCaseExecuteResult.ERROR.name())) {
|
||||
//失败 发送通知
|
||||
testPlanSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.TEST_PLAN_TASK, NoticeConstants.Event.EXECUTE_FAIL, testPlanId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<String> doSelectIds(BasePlanCaseBatchRequest request, String projectId) {
|
||||
if (request.isSelectAll()) {
|
||||
List<String> ids = extTestPlanFunctionalCaseMapper.selectIdByConditions(request, projectId);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
ids.removeAll(request.getExcludeIds());
|
||||
}
|
||||
return ids;
|
||||
} else {
|
||||
return request.getSelectIds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<LogDTO> runLog(Map<String, String> idsMap, List<String> caseIds, String projectId, String organizationId, ResourceLogInsertModule logInsertModule) {
|
||||
FunctionalCaseExample example = new FunctionalCaseExample();
|
||||
example.createCriteria().andIdIn(caseIds);
|
||||
List<FunctionalCase> functionalCases = functionalCaseMapper.selectByExample(example);
|
||||
Map<String, String> caseMap = functionalCases.stream().collect(Collectors.toMap(FunctionalCase::getId, FunctionalCase::getName));
|
||||
List<LogDTO> list = new ArrayList<>();
|
||||
idsMap.forEach((k, v) -> {
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(projectId)
|
||||
.organizationId(organizationId)
|
||||
.type(OperationLogType.EXECUTE.name())
|
||||
.module(OperationLogModule.TEST_PLAN)
|
||||
.method(logInsertModule.getRequestMethod())
|
||||
.path(logInsertModule.getRequestUrl())
|
||||
.sourceId(k)
|
||||
.content(Translator.get("run_functional_case") + ":" + caseMap.get(v))
|
||||
.createUser(logInsertModule.getOperator())
|
||||
.build().getLogDTO();
|
||||
list.add(dto);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public class TestPlanCaseControllerTests extends BaseTest {
|
|||
|
||||
|
||||
public static final String FUNCTIONAL_CASE_RUN_URL = "/test-plan/functional/case/run";
|
||||
public static final String FUNCTIONAL_CASE_BATCH_RUN_URL = "/test-plan/functional/case/batch/run";
|
||||
@Resource
|
||||
private TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper;
|
||||
@Resource
|
||||
|
@ -100,7 +101,7 @@ public class TestPlanCaseControllerTests extends BaseTest {
|
|||
void disassociate() throws Exception {
|
||||
TestPlanDisassociationRequest request = new TestPlanDisassociationRequest();
|
||||
request.setTestPlanId("gyq_disassociate_plan_1");
|
||||
request.setRefId("gyq_disassociate_case_3");
|
||||
request.setId("gyq_disassociate_case_3");
|
||||
this.requestPostWithOk(FUNCTIONAL_CASE_DISASSOCIATE_URL, request);
|
||||
}
|
||||
|
||||
|
@ -190,4 +191,24 @@ public class TestPlanCaseControllerTests extends BaseTest {
|
|||
this.requestPostWithOk(FUNCTIONAL_CASE_RUN_URL, request);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Order(12)
|
||||
public void testFunctionalCaseBatchRun() throws Exception {
|
||||
TestPlanCaseBatchRunRequest request = new TestPlanCaseBatchRunRequest();
|
||||
request.setProjectId("1234");
|
||||
request.setTestPlanId("plan_2");
|
||||
request.setLastExecResult("SUCCESS");
|
||||
request.setContent("12334");
|
||||
request.setNotifier("123");
|
||||
request.setSelectAll(true);
|
||||
this.requestPostWithOk(FUNCTIONAL_CASE_BATCH_RUN_URL, request);
|
||||
request.setSelectAll(false);
|
||||
request.setSelectIds(List.of("relate_case_3"));
|
||||
request.setLastExecResult("ERROR");
|
||||
this.requestPostWithOk(FUNCTIONAL_CASE_BATCH_RUN_URL, request);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue