feat(测试跟踪): 测试计划增加执行成功和失败的消息通知功能

测试计划增加执行成功和失败的消息通知功能
This commit is contained in:
song-tianyang 2022-04-14 15:10:42 +08:00 committed by TIanyang
parent 09f4d7057e
commit 6207c72d70
9 changed files with 149 additions and 133 deletions

View File

@ -23,6 +23,7 @@ import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -55,10 +56,9 @@ public class ApiExecutionQueueService {
private ExtApiExecutionQueueMapper extApiExecutionQueueMapper; private ExtApiExecutionQueueMapper extApiExecutionQueueMapper;
@Resource @Resource
private ApiScenarioReportResultMapper apiScenarioReportResultMapper; private ApiScenarioReportResultMapper apiScenarioReportResultMapper;
@Lazy
@Resource @Resource
private TestPlanExecutionQueueMapper testPlanExecutionQueueMapper; private TestPlanReportService testPlanReportService;
@Resource
private TestPlanReportMapper testPlanReportMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW) @Transactional(propagation = Propagation.REQUIRES_NEW)
@ -92,6 +92,22 @@ public class ApiExecutionQueueService {
queueDetails.add(queue); queueDetails.add(queue);
detailMap.put(k, queue.getId()); detailMap.put(k, queue.getId());
}); });
} else if (StringUtils.equalsIgnoreCase(type, ApiRunMode.TEST_PLAN_PERFORMANCE_TEST.name())) {
final int[] sort = {0};
Map<String, String> runMap = (Map<String, String>) runObj;
if (config.getEnvMap() == null) {
config.setEnvMap(new LinkedHashMap<>());
}
String envStr = JSON.toJSONString(config.getEnvMap());
runMap.forEach((k, v) -> {
ApiExecutionQueueDetail queue = detail(v, k, "loadTest", sort[0], executionQueue.getId(), envStr);
if (sort[0] == 0) {
resQueue.setQueue(queue);
}
sort[0]++;
queueDetails.add(queue);
detailMap.put(k, queue.getId());
});
} else { } else {
Map<String, RunModeDataDTO> runMap = (Map<String, RunModeDataDTO>) runObj; Map<String, RunModeDataDTO> runMap = (Map<String, RunModeDataDTO>) runObj;
final int[] sort = {0}; final int[] sort = {0};
@ -304,7 +320,7 @@ public class ApiExecutionQueueService {
// 计算一小时前的超时报告 // 计算一小时前的超时报告
final long timeout = System.currentTimeMillis() - (60 * MINUTE_MILLIS); final long timeout = System.currentTimeMillis() - (60 * MINUTE_MILLIS);
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample(); ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
example.createCriteria().andCreateTimeLessThan(timeout); example.createCriteria().andCreateTimeLessThan(timeout).andTypeNotEqualTo("loadTest");
List<ApiExecutionQueueDetail> queueDetails = executionQueueDetailMapper.selectByExample(example); List<ApiExecutionQueueDetail> queueDetails = executionQueueDetailMapper.selectByExample(example);
for (ApiExecutionQueueDetail item : queueDetails) { for (ApiExecutionQueueDetail item : queueDetails) {
@ -416,4 +432,24 @@ public class ApiExecutionQueueService {
} }
}); });
} }
public void checkExecutionQueneByLoadTest(LoadTestReport loadTestReport) {
ApiExecutionQueueDetailExample detailExample = new ApiExecutionQueueDetailExample();
detailExample.createCriteria().andReportIdEqualTo(loadTestReport.getId());
List<ApiExecutionQueueDetail> detailList = executionQueueDetailMapper.selectByExample(detailExample);
if (CollectionUtils.isNotEmpty(detailList)) {
List<String> executionQueueIdList = new ArrayList<>();
detailList.forEach(item -> {
executionQueueIdList.add(item.getQueueId());
});
executionQueueDetailMapper.deleteByExample(detailExample);
}
List<String> testPlanReportIdList = testPlanReportService.getTestPlanReportIdsByLoadTestReportId(loadTestReport.getId());
for (String testPlanReportId : testPlanReportIdList) {
this.testPlanReportTestEnded(testPlanReportId);
}
}
} }

View File

@ -317,9 +317,8 @@
<select id="findIdByPerformanceReportId" resultType="java.lang.String"> <select id="findIdByPerformanceReportId" resultType="java.lang.String">
SELECT report.id SELECT report.id
FROM test_plan_report report FROM test_plan_report report
INNER JOIN test_plan_report_data reportData ON report.id = reportData.test_plan_report_id INNER JOIN test_plan_report_content reportData ON report.id = reportData.test_plan_report_id
WHERE reportData.performance_info like CONCAT('%', #{0}, '%') WHERE reportData.plan_load_case_report_struct like CONCAT('%', #{0}, '%');
AND report.is_performance_executing = true;
</select> </select>
<select id="listRecent" resultType="io.metersphere.base.domain.TestPlan"> <select id="listRecent" resultType="io.metersphere.base.domain.TestPlan">
select distinct test_plan.* select distinct test_plan.*

View File

@ -2,6 +2,7 @@ package io.metersphere.commons.constants;
public enum ApiRunMode { public enum ApiRunMode {
RUN, DEBUG, DEFINITION, TEST_CASE, SCENARIO, API_PLAN, JENKINS_API_PLAN, JENKINS_SCENARIO_PLAN, JENKINS_PERFORMANCE_TEST, JENKINS, RUN, DEBUG, DEFINITION, TEST_CASE, SCENARIO, API_PLAN, JENKINS_API_PLAN, JENKINS_SCENARIO_PLAN, JENKINS_PERFORMANCE_TEST, JENKINS,
TEST_PLAN_PERFORMANCE_TEST,
SCENARIO_PLAN, API, SCHEDULE_API_PLAN, SCHEDULE_SCENARIO, SCHEDULE_SCENARIO_PLAN, SCHEDULE_PERFORMANCE_TEST, MANUAL_PLAN, SCENARIO_PLAN, API, SCHEDULE_API_PLAN, SCHEDULE_SCENARIO, SCHEDULE_SCENARIO_PLAN, SCHEDULE_PERFORMANCE_TEST, MANUAL_PLAN,
UI_SCENARIO, UI_SCENARIO_PLAN, UI_SCHEDULE_SCENARIO_PLAN, UI_JENKINS_SCENARIO_PLAN, UI_SCHEDULE_SCENARIO UI_SCENARIO, UI_SCENARIO_PLAN, UI_SCHEDULE_SCENARIO_PLAN, UI_JENKINS_SCENARIO_PLAN, UI_SCHEDULE_SCENARIO
} }

View File

@ -2,16 +2,17 @@ package io.metersphere.commons.consumer;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import io.metersphere.Application; import io.metersphere.Application;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.base.domain.LoadTestReport; import io.metersphere.base.domain.LoadTestReport;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.config.KafkaProperties;
import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.reflections8.Reflections; import org.reflections8.Reflections;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Set; import java.util.Set;
@Service @Service
@ -19,6 +20,9 @@ import java.util.Set;
public class LoadTestConsumer { public class LoadTestConsumer {
public static final String CONSUME_ID = "load-test-data"; public static final String CONSUME_ID = "load-test-data";
@Resource
ApiExecutionQueueService apiExecutionQueueService;
@KafkaListener(id = CONSUME_ID, topics = "${kafka.test.topic}", groupId = "${spring.kafka.consumer.group-id}") @KafkaListener(id = CONSUME_ID, topics = "${kafka.test.topic}", groupId = "${spring.kafka.consumer.group-id}")
public void consume(ConsumerRecord<?, String> record) { public void consume(ConsumerRecord<?, String> record) {
LoadTestReport loadTestReport = JSON.parseObject(record.value(), LoadTestReport.class); LoadTestReport loadTestReport = JSON.parseObject(record.value(), LoadTestReport.class);
@ -31,5 +35,7 @@ public class LoadTestConsumer {
LogUtil.error(e); LogUtil.error(e);
} }
}); });
//删除性能测试在执行队列中的数据 在测试计划执行中会将性能测试执行添加到执行队列用于判断整个测试计划到执行进度
apiExecutionQueueService.checkExecutionQueneByLoadTest(loadTestReport);
} }
} }

View File

@ -126,19 +126,7 @@ public class NoticeSendService {
public void send(Project project, String taskType, NoticeModel noticeModel) { public void send(Project project, String taskType, NoticeModel noticeModel) {
try { try {
List<MessageDetail> messageDetails; List<MessageDetail> messageDetails;
// switch (taskType) {
// case NoticeConstants.Mode.API:
// String projectId = (String) noticeModel.getParamMap().get("projectId");
// messageDetails = noticeService.searchMessageByTypeBySend(NoticeConstants.TaskType.JENKINS_TASK, projectId);
// break;
// case NoticeConstants.Mode.SCHEDULE:
// messageDetails = noticeService.searchMessageByTestId(noticeModel.getTestId());
// break;
// default:
// break;
// }
messageDetails = noticeService.searchMessageByTypeAndProjectId(taskType, project.getId()); messageDetails = noticeService.searchMessageByTypeAndProjectId(taskType, project.getId());
// 异步发送通知 // 异步发送通知
messageDetails.stream() messageDetails.stream()
.filter(messageDetail -> StringUtils.equals(messageDetail.getEvent(), noticeModel.getEvent())) .filter(messageDetail -> StringUtils.equals(messageDetail.getEvent(), noticeModel.getEvent()))

View File

@ -1,39 +0,0 @@
package io.metersphere.track.service;
import io.metersphere.base.domain.LoadTestReport;
import io.metersphere.base.domain.TestPlanReport;
import io.metersphere.commons.constants.NoticeConstants;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.consumer.LoadTestFinishEvent;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.track.dto.TestPlanLoadCaseEventDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* @author song.tianyang
* @Date 2021/1/13 2:53 下午
* @Description
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanLoadCaseEvent implements LoadTestFinishEvent {
@Resource
TestPlanReportService testPlanReportService;
@Override
public void execute(LoadTestReport loadTestReport) {
LogUtil.info("PerformanceNoticeEvent OVER:" + loadTestReport.getTriggerMode()+";"+loadTestReport.getStatus());
if (StringUtils.equals(ReportTriggerMode.TEST_PLAN_SCHEDULE.name(), loadTestReport.getTriggerMode()) ) {
TestPlanLoadCaseEventDTO eventDTO = new TestPlanLoadCaseEventDTO();
eventDTO.setReportId(loadTestReport.getId());
eventDTO.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
eventDTO.setStatus(loadTestReport.getStatus());
testPlanReportService.updatePerformanceTestStatus(eventDTO);
}
}
}

View File

@ -448,8 +448,6 @@ public class TestPlanReportService {
//初始化测试计划包含组件信息 //初始化测试计划包含组件信息
int[] componentIndexArr = new int[]{1, 3, 4}; int[] componentIndexArr = new int[]{1, 3, 4};
testPlanReport.setComponents(JSONArray.toJSONString(componentIndexArr)); testPlanReport.setComponents(JSONArray.toJSONString(componentIndexArr));
//计算测试计划状态
testPlanReport.setStatus(status);
//如果测试案例没有未结束的功能用例则更新最后结束日期 //如果测试案例没有未结束的功能用例则更新最后结束日期
TestPlanTestCaseMapper testPlanTestCaseMapper = CommonBeanFactory.getBean(TestPlanTestCaseMapper.class); TestPlanTestCaseMapper testPlanTestCaseMapper = CommonBeanFactory.getBean(TestPlanTestCaseMapper.class);
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample(); TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
@ -469,6 +467,7 @@ public class TestPlanReportService {
if(CollectionUtils.isNotEmpty(contents)){ if(CollectionUtils.isNotEmpty(contents)){
content = contents.get(0); content = contents.get(0);
} }
boolean hasErrorCase = false;
if(content!= null){ if(content!= null){
//更新接口用例场景用例的最终执行状态 //更新接口用例场景用例的最终执行状态
if(StringUtils.isNotEmpty(content.getPlanApiCaseReportStruct())){ if(StringUtils.isNotEmpty(content.getPlanApiCaseReportStruct())){
@ -493,6 +492,9 @@ public class TestPlanReportService {
} }
dto.setExecResult(execStatus); dto.setExecResult(execStatus);
} }
if(!StringUtils.equalsAnyIgnoreCase( dto.getExecResult(),"success")){
hasErrorCase = true;
}
} }
content.setPlanApiCaseReportStruct(JSONObject.toJSONString(apiTestCases)); content.setPlanApiCaseReportStruct(JSONObject.toJSONString(apiTestCases));
}catch (Exception e){ }catch (Exception e){
@ -524,6 +526,9 @@ public class TestPlanReportService {
} }
dto.setLastResult(execStatus); dto.setLastResult(execStatus);
dto.setStatus(execStatus); dto.setStatus(execStatus);
if(!StringUtils.equalsAnyIgnoreCase(execStatus,"success")){
hasErrorCase = true;
}
} }
} }
content.setPlanScenarioReportStruct(JSONObject.toJSONString(scenarioCases)); content.setPlanScenarioReportStruct(JSONObject.toJSONString(scenarioCases));
@ -536,7 +541,16 @@ public class TestPlanReportService {
content.setEndTime(endTime); content.setEndTime(endTime);
testPlanReportContentMapper.updateByExampleSelective(content, contentExample); testPlanReportContentMapper.updateByExampleSelective(content, contentExample);
} }
//计算测试计划状态
if(StringUtils.equalsIgnoreCase(status,TestPlanReportStatus.COMPLETED.name())){
if(hasErrorCase){
testPlanReport.setStatus(TestPlanReportStatus.FAILED.name());
}else {
testPlanReport.setStatus(TestPlanReportStatus.SUCCESS.name());
}
}else {
testPlanReport.setStatus(status);
}
//更新测试计划并发送通知 //更新测试计划并发送通知
testPlanReport.setIsApiCaseExecuting(false); testPlanReport.setIsApiCaseExecuting(false);
testPlanReport.setIsScenarioExecuting(false); testPlanReport.setIsScenarioExecuting(false);
@ -759,7 +773,6 @@ public class TestPlanReportService {
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo(); BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
String url = baseSystemConfigDTO.getUrl() + "/#/track/testPlan/reportList"; String url = baseSystemConfigDTO.getUrl() + "/#/track/testPlan/reportList";
String subject = ""; String subject = "";
String event = NoticeConstants.Event.COMPLETE;
String successContext = "${operator}执行的 ${name} 测试计划运行成功, 报告: ${planShareUrl}"; String successContext = "${operator}执行的 ${name} 测试计划运行成功, 报告: ${planShareUrl}";
String failedContext = "${operator}执行的 ${name} 测试计划运行失败, 报告: ${planShareUrl}"; String failedContext = "${operator}执行的 ${name} 测试计划运行失败, 报告: ${planShareUrl}";
String context = "${operator}完成了测试计划: ${name}, 报告: ${planShareUrl}"; String context = "${operator}完成了测试计划: ${name}, 报告: ${planShareUrl}";
@ -790,27 +803,44 @@ public class TestPlanReportService {
String testPlanShareUrl = shareInfoService.getTestPlanShareUrl(testPlanReport.getId(), creator); String testPlanShareUrl = shareInfoService.getTestPlanShareUrl(testPlanReport.getId(), creator);
paramMap.put("planShareUrl", baseSystemConfigDTO.getUrl() + "/sharePlanReport" + testPlanShareUrl); paramMap.put("planShareUrl", baseSystemConfigDTO.getUrl() + "/sharePlanReport" + testPlanShareUrl);
NoticeModel noticeModel = NoticeModel.builder() /**
.operator(creator) * 测试计划的消息通知配置包括 完成成功失败
.context(context) * 所以发送通知时必定会有"完成"状态的通知
.successContext(successContext) */
.successMailTemplate(successfulMailTemplate) Map<String,String> execStatusEventMap = new HashMap<>();
.failedContext(failedContext) execStatusEventMap.put(TestPlanReportStatus.COMPLETED.name(),NoticeConstants.Event.COMPLETE);
.failedMailTemplate(errfoMailTemplate) if(StringUtils.equalsIgnoreCase(testPlanReport.getStatus(),TestPlanReportStatus.SUCCESS.name())){
.mailTemplate("track/TestPlanComplete") execStatusEventMap.put(testPlanReport.getStatus(),NoticeConstants.Event.EXECUTE_SUCCESSFUL);
.testId(testPlan.getId()) }else if(StringUtils.equalsIgnoreCase(testPlanReport.getStatus(),TestPlanReportStatus.FAILED.name())){
.status(testPlanReport.getStatus()) execStatusEventMap.put(testPlanReport.getStatus(),NoticeConstants.Event.EXECUTE_FAILED);
.event(event) }else if(!StringUtils.equalsIgnoreCase(testPlanReport.getStatus(),TestPlanReportStatus.COMPLETED.name())){
.subject(subject) execStatusEventMap.put(testPlanReport.getStatus(),NoticeConstants.Event.COMPLETE);
.paramMap(paramMap)
.build();
if (StringUtils.equals(testPlanReport.getTriggerMode(), ReportTriggerMode.MANUAL.name())) {
noticeSendService.send(projectService.getProjectById(projectId), NoticeConstants.TaskType.TEST_PLAN_TASK, noticeModel);
} }
for (Map.Entry<String,String> entry : execStatusEventMap.entrySet()) {
String status = entry.getKey();
String event = entry.getValue();
NoticeModel noticeModel = NoticeModel.builder()
.operator(creator)
.context(context)
.successContext(successContext)
.successMailTemplate(successfulMailTemplate)
.failedContext(failedContext)
.failedMailTemplate(errfoMailTemplate)
.mailTemplate("track/TestPlanComplete")
.testId(testPlan.getId())
.status(status)
.event(event)
.subject(subject)
.paramMap(paramMap)
.build();
if (StringUtils.equalsAny(testPlanReport.getTriggerMode(), ReportTriggerMode.SCHEDULE.name(), ReportTriggerMode.API.name())) { if (StringUtils.equals(testPlanReport.getTriggerMode(), ReportTriggerMode.MANUAL.name())) {
noticeSendService.send(testPlanReport.getTriggerMode(), NoticeConstants.TaskType.TEST_PLAN_TASK, noticeModel); noticeSendService.send(projectService.getProjectById(projectId), NoticeConstants.TaskType.TEST_PLAN_TASK, noticeModel);
}
if (StringUtils.equalsAny(testPlanReport.getTriggerMode(), ReportTriggerMode.SCHEDULE.name(), ReportTriggerMode.API.name())) {
noticeSendService.send(testPlanReport.getTriggerMode(), NoticeConstants.TaskType.TEST_PLAN_TASK, noticeModel);
}
} }
} }
@ -818,13 +848,9 @@ public class TestPlanReportService {
return testPlanReportMapper.selectByPrimaryKey(planId); return testPlanReportMapper.selectByPrimaryKey(planId);
} }
public void updatePerformanceTestStatus(TestPlanLoadCaseEventDTO eventDTO) { public List<String> getTestPlanReportIdsByLoadTestReportId(String loadTestReportId) {
List<String> testPlanReportId = extTestPlanMapper.findIdByPerformanceReportId(eventDTO.getReportId()); List<String> testPlanReportId = extTestPlanMapper.findIdByPerformanceReportId(loadTestReportId);
if (StringUtils.equals(eventDTO.getTriggerMode(), ReportTriggerMode.API.name())) { return testPlanReportId;
this.updateReport(testPlanReportId, ApiRunMode.JENKINS_PERFORMANCE_TEST.name(), eventDTO.getTriggerMode());
} else {
this.updateReport(testPlanReportId, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name(), eventDTO.getTriggerMode());
}
} }
public void delete(List<String> testPlanReportIdList) { public void delete(List<String> testPlanReportIdList) {

View File

@ -13,10 +13,7 @@ import io.metersphere.api.dto.definition.ApiTestCaseRequest;
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest; import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
import io.metersphere.api.dto.definition.ParamsDTO; import io.metersphere.api.dto.definition.ParamsDTO;
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO; import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
import io.metersphere.api.service.ApiAutomationService; import io.metersphere.api.service.*;
import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiScenarioReportService;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*; import io.metersphere.base.mapper.ext.*;
@ -131,7 +128,8 @@ public class TestPlanService {
private ExtTestPlanLoadCaseMapper extTestPlanLoadCaseMapper; private ExtTestPlanLoadCaseMapper extTestPlanLoadCaseMapper;
@Resource @Resource
private ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper; private ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper;
@Resource
private ApiExecutionQueueService apiExecutionQueueService;
@Resource @Resource
private PerformanceTestService performanceTestService; private PerformanceTestService performanceTestService;
@Resource @Resource
@ -181,8 +179,6 @@ public class TestPlanService {
private ExtTestPlanExecutionQueueMapper extTestPlanExecutionQueueMapper; private ExtTestPlanExecutionQueueMapper extTestPlanExecutionQueueMapper;
public synchronized TestPlan addTestPlan(AddTestPlanRequest testPlan) { public synchronized TestPlan addTestPlan(AddTestPlanRequest testPlan) {
if (getTestPlanByName(testPlan.getName()).size() > 0) { if (getTestPlanByName(testPlan.getName()).size() > 0) {
MSException.throwException(Translator.get("plan_name_already_exists")); MSException.throwException(Translator.get("plan_name_already_exists"));
@ -497,9 +493,9 @@ public class TestPlanService {
testPlanWithBLOBs.setStatus(TestPlanStatus.Completed.name()); testPlanWithBLOBs.setStatus(TestPlanStatus.Completed.name());
this.editTestPlan(testPlanWithBLOBs); this.editTestPlan(testPlanWithBLOBs);
} else if (prepareNum == 0 && passNum + failNum == statusList.size()) { // 已结束 } else if (prepareNum == 0 && passNum + failNum == statusList.size()) { // 已结束
if(testPlanWithBLOBs.getPlannedEndTime() != null && testPlanWithBLOBs.getPlannedEndTime() > System.currentTimeMillis()){ if (testPlanWithBLOBs.getPlannedEndTime() != null && testPlanWithBLOBs.getPlannedEndTime() > System.currentTimeMillis()) {
testPlanWithBLOBs.setStatus(TestPlanStatus.Completed.name()); testPlanWithBLOBs.setStatus(TestPlanStatus.Completed.name());
}else{ } else {
testPlanWithBLOBs.setStatus(TestPlanStatus.Finished.name()); testPlanWithBLOBs.setStatus(TestPlanStatus.Finished.name());
} }
editTestPlan(testPlanWithBLOBs); editTestPlan(testPlanWithBLOBs);
@ -946,7 +942,7 @@ public class TestPlanService {
return reportInfoDTO; return reportInfoDTO;
} }
public String run(String testPlanID, String projectID, String userId, String triggerMode, TestPlanScheduleReportInfoDTO reportInfoDTO,String apiRunConfig) { public String run(String testPlanID, String projectID, String userId, String triggerMode, TestPlanScheduleReportInfoDTO reportInfoDTO, String apiRunConfig) {
RunModeConfigDTO runModeConfig = null; RunModeConfigDTO runModeConfig = null;
try { try {
runModeConfig = JSONObject.parseObject(apiRunConfig, RunModeConfigDTO.class); runModeConfig = JSONObject.parseObject(apiRunConfig, RunModeConfigDTO.class);
@ -965,7 +961,7 @@ public class TestPlanService {
} }
} }
//创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数 //创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数
if(reportInfoDTO==null){ if (reportInfoDTO == null) {
reportInfoDTO = this.genTestPlanReport(projectID, testPlanID, userId, triggerMode); reportInfoDTO = this.genTestPlanReport(projectID, testPlanID, userId, triggerMode);
} }
//测试计划准备执行取消测试计划的实际结束时间 //测试计划准备执行取消测试计划的实际结束时间
@ -983,7 +979,7 @@ public class TestPlanService {
Map<String, String> scenarioReportMap = this.executeScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap()); Map<String, String> scenarioReportMap = this.executeScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
//执行性能测试任务 //执行性能测试任务
LoggerUtil.info("开始执行测试计划性能用例 " + planReportId); LoggerUtil.info("开始执行测试计划性能用例 " + planReportId);
Map<String, String> loadCaseReportMap = this.executeLoadCaseTask(runModeConfig, triggerMode, reportInfoDTO.getPerformanceIdMap()); Map<String, String> loadCaseReportMap = this.executeLoadCaseTask(planReportId, runModeConfig, triggerMode, reportInfoDTO.getPerformanceIdMap());
LoggerUtil.info("开始生成测试计划报告 " + planReportId); LoggerUtil.info("开始生成测试计划报告 " + planReportId);
testPlanReportService.createTestPlanReportContentReportIds(planReportId, apiCaseReportMap, scenarioReportMap, loadCaseReportMap); testPlanReportService.createTestPlanReportContentReportIds(planReportId, apiCaseReportMap, scenarioReportMap, loadCaseReportMap);
return planReportId; return planReportId;
@ -1044,7 +1040,7 @@ public class TestPlanService {
return returnMap; return returnMap;
} }
private Map<String, String> executeLoadCaseTask(RunModeConfigDTO runModeConfig, String triggerMode, Map<String, String> performanceIdMap) { private Map<String, String> executeLoadCaseTask(String planReportId, RunModeConfigDTO runModeConfig, String triggerMode, Map<String, String> performanceIdMap) {
Map<String, String> loadCaseReportMap = new HashMap<>(); Map<String, String> loadCaseReportMap = new HashMap<>();
for (Map.Entry<String, String> entry : performanceIdMap.entrySet()) { for (Map.Entry<String, String> entry : performanceIdMap.entrySet()) {
String id = entry.getKey(); String id = entry.getKey();
@ -1057,8 +1053,6 @@ public class TestPlanService {
} }
if (StringUtils.equals(ReportTriggerMode.API.name(), triggerMode)) { if (StringUtils.equals(ReportTriggerMode.API.name(), triggerMode)) {
performanceRequest.setTriggerMode(ReportTriggerMode.TEST_PLAN_API.name()); performanceRequest.setTriggerMode(ReportTriggerMode.TEST_PLAN_API.name());
} else if (StringUtils.equals(ReportTriggerMode.MANUAL.name(), triggerMode)) {
performanceRequest.setTriggerMode(ReportTriggerMode.MANUAL.name());
} else { } else {
performanceRequest.setTriggerMode(ReportTriggerMode.TEST_PLAN_SCHEDULE.name()); performanceRequest.setTriggerMode(ReportTriggerMode.TEST_PLAN_SCHEDULE.name());
} }
@ -1084,6 +1078,11 @@ public class TestPlanService {
} }
} }
//将性能测试加入到队列中
apiExecutionQueueService.add(loadCaseReportMap, null, ApiRunMode.TEST_PLAN_PERFORMANCE_TEST.name(),
planReportId, null, null, new RunModeConfigDTO());
return loadCaseReportMap; return loadCaseReportMap;
} }
@ -1214,7 +1213,7 @@ public class TestPlanService {
planScenario.setTestPlanId(targetPlanId); planScenario.setTestPlanId(targetPlanId);
planScenario.setApiScenarioId(apiScenario.getApiScenarioId()); planScenario.setApiScenarioId(apiScenario.getApiScenarioId());
planScenario.setEnvironment(apiScenario.getEnvironment()); planScenario.setEnvironment(apiScenario.getEnvironment());
if(apiScenario.getEnvironmentType()!=null){ if (apiScenario.getEnvironmentType() != null) {
planScenario.setEnvironmentType(apiScenario.getEnvironmentType()); planScenario.setEnvironmentType(apiScenario.getEnvironmentType());
} }
planScenario.setCreateTime(System.currentTimeMillis()); planScenario.setCreateTime(System.currentTimeMillis());
@ -1394,7 +1393,7 @@ public class TestPlanService {
public void buildScenarioResponse(List<TestPlanFailureScenarioDTO> cases) { public void buildScenarioResponse(List<TestPlanFailureScenarioDTO> cases) {
if (!CollectionUtils.isEmpty(cases)) { if (!CollectionUtils.isEmpty(cases)) {
cases.forEach((item) -> { cases.forEach((item) -> {
item.setResponse(apiScenarioReportService.get(item.getReportId(),true)); item.setResponse(apiScenarioReportService.get(item.getReportId(), true));
}); });
} }
} }
@ -1529,17 +1528,17 @@ public class TestPlanService {
List<TestPlanFailureScenarioDTO> scenarioAllCases = null; List<TestPlanFailureScenarioDTO> scenarioAllCases = null;
if (checkReportConfig(config, "api", "all")) { if (checkReportConfig(config, "api", "all")) {
// 接口 // 接口
if(CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getApiCaseInfoDTOList())){ if (CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getApiCaseInfoDTOList())) {
apiAllCases = testPlanExecuteReportDTO.getApiCaseInfoDTOList(); apiAllCases = testPlanExecuteReportDTO.getApiCaseInfoDTOList();
}else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) { } else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) {
apiAllCases = testPlanApiCaseService.getByApiExecReportIds(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap()); apiAllCases = testPlanApiCaseService.getByApiExecReportIds(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap());
} }
report.setApiAllCases(apiAllCases); report.setApiAllCases(apiAllCases);
//场景 //场景
if(CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getScenarioInfoDTOList())){ if (CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getScenarioInfoDTOList())) {
scenarioAllCases = testPlanExecuteReportDTO.getScenarioInfoDTOList(); scenarioAllCases = testPlanExecuteReportDTO.getScenarioInfoDTOList();
}else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap())) { } else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap())) {
scenarioAllCases = testPlanScenarioCaseService.getAllCases(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap()); scenarioAllCases = testPlanScenarioCaseService.getAllCases(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap());
} }
report.setScenarioAllCases(scenarioAllCases); report.setScenarioAllCases(scenarioAllCases);
@ -1762,15 +1761,15 @@ public class TestPlanService {
testPlanScenarioCaseService.calculatePlanReport(planId, report); testPlanScenarioCaseService.calculatePlanReport(planId, report);
testPlanLoadCaseService.calculatePlanReport(planId, report); testPlanLoadCaseService.calculatePlanReport(planId, report);
} else { } else {
if(CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getApiCaseInfoDTOList())){ if (CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getApiCaseInfoDTOList())) {
testPlanApiCaseService.calculatePlanReportByApiCaseList(testPlanExecuteReportDTO.getApiCaseInfoDTOList(), report); testPlanApiCaseService.calculatePlanReportByApiCaseList(testPlanExecuteReportDTO.getApiCaseInfoDTOList(), report);
}else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) { } else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) {
testPlanApiCaseService.calculatePlanReport(new ArrayList<>(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap().values()), report); testPlanApiCaseService.calculatePlanReport(new ArrayList<>(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap().values()), report);
} }
if(CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getScenarioInfoDTOList())){ if (CollectionUtils.isNotEmpty(testPlanExecuteReportDTO.getScenarioInfoDTOList())) {
testPlanScenarioCaseService.calculatePlanReportByScenarioList(testPlanExecuteReportDTO.getScenarioInfoDTOList(), report); testPlanScenarioCaseService.calculatePlanReportByScenarioList(testPlanExecuteReportDTO.getScenarioInfoDTOList(), report);
}else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap())) { } else if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap())) {
testPlanScenarioCaseService.calculatePlanReport(new ArrayList<>(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap().values()), report); testPlanScenarioCaseService.calculatePlanReport(new ArrayList<>(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap().values()), report);
} }
@ -1853,7 +1852,7 @@ public class TestPlanService {
String apiRunConfig = JSONObject.toJSONString(runModeConfig); String apiRunConfig = JSONObject.toJSONString(runModeConfig);
updatePlan(testplanRunRequest, testPlanId); updatePlan(testplanRunRequest, testPlanId);
return this.run(testPlanId, testplanRunRequest.getProjectId(), return this.run(testPlanId, testplanRunRequest.getProjectId(),
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(),testplanRunRequest.getPlanScheduleReportInfoDTO() != null ? testplanRunRequest.getPlanScheduleReportInfoDTO() : null, apiRunConfig); testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(), testplanRunRequest.getPlanScheduleReportInfoDTO() != null ? testplanRunRequest.getPlanScheduleReportInfoDTO() : null, apiRunConfig);
} }
@ -1881,7 +1880,7 @@ public class TestPlanService {
private void updatePlan(TestplanRunRequest testplanRunRequest, String testPlanId) { private void updatePlan(TestplanRunRequest testplanRunRequest, String testPlanId) {
String request = JSON.toJSONString(testplanRunRequest); String request = JSON.toJSONString(testplanRunRequest);
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId); TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
if(testPlanWithBLOBs.getRunModeConfig()==null||!(StringUtils.equals(request,testPlanWithBLOBs.getRunModeConfig()))){ if (testPlanWithBLOBs.getRunModeConfig() == null || !(StringUtils.equals(request, testPlanWithBLOBs.getRunModeConfig()))) {
testPlanWithBLOBs.setRunModeConfig(request); testPlanWithBLOBs.setRunModeConfig(request);
testPlanMapper.updateByPrimaryKeyWithBLOBs(testPlanWithBLOBs); testPlanMapper.updateByPrimaryKeyWithBLOBs(testPlanWithBLOBs);
} }
@ -2055,31 +2054,31 @@ public class TestPlanService {
public List<MsExecResponseDTO> runBatch(TestplanRunRequest request) { public List<MsExecResponseDTO> runBatch(TestplanRunRequest request) {
List<String> ids = request.getTestPlanIds(); List<String> ids = request.getTestPlanIds();
if (CollectionUtils.isEmpty(ids)&&!request.getIsAll()) { if (CollectionUtils.isEmpty(ids) && !request.getIsAll()) {
return new LinkedList<>(); return new LinkedList<>();
} }
LoggerUtil.info("开始查询测试计划"); LoggerUtil.info("开始查询测试计划");
List<TestPlanWithBLOBs> planList = new ArrayList<>(); List<TestPlanWithBLOBs> planList = new ArrayList<>();
if(request.getIsAll()!=null&&request.getIsAll()){ if (request.getIsAll() != null && request.getIsAll()) {
List<TestPlanDTOWithMetric> testPlanDTOWithMetrics = this.listTestPlan(request.getQueryTestPlanRequest()); List<TestPlanDTOWithMetric> testPlanDTOWithMetrics = this.listTestPlan(request.getQueryTestPlanRequest());
planList.addAll(testPlanDTOWithMetrics); planList.addAll(testPlanDTOWithMetrics);
}else{ } else {
TestPlanExample example = new TestPlanExample(); TestPlanExample example = new TestPlanExample();
example.createCriteria().andIdIn(ids); example.createCriteria().andIdIn(ids);
example.createCriteria().andProjectIdEqualTo(request.getProjectId()); example.createCriteria().andProjectIdEqualTo(request.getProjectId());
planList = testPlanMapper.selectByExampleWithBLOBs(example); planList = testPlanMapper.selectByExampleWithBLOBs(example);
} }
Map<String, TestPlanWithBLOBs> testPlanMap = planList.stream().collect(Collectors.toMap(TestPlan::getId, a -> a,(k1,k2)->k1)); Map<String, TestPlanWithBLOBs> testPlanMap = planList.stream().collect(Collectors.toMap(TestPlan::getId, a -> a, (k1, k2) -> k1));
Map<String, TestPlanReport> executeQueue = new LinkedHashMap<>(); Map<String, TestPlanReport> executeQueue = new LinkedHashMap<>();
List<MsExecResponseDTO> responseDTOS = new LinkedList<>(); List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
Map<String, TestPlanScheduleReportInfoDTO> planScheduleReportInfoDTOMap = new LinkedHashMap<>(); Map<String, TestPlanScheduleReportInfoDTO> planScheduleReportInfoDTOMap = new LinkedHashMap<>();
boolean startThread = true; boolean startThread = true;
for (String id : ids) { for (String id : ids) {
TestPlanWithBLOBs testPlan = testPlanMap.get(id); TestPlanWithBLOBs testPlan = testPlanMap.get(id);
if(StringUtils.isBlank(testPlan.getRunModeConfig())){ if (StringUtils.isBlank(testPlan.getRunModeConfig())) {
startThread = false; startThread = false;
MSException.throwException("请保存["+testPlan.getName()+"]的运行配置"); MSException.throwException("请保存[" + testPlan.getName() + "]的运行配置");
} }
//创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数 //创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数
TestPlanScheduleReportInfoDTO reportInfoDTO = this.genTestPlanReport(testPlan.getProjectId(), testPlan.getId(), request.getUserId(), request.getTriggerMode()); TestPlanScheduleReportInfoDTO reportInfoDTO = this.genTestPlanReport(testPlan.getProjectId(), testPlan.getId(), request.getUserId(), request.getTriggerMode());
@ -2089,7 +2088,7 @@ public class TestPlanService {
executeQueue.put(testPlan.getId(), reportInfoDTO.getTestPlanReport()); executeQueue.put(testPlan.getId(), reportInfoDTO.getTestPlanReport());
responseDTOS.add(new MsExecResponseDTO(testPlan.getId(), reportInfoDTO.getTestPlanReport().getId(), request.getTriggerMode())); responseDTOS.add(new MsExecResponseDTO(testPlan.getId(), reportInfoDTO.getTestPlanReport().getId(), request.getTriggerMode()));
planScheduleReportInfoDTOMap.put(testPlan.getId(),reportInfoDTO); planScheduleReportInfoDTOMap.put(testPlan.getId(), reportInfoDTO);
} }
LoggerUtil.info("开始生成测试计划队列"); LoggerUtil.info("开始生成测试计划队列");
@ -2100,14 +2099,14 @@ public class TestPlanService {
extTestPlanExecutionQueueMapper.sqlInsert(planExecutionQueues); extTestPlanExecutionQueueMapper.sqlInsert(planExecutionQueues);
} }
// 开始选择执行模式 // 开始选择执行模式
runByMode(startThread,request, testPlanMap, planScheduleReportInfoDTOMap, planExecutionQueues); runByMode(startThread, request, testPlanMap, planScheduleReportInfoDTOMap, planExecutionQueues);
return responseDTOS; return responseDTOS;
} }
private List<TestPlanExecutionQueue> getTestPlanExecutionQueues(TestplanRunRequest request, Map<String, TestPlanReport> executeQueue) { private List<TestPlanExecutionQueue> getTestPlanExecutionQueues(TestplanRunRequest request, Map<String, TestPlanReport> executeQueue) {
List<TestPlanExecutionQueue>planExecutionQueues = new ArrayList<>(); List<TestPlanExecutionQueue> planExecutionQueues = new ArrayList<>();
executeQueue.forEach((k, v)->{ executeQueue.forEach((k, v) -> {
TestPlanExecutionQueue executionQueue = new TestPlanExecutionQueue(); TestPlanExecutionQueue executionQueue = new TestPlanExecutionQueue();
executionQueue.setId(UUID.randomUUID().toString()); executionQueue.setId(UUID.randomUUID().toString());
executionQueue.setCreateTime(System.currentTimeMillis()); executionQueue.setCreateTime(System.currentTimeMillis());
@ -2125,18 +2124,18 @@ public class TestPlanService {
@Override @Override
public void run() { public void run() {
Thread.currentThread().setName("TEST_PLAN_BATCH" + System.currentTimeMillis()); Thread.currentThread().setName("TEST_PLAN_BATCH" + System.currentTimeMillis());
if(StringUtils.equalsIgnoreCase(request.getMode(),RunModeConstants.SERIAL.name())){ if (StringUtils.equalsIgnoreCase(request.getMode(), RunModeConstants.SERIAL.name())) {
TestPlanExecutionQueue planExecutionQueue = planExecutionQueues.get(0); TestPlanExecutionQueue planExecutionQueue = planExecutionQueues.get(0);
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId()); TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig()); JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig());
TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject,TestplanRunRequest.class); TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject, TestplanRunRequest.class);
runRequest.setPlanScheduleReportInfoDTO(planScheduleReportInfoDTOMap.get(planExecutionQueue.getTestPlanId())); runRequest.setPlanScheduleReportInfoDTO(planScheduleReportInfoDTOMap.get(planExecutionQueue.getTestPlanId()));
runPlan(runRequest); runPlan(runRequest);
}else { } else {
for (TestPlanExecutionQueue planExecutionQueue : planExecutionQueues) { for (TestPlanExecutionQueue planExecutionQueue : planExecutionQueues) {
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId()); TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig()); JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig());
TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject,TestplanRunRequest.class); TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject, TestplanRunRequest.class);
runRequest.setPlanScheduleReportInfoDTO(planScheduleReportInfoDTOMap.get(planExecutionQueue.getTestPlanId())); runRequest.setPlanScheduleReportInfoDTO(planScheduleReportInfoDTOMap.get(planExecutionQueue.getTestPlanId()));
runPlan(runRequest); runPlan(runRequest);
} }

View File

@ -176,8 +176,8 @@ export default {
{value: 'UPDATE', label: this.$t('commons.update')}, {value: 'UPDATE', label: this.$t('commons.update')},
{value: 'DELETE', label: this.$t('commons.delete')}, {value: 'DELETE', label: this.$t('commons.delete')},
{value: 'COMPLETE', label: this.$t('commons.run_completed')}, {value: 'COMPLETE', label: this.$t('commons.run_completed')},
// {value: 'SUCCESS_ONE_BY_ONE', label: ''}, {value: 'EXECUTE_SUCCESSFUL', label: this.$t('commons.run_success')},
// {value: 'FAIL_ONE_BY_ONE', label: ''}, {value: 'EXECUTE_FAILED', label: this.$t('commons.run_fail')},
], ],
variables: [ variables: [
{ {