feat(测试跟踪): 测试计划中性能测试用例支持串行和并行
--story=1008149 --user=赵勇 定时任务、jenkins、页面执行测试计划的性能测试不支持串行模式运行 https://www.tapd.cn/55049933/s/1195943
This commit is contained in:
parent
7495be1c9b
commit
b459e4736c
|
@ -0,0 +1,76 @@
|
|||
package io.metersphere.api.exec.perf;
|
||||
|
||||
import io.metersphere.api.service.ApiExecutionQueueService;
|
||||
import io.metersphere.base.mapper.ext.ExtLoadTestReportMapper;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.constants.ReportTriggerMode;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.RunModeConfigDTO;
|
||||
import io.metersphere.performance.request.RunTestPlanRequest;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class PerfExecService {
|
||||
@Resource
|
||||
private ApiExecutionQueueService apiExecutionQueueService;
|
||||
@Resource
|
||||
private PerfModeExecService perfModeExecService;
|
||||
@Resource
|
||||
private ExtLoadTestReportMapper extLoadTestReportMapper;
|
||||
|
||||
public Map<String, String> run(String planReportId, RunModeConfigDTO config, String triggerMode, Map<String, String> perfMap) {
|
||||
LoggerUtil.info("开始生成测试计划性能测试队列");
|
||||
|
||||
List<RunTestPlanRequest> requests = new LinkedList<>();
|
||||
Map<String, String> responseMap = new LinkedHashMap<>();
|
||||
perfMap.forEach((k, v) -> {
|
||||
String reportId = null;
|
||||
// 执行中的性能测试资源
|
||||
List<String> reportIds = extLoadTestReportMapper.selectReportIdByTestId(v);
|
||||
if (CollectionUtils.isNotEmpty(reportIds)) {
|
||||
reportId = reportIds.get(0);
|
||||
}
|
||||
// 过滤掉执行中的性能测试资源
|
||||
if (StringUtils.isEmpty(reportId)) {
|
||||
RunTestPlanRequest request = new RunTestPlanRequest();
|
||||
reportId = UUID.randomUUID().toString();
|
||||
request.setId(v);
|
||||
request.setTestPlanLoadId(k);
|
||||
request.setReportId(reportId);
|
||||
request.setTriggerMode(triggerMode);
|
||||
if (StringUtils.isNotBlank(config.getResourcePoolId())) {
|
||||
request.setTestResourcePoolId(config.getResourcePoolId());
|
||||
}
|
||||
if (StringUtils.isEmpty(triggerMode)) {
|
||||
request.setTriggerMode(ReportTriggerMode.TEST_PLAN_SCHEDULE.name());
|
||||
}
|
||||
requests.add(request);
|
||||
}
|
||||
responseMap.put(k, reportId);
|
||||
});
|
||||
|
||||
//将性能测试加入到队列中
|
||||
if (MapUtils.isNotEmpty(responseMap)) {
|
||||
apiExecutionQueueService.add(responseMap, config.getResourcePoolId(), ApiRunMode.TEST_PLAN_PERFORMANCE_TEST.name(),
|
||||
planReportId, config.getReportType(), config.getMode(), config);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(requests) && StringUtils.isNotEmpty(planReportId)) {
|
||||
apiExecutionQueueService.testPlanReportTestEnded(planReportId);
|
||||
return responseMap;
|
||||
}
|
||||
LoggerUtil.info("开始执行性能测试任务");
|
||||
if (config != null && config.getMode().equals(RunModeConstants.SERIAL.toString())) {
|
||||
perfModeExecService.serial(requests.get(0));
|
||||
} else {
|
||||
perfModeExecService.parallel(requests);
|
||||
}
|
||||
return responseMap;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package io.metersphere.api.exec.perf;
|
||||
|
||||
import io.metersphere.base.domain.TestPlanLoadCaseWithBLOBs;
|
||||
import io.metersphere.base.mapper.TestPlanLoadCaseMapper;
|
||||
import io.metersphere.commons.constants.TestPlanLoadCaseStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.performance.request.RunTestPlanRequest;
|
||||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PerfModeExecService {
|
||||
@Resource
|
||||
private PerformanceTestService performanceTestService;
|
||||
@Resource
|
||||
private TestPlanLoadCaseMapper testPlanLoadCaseMapper;
|
||||
|
||||
public void serial(RunTestPlanRequest request) {
|
||||
TestPlanLoadCaseWithBLOBs loadCase = testPlanLoadCaseMapper.selectByPrimaryKey(request.getTestPlanLoadId());
|
||||
if (loadCase != null) {
|
||||
loadCase.setLoadReportId(request.getReportId());
|
||||
loadCase.setStatus(TestPlanLoadCaseStatus.run.name());
|
||||
request.setId(loadCase.getLoadCaseId());
|
||||
try {
|
||||
performanceTestService.run(request);
|
||||
} catch (Exception e) {
|
||||
loadCase.setStatus(TestPlanLoadCaseStatus.error.name());
|
||||
MSException.throwException(e);
|
||||
}
|
||||
//更新关联处的报告
|
||||
testPlanLoadCaseMapper.updateByPrimaryKeySelective(loadCase);
|
||||
}
|
||||
}
|
||||
|
||||
public void parallel(List<RunTestPlanRequest> requests) {
|
||||
for (RunTestPlanRequest request : requests) {
|
||||
this.serial(request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package io.metersphere.api.exec.perf;
|
||||
|
||||
import io.metersphere.api.exec.queue.DBTestQueue;
|
||||
import io.metersphere.api.service.ApiExecutionQueueService;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiExecutionQueueDetailMapper;
|
||||
import io.metersphere.base.mapper.ApiExecutionQueueMapper;
|
||||
import io.metersphere.base.mapper.TestPlanLoadCaseMapper;
|
||||
import io.metersphere.commons.constants.TestPlanLoadCaseStatus;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.performance.request.RunTestPlanRequest;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class PerfQueueService {
|
||||
@Resource
|
||||
private ApiExecutionQueueDetailMapper executionQueueDetailMapper;
|
||||
@Resource
|
||||
private ApiExecutionQueueService apiExecutionQueueService;
|
||||
@Resource
|
||||
private PerfModeExecService perfModeExecService;
|
||||
@Resource
|
||||
protected ApiExecutionQueueMapper queueMapper;
|
||||
@Resource
|
||||
private TestPlanLoadCaseMapper testPlanLoadCaseMapper;
|
||||
|
||||
/**
|
||||
* 性能测试监听检查
|
||||
*
|
||||
* @param loadTestReport
|
||||
*/
|
||||
public void queueNext(LoadTestReport loadTestReport) {
|
||||
LoggerUtil.info("进入结果处理监听", loadTestReport.getId());
|
||||
|
||||
ApiExecutionQueueDetailExample detailExample = new ApiExecutionQueueDetailExample();
|
||||
detailExample.createCriteria().andReportIdEqualTo(loadTestReport.getId());
|
||||
List<ApiExecutionQueueDetail> details = executionQueueDetailMapper.selectByExample(detailExample);
|
||||
executionQueueDetailMapper.deleteByExample(detailExample);
|
||||
if (CollectionUtils.isEmpty(details)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> ids = details.stream().map(ApiExecutionQueueDetail::getQueueId).collect(Collectors.toList());
|
||||
ApiExecutionQueueExample queueExample = new ApiExecutionQueueExample();
|
||||
queueExample.createCriteria().andIdIn(ids);
|
||||
List<ApiExecutionQueue> queues = queueMapper.selectByExample(queueExample);
|
||||
|
||||
List<String> testPlanReportIds = queues.stream().map(ApiExecutionQueue::getReportId).collect(Collectors.toList());
|
||||
for (String testPlanReportId : testPlanReportIds) {
|
||||
LoggerUtil.info("处理测试计划报告状态", loadTestReport.getId());
|
||||
apiExecutionQueueService.testPlanReportTestEnded(testPlanReportId);
|
||||
}
|
||||
|
||||
for (ApiExecutionQueueDetail detail : details) {
|
||||
// 更新测试计划关联数据状态
|
||||
TestPlanLoadCaseWithBLOBs loadCase = new TestPlanLoadCaseWithBLOBs();
|
||||
loadCase.setId(loadTestReport.getTestId());
|
||||
loadCase.setStatus(TestPlanLoadCaseStatus.success.name());
|
||||
testPlanLoadCaseMapper.updateByPrimaryKeySelective(loadCase);
|
||||
|
||||
// 检查队列是否已空
|
||||
ApiExecutionQueueDetailExample queueDetailExample = new ApiExecutionQueueDetailExample();
|
||||
queueDetailExample.createCriteria().andQueueIdEqualTo(detail.getQueueId());
|
||||
long count = executionQueueDetailMapper.countByExample(queueDetailExample);
|
||||
// 最后一个执行节点,删除执行链
|
||||
if (count == 0) {
|
||||
queueMapper.deleteByPrimaryKey(detail.getQueueId());
|
||||
continue;
|
||||
}
|
||||
// 获取串行下一个执行节点
|
||||
DBTestQueue executionQueue = apiExecutionQueueService.handleQueue(detail.getQueueId(), detail.getTestId());
|
||||
if (executionQueue != null && executionQueue.getQueue() != null
|
||||
&& StringUtils.isNotEmpty(executionQueue.getQueue().getTestId()) &&
|
||||
StringUtils.equals(executionQueue.getRunMode(), RunModeConstants.SERIAL.toString())) {
|
||||
|
||||
LoggerUtil.info("获取下一个执行资源:" + executionQueue.getQueue().getTestId(), loadTestReport.getId());
|
||||
RunTestPlanRequest request = new RunTestPlanRequest();
|
||||
request.setTestPlanLoadId(executionQueue.getQueue().getTestId());
|
||||
request.setReportId(executionQueue.getQueue().getReportId());
|
||||
try {
|
||||
perfModeExecService.serial(request);
|
||||
} catch (Exception e) {
|
||||
if (BooleanUtils.isTrue(executionQueue.getFailure()) && StringUtils.isNotEmpty(executionQueue.getCompletedReportId())) {
|
||||
LoggerUtil.info("失败停止处理:" + request.getId(), request.getReportId());
|
||||
continue;
|
||||
}
|
||||
LoggerUtil.error("执行异常", executionQueue.getQueue().getTestId(), e);
|
||||
executionQueueDetailMapper.deleteByExample(detailExample);
|
||||
// 异常执行下一个
|
||||
DBTestQueue next = apiExecutionQueueService.handleQueue(executionQueue.getId(), executionQueue.getQueue().getTestId());
|
||||
if (next != null) {
|
||||
LoadTestReport report = new LoadTestReport();
|
||||
report.setId(next.getReportId());
|
||||
this.queueNext(report);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ import io.metersphere.utils.LoggerUtil;
|
|||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
@ -67,88 +66,99 @@ public class ApiExecutionQueueService {
|
|||
protected ExtApiExecutionQueueMapper extApiExecutionQueueMapper;
|
||||
@Resource
|
||||
private ApiScenarioReportResultMapper apiScenarioReportResultMapper;
|
||||
@Lazy
|
||||
@Resource
|
||||
private TestPlanReportService testPlanReportService;
|
||||
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public DBTestQueue add(Object runObj, String poolId, String type, String reportId, String reportType, String runMode, RunModeConfigDTO config) {
|
||||
LoggerUtil.info("开始生成执行链", reportId);
|
||||
|
||||
LoggerUtil.info("报告【" + reportId + "】开始生成执行链");
|
||||
if (config.getEnvMap() == null) {
|
||||
config.setEnvMap(new LinkedHashMap<>());
|
||||
}
|
||||
ApiExecutionQueue executionQueue = getApiExecutionQueue(poolId, reportId, reportType, runMode, config);
|
||||
queueMapper.insert(executionQueue);
|
||||
DBTestQueue resQueue = new DBTestQueue();
|
||||
BeanUtils.copyBean(resQueue, executionQueue);
|
||||
|
||||
Map<String, String> detailMap = new HashMap<>();
|
||||
List<ApiExecutionQueueDetail> queueDetails = new LinkedList<>();
|
||||
// 初始化API/用例队列
|
||||
if (StringUtils.equalsAnyIgnoreCase(type, ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
|
||||
final int[] sort = {0};
|
||||
Map<String, ApiDefinitionExecResult> runMap = (Map<String, ApiDefinitionExecResult>) runObj;
|
||||
if (config.getEnvMap() == null) {
|
||||
config.setEnvMap(new LinkedHashMap<>());
|
||||
}
|
||||
String envStr = JSON.toJSONString(config.getEnvMap());
|
||||
runMap.forEach((k, v) -> {
|
||||
ApiExecutionQueueDetail queue = detail(v.getId(), k, config.getMode(), sort[0], executionQueue.getId(), envStr);
|
||||
if (sort[0] == 0) {
|
||||
resQueue.setQueue(queue);
|
||||
}
|
||||
sort[0]++;
|
||||
queue.setRetryEnable(config.isRetryEnable());
|
||||
queue.setRetryNumber(config.getRetryNum());
|
||||
queueDetails.add(queue);
|
||||
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]++;
|
||||
queue.setRetryEnable(config.isRetryEnable());
|
||||
queue.setRetryNumber(config.getRetryNum());
|
||||
queueDetails.add(queue);
|
||||
detailMap.put(k, queue.getId());
|
||||
});
|
||||
} else {
|
||||
initApi(runMap, resQueue, config, detailMap, queueDetails);
|
||||
}
|
||||
// 初始化性能测试执行链
|
||||
else if (StringUtils.equalsIgnoreCase(type, ApiRunMode.TEST_PLAN_PERFORMANCE_TEST.name())) {
|
||||
Map<String, String> requests = (Map<String, String>) runObj;
|
||||
initPerf(requests, resQueue, config, detailMap, queueDetails);
|
||||
}
|
||||
// 初始化场景/UI执行链
|
||||
else {
|
||||
Map<String, RunModeDataDTO> runMap = (Map<String, RunModeDataDTO>) runObj;
|
||||
final int[] sort = {0};
|
||||
runMap.forEach((k, v) -> {
|
||||
String envMap = JSON.toJSONString(v.getPlanEnvMap());
|
||||
if (StringUtils.startsWith(type, "UI_")) {
|
||||
UiExecutionQueueParam param = new UiExecutionQueueParam();
|
||||
BeanUtils.copyBean(param, config);
|
||||
envMap = JSONObject.toJSONString(param);
|
||||
}
|
||||
ApiExecutionQueueDetail queue = detail(k, v.getTestId(), config.getMode(), sort[0], executionQueue.getId(), envMap);
|
||||
queue.setSort(sort[0]);
|
||||
if (sort[0] == 0) {
|
||||
resQueue.setQueue(queue);
|
||||
}
|
||||
sort[0]++;
|
||||
queue.setRetryEnable(config.isRetryEnable());
|
||||
queue.setRetryNumber(config.getRetryNum());
|
||||
queueDetails.add(queue);
|
||||
detailMap.put(k, queue.getId());
|
||||
});
|
||||
initScenario(runMap, resQueue, config, type, detailMap, queueDetails);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(queueDetails)) {
|
||||
extApiExecutionQueueMapper.sqlInsert(queueDetails);
|
||||
}
|
||||
resQueue.setDetailMap(detailMap);
|
||||
|
||||
LoggerUtil.info("生成执行链结束", reportId);
|
||||
LoggerUtil.info("报告【" + reportId + "】生成执行链结束");
|
||||
return resQueue;
|
||||
}
|
||||
|
||||
private void initScenario(Map<String, RunModeDataDTO> runMap, DBTestQueue resQueue,
|
||||
RunModeConfigDTO config, String type, Map<String, String> detailMap, List<ApiExecutionQueueDetail> queueDetails) {
|
||||
final int[] sort = {0};
|
||||
runMap.forEach((k, v) -> {
|
||||
String envMap = JSON.toJSONString(v.getPlanEnvMap());
|
||||
if (StringUtils.startsWith(type, "UI_")) {
|
||||
UiExecutionQueueParam param = new UiExecutionQueueParam();
|
||||
BeanUtils.copyBean(param, config);
|
||||
envMap = JSONObject.toJSONString(param);
|
||||
}
|
||||
ApiExecutionQueueDetail queue = detail(k, v.getTestId(), config.getMode(), sort[0], resQueue.getId(), envMap);
|
||||
queue.setSort(sort[0]);
|
||||
if (sort[0] == 0) {
|
||||
resQueue.setQueue(queue);
|
||||
}
|
||||
sort[0]++;
|
||||
queue.setRetryEnable(config.isRetryEnable());
|
||||
queue.setRetryNumber(config.getRetryNum());
|
||||
queueDetails.add(queue);
|
||||
detailMap.put(k, queue.getId());
|
||||
});
|
||||
}
|
||||
|
||||
private void initApi(Map<String, ApiDefinitionExecResult> runMap,
|
||||
DBTestQueue resQueue, RunModeConfigDTO config, Map<String, String> detailMap, List<ApiExecutionQueueDetail> queueDetails) {
|
||||
int sort = 0;
|
||||
String envStr = JSON.toJSONString(config.getEnvMap());
|
||||
for (String k : runMap.keySet()) {
|
||||
ApiExecutionQueueDetail queue = detail(runMap.get(k).getId(), k, config.getMode(), sort++, resQueue.getId(), envStr);
|
||||
if (sort == 0) {
|
||||
resQueue.setQueue(queue);
|
||||
}
|
||||
queue.setRetryEnable(config.isRetryEnable());
|
||||
queue.setRetryNumber(config.getRetryNum());
|
||||
queueDetails.add(queue);
|
||||
detailMap.put(k, queue.getId());
|
||||
}
|
||||
resQueue.setDetailMap(detailMap);
|
||||
}
|
||||
|
||||
private void initPerf(Map<String, String> requests,
|
||||
DBTestQueue resQueue, RunModeConfigDTO config, Map<String, String> detailMap, List<ApiExecutionQueueDetail> queueDetails) {
|
||||
String envStr = JSON.toJSONString(config.getEnvMap());
|
||||
int i = 0;
|
||||
for (String testId : requests.keySet()) {
|
||||
ApiExecutionQueueDetail queue = detail(requests.get(testId), testId, config.getMode(), i++, resQueue.getId(), envStr);
|
||||
if (i == 0) {
|
||||
resQueue.setQueue(queue);
|
||||
}
|
||||
queue.setRetryEnable(config.isRetryEnable());
|
||||
queue.setRetryNumber(config.getRetryNum());
|
||||
queueDetails.add(queue);
|
||||
detailMap.put(testId, queue.getId());
|
||||
}
|
||||
}
|
||||
|
||||
protected ApiExecutionQueue getApiExecutionQueue(String poolId, String reportId, String reportType, String runMode, RunModeConfigDTO config) {
|
||||
ApiExecutionQueue executionQueue = new ApiExecutionQueue();
|
||||
executionQueue.setId(UUID.randomUUID().toString());
|
||||
|
@ -175,7 +185,7 @@ public class ApiExecutionQueueService {
|
|||
}
|
||||
|
||||
private boolean failure(DBTestQueue executionQueue, ResultDTO dto) {
|
||||
LoggerUtil.info("进入失败停止处理:" + executionQueue.getId(), dto.getReportId());
|
||||
LoggerUtil.info("进入失败停止处理:" + executionQueue.getId());
|
||||
boolean isError = false;
|
||||
if (StringUtils.contains(dto.getRunMode(), ApiRunMode.SCENARIO.name())) {
|
||||
if (StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) {
|
||||
|
@ -250,15 +260,15 @@ public class ApiExecutionQueueService {
|
|||
if (CollectionUtils.isNotEmpty(queues)) {
|
||||
queue.setQueue(queues.get(0));
|
||||
} else {
|
||||
LoggerUtil.info("execution complete,clear queue:【" + id + "】", queue.getReportId());
|
||||
LoggerUtil.info("execution complete,clear queue:【" + id + "】");
|
||||
queueMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
} else {
|
||||
LoggerUtil.info("execution complete,clear queue:【" + id + "】", queue.getReportId());
|
||||
LoggerUtil.info("execution complete,clear queue:【" + id + "】");
|
||||
queueMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
} else {
|
||||
LoggerUtil.info("The queue was accidentally deleted:【" + id + "】", queue.getReportId());
|
||||
LoggerUtil.info("The queue was accidentally deleted:【" + id + "】");
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
@ -289,7 +299,7 @@ public class ApiExecutionQueueService {
|
|||
}
|
||||
|
||||
public void queueNext(ResultDTO dto) {
|
||||
LoggerUtil.info("开始处理队列:" + dto.getQueueId(), dto.getReportId());
|
||||
LoggerUtil.info("开始处理队列:" + dto.getReportId() + "QID:" + dto.getQueueId());
|
||||
if (StringUtils.equals(dto.getRunType(), RunModeConstants.PARALLEL.toString())) {
|
||||
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
|
||||
example.createCriteria().andQueueIdEqualTo(dto.getQueueId()).andTestIdEqualTo(dto.getTestId());
|
||||
|
@ -320,7 +330,7 @@ public class ApiExecutionQueueService {
|
|||
return;
|
||||
}
|
||||
}
|
||||
LoggerUtil.info("开始处理执行队列:" + executionQueue.getId() + " 当前资源是:" + dto.getTestId(), dto.getReportId());
|
||||
LoggerUtil.info("开始处理执行队列:" + executionQueue.getId() + " 当前资源是:" + dto.getTestId() + "报告ID:" + dto.getReportId());
|
||||
if (executionQueue.getQueue() != null && StringUtils.isNotEmpty(executionQueue.getQueue().getTestId())) {
|
||||
if (StringUtils.equals(dto.getRunType(), RunModeConstants.SERIAL.toString())) {
|
||||
LoggerUtil.info("当前执行队列是:" + JSON.toJSONString(executionQueue.getQueue()));
|
||||
|
@ -344,14 +354,14 @@ public class ApiExecutionQueueService {
|
|||
apiScenarioReportService.margeReport(reportId, dto.getRunMode(), dto.getConsole());
|
||||
}
|
||||
queueMapper.deleteByPrimaryKey(dto.getQueueId());
|
||||
LoggerUtil.info("Queue execution ends:" + dto.getQueueId(), dto.getReportId());
|
||||
LoggerUtil.info("Queue execution ends:" + dto.getQueueId());
|
||||
}
|
||||
|
||||
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
|
||||
example.createCriteria().andQueueIdEqualTo(dto.getQueueId()).andTestIdEqualTo(dto.getTestId());
|
||||
executionQueueDetailMapper.deleteByExample(example);
|
||||
}
|
||||
LoggerUtil.info("处理队列结束:" + dto.getQueueId(), dto.getReportId());
|
||||
LoggerUtil.info("处理队列结束:" + dto.getReportId() + "QID:" + dto.getQueueId());
|
||||
}
|
||||
|
||||
public void defendQueue() {
|
||||
|
@ -404,7 +414,7 @@ public class ApiExecutionQueueService {
|
|||
// 删除串行资源锁
|
||||
redisTemplate.delete(RunModeConstants.SERIAL.name() + "_" + dto.getReportId());
|
||||
|
||||
LoggerUtil.info("超时处理报告处理,进入下一个执行", report.getId());
|
||||
LoggerUtil.info("超时处理报告:【" + report.getId() + "】进入下一个执行");
|
||||
dto.setTestPlanReportId(queue.getReportId());
|
||||
dto.setReportId(queue.getReportId());
|
||||
dto.setRunMode(queue.getRunMode());
|
||||
|
@ -507,20 +517,4 @@ public class ApiExecutionQueueService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 性能测试监听检查
|
||||
*
|
||||
* @param loadTestReport
|
||||
*/
|
||||
public void checkExecutionQueueByLoadTest(LoadTestReport loadTestReport) {
|
||||
ApiExecutionQueueDetailExample detailExample = new ApiExecutionQueueDetailExample();
|
||||
detailExample.createCriteria().andReportIdEqualTo(loadTestReport.getId());
|
||||
executionQueueDetailMapper.deleteByExample(detailExample);
|
||||
List<String> testPlanReportIdList = testPlanReportService.getTestPlanReportIdsByLoadTestReportId(loadTestReport.getId());
|
||||
for (String testPlanReportId : testPlanReportIdList) {
|
||||
this.testPlanReportTestEnded(testPlanReportId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,10 @@ public interface ExtLoadTestReportMapper {
|
|||
|
||||
List<PlanReportCaseDTO> selectForPlanReport(@Param("ids") List<String> reportIds);
|
||||
|
||||
int updateReportVumStatus(String reportId,String reportKey ,String nextStatus, String preStatus);
|
||||
int updateReportVumStatus(String reportId, String reportKey, String nextStatus, String preStatus);
|
||||
|
||||
List<FileMetadata> getFileMetadataById(@Param("reportId") String reportId);
|
||||
|
||||
List<String> selectReportIdByTestId(@Param("testId") String testId);
|
||||
|
||||
}
|
||||
|
|
|
@ -201,4 +201,8 @@
|
|||
WHERE report_id = #{reportId}
|
||||
ORDER BY sort
|
||||
</select>
|
||||
|
||||
<select id="selectReportIdByTestId" resultType="string">
|
||||
SELECT id FROM load_test_report WHERE test_id = #{testId} AND `status` !='Completed'
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.metersphere.performance.notice;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.service.ApiExecutionQueueService;
|
||||
import io.metersphere.api.exec.perf.PerfQueueService;
|
||||
import io.metersphere.base.domain.LoadTestReport;
|
||||
import io.metersphere.commons.consumer.LoadTestFinishEvent;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
|
@ -13,12 +13,12 @@ import javax.annotation.Resource;
|
|||
@Component
|
||||
public class PerformanceQueueEvent implements LoadTestFinishEvent {
|
||||
@Resource
|
||||
ApiExecutionQueueService apiExecutionQueueService;
|
||||
private PerfQueueService perfQueueService;
|
||||
|
||||
public void sendNotice(LoadTestReport loadTestReport) {
|
||||
//删除性能测试在执行队列中的数据 (在测试计划执行中会将性能测试执行添加到执行队列,用于判断整个测试计划到执行进度)
|
||||
try {
|
||||
apiExecutionQueueService.checkExecutionQueueByLoadTest(loadTestReport);
|
||||
perfQueueService.queueNext(loadTestReport);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("PerformanceQueueEvent error. id:" + loadTestReport.getId());
|
||||
}
|
||||
|
|
|
@ -20,4 +20,8 @@ public class RunTestPlanRequest extends TestPlanRequest {
|
|||
* 资源池ID
|
||||
*/
|
||||
private String ownTestPoolId;
|
||||
/**
|
||||
* 测试计划中生成的报告ID
|
||||
*/
|
||||
private String reportId;
|
||||
}
|
||||
|
|
|
@ -445,7 +445,7 @@ public class PerformanceTestService {
|
|||
|
||||
|
||||
LoadTestReportWithBLOBs testReport = new LoadTestReportWithBLOBs();
|
||||
testReport.setId(UUID.randomUUID().toString());
|
||||
testReport.setId(StringUtils.isNotEmpty(request.getReportId()) ? request.getReportId() : UUID.randomUUID().toString());
|
||||
testReport.setCreateTime(System.currentTimeMillis());
|
||||
testReport.setUpdateTime(System.currentTimeMillis());
|
||||
testReport.setTestId(loadTest.getId());
|
||||
|
|
|
@ -3,7 +3,7 @@ package io.metersphere.track.service;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.exec.utils.NamedThreadFactory;
|
||||
import io.metersphere.api.exec.perf.PerfExecService;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.LoadTestMapper;
|
||||
import io.metersphere.base.mapper.LoadTestReportMapper;
|
||||
|
@ -13,11 +13,10 @@ import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtLoadTestReportMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanLoadCaseMapper;
|
||||
import io.metersphere.commons.constants.PerformanceTestStatus;
|
||||
import io.metersphere.commons.constants.ReportTriggerMode;
|
||||
import io.metersphere.commons.constants.TestPlanLoadCaseStatus;
|
||||
import io.metersphere.commons.constants.TestPlanStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.controller.request.ResetOrderRequest;
|
||||
import io.metersphere.dto.LoadTestDTO;
|
||||
|
@ -30,8 +29,6 @@ import io.metersphere.track.request.testplan.LoadCaseReportBatchRequest;
|
|||
import io.metersphere.track.request.testplan.LoadCaseReportRequest;
|
||||
import io.metersphere.track.request.testplan.LoadCaseRequest;
|
||||
import io.metersphere.track.request.testplan.RunBatchTestPlanRequest;
|
||||
import io.metersphere.track.service.utils.ParallelExecTask;
|
||||
import io.metersphere.track.service.utils.SerialExecTask;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
|
@ -44,9 +41,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -73,6 +67,8 @@ public class TestPlanLoadCaseService {
|
|||
private TestPlanService testPlanService;
|
||||
@Resource
|
||||
private ExtLoadTestMapper extLoadTestMapper;
|
||||
@Resource
|
||||
private PerfExecService perfExecService;
|
||||
|
||||
public Pager<List<LoadTestDTO>> relevanceList(LoadCaseRequest request, int goPage, int pageSize) {
|
||||
List<OrderRequest> orders = ServiceUtils.getDefaultSortOrder(request.getOrders());
|
||||
|
@ -83,7 +79,7 @@ public class TestPlanLoadCaseService {
|
|||
}
|
||||
List<String> ids = extTestPlanLoadCaseMapper.selectIdsNotInPlan(request);
|
||||
if (CollectionUtils.isEmpty(ids)) {
|
||||
return PageUtils.setPageInfo(PageHelper.startPage(goPage, pageSize, true), new ArrayList <>());
|
||||
return PageUtils.setPageInfo(PageHelper.startPage(goPage, pageSize, true), new ArrayList<>());
|
||||
}
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
QueryTestPlanRequest newRequest = new QueryTestPlanRequest();
|
||||
|
@ -172,38 +168,9 @@ public class TestPlanLoadCaseService {
|
|||
}
|
||||
|
||||
public void runBatch(RunBatchTestPlanRequest request) {
|
||||
try {
|
||||
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
|
||||
serialRun(request);
|
||||
} else {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(request.getRequests().size(), new NamedThreadFactory("TestPlanLoadCaseService"));
|
||||
request.getRequests().forEach(item -> {
|
||||
executorService.submit(new ParallelExecTask(performanceTestService, testPlanLoadCaseMapper, item));
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (StringUtils.isNotEmpty(e.getMessage())) {
|
||||
MSException.throwException("测试正在运行, 请等待!");
|
||||
} else {
|
||||
MSException.throwException("请求参数错误,请刷新后执行!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void serialRun(RunBatchTestPlanRequest request) throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(request.getRequests().size(), new NamedThreadFactory("TestPlanLoadCaseService-serial"));
|
||||
for (RunTestPlanRequest runTestPlanRequest : request.getRequests()) {
|
||||
Future<LoadTestReportWithBLOBs> future = executorService.submit(new SerialExecTask(performanceTestService, testPlanLoadCaseMapper, loadTestReportMapper, runTestPlanRequest));
|
||||
LoadTestReportWithBLOBs report = future.get();
|
||||
// 如果开启失败结束执行,则判断返回结果状态
|
||||
if (request.getConfig().isOnSampleError()) {
|
||||
TestPlanLoadCaseExample example = new TestPlanLoadCaseExample();
|
||||
example.createCriteria().andLoadReportIdEqualTo(report.getId());
|
||||
List<TestPlanLoadCase> cases = testPlanLoadCaseMapper.selectByExample(example);
|
||||
if (CollectionUtils.isEmpty(cases) || !cases.get(0).getStatus().equals(TestPlanLoadCaseStatus.success.name())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (request != null && CollectionUtils.isNotEmpty(request.getRequests())) {
|
||||
Map<String, String> reqMap = request.getRequests().stream().collect(Collectors.toMap(RunTestPlanRequest::getTestPlanLoadId, a -> a.getId(), (k1, k2) -> k1));
|
||||
perfExecService.run(null, request.getConfig(), ReportTriggerMode.BATCH.name(), reqMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,12 +396,9 @@ public class TestPlanLoadCaseService {
|
|||
}
|
||||
|
||||
public List<TestPlanLoadCaseDTO> buildCases(List<TestPlanLoadCaseDTO> cases) {
|
||||
// Map<String, Project> projectMap = ServiceUtils.getProjectMap(
|
||||
// failureCases.stream().map(TestPlanCaseDTO::getProjectId).collect(Collectors.toList()));
|
||||
Map<String, String> userNameMap = ServiceUtils.getUserNameMap(
|
||||
cases.stream().map(TestPlanLoadCaseDTO::getCreateUser).collect(Collectors.toList()));
|
||||
cases.forEach(item -> {
|
||||
// item.setProjectName(projectMap.get(item.getProjectId()).getName());
|
||||
item.setUserName(userNameMap.get(item.getCreateUser()));
|
||||
});
|
||||
return cases;
|
||||
|
|
|
@ -12,7 +12,11 @@ import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
|||
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.ParamsDTO;
|
||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||
import io.metersphere.api.service.*;
|
||||
import io.metersphere.api.exec.perf.PerfExecService;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
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.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.*;
|
||||
|
@ -30,7 +34,6 @@ import io.metersphere.performance.base.*;
|
|||
import io.metersphere.performance.dto.LoadTestExportJmx;
|
||||
import io.metersphere.performance.dto.MetricData;
|
||||
import io.metersphere.performance.dto.Monitor;
|
||||
import io.metersphere.performance.request.RunTestPlanRequest;
|
||||
import io.metersphere.performance.service.MetricQueryService;
|
||||
import io.metersphere.performance.service.PerformanceReportService;
|
||||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
|
@ -58,8 +61,6 @@ import org.quartz.CronExpression;
|
|||
import org.quartz.CronScheduleBuilder;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.TriggerBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
|
@ -80,8 +81,6 @@ import java.util.stream.Stream;
|
|||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class TestPlanService {
|
||||
Logger testPlanLog = LoggerFactory.getLogger("testPlanExecuteLog");
|
||||
|
||||
@Resource
|
||||
ExtScheduleMapper extScheduleMapper;
|
||||
@Resource
|
||||
|
@ -132,8 +131,6 @@ public class TestPlanService {
|
|||
@Resource
|
||||
private ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper;
|
||||
@Resource
|
||||
private ApiExecutionQueueService apiExecutionQueueService;
|
||||
@Resource
|
||||
private PerformanceTestService performanceTestService;
|
||||
@Resource
|
||||
private TestPlanLoadCaseMapper testPlanLoadCaseMapper;
|
||||
|
@ -157,7 +154,7 @@ public class TestPlanService {
|
|||
@Resource
|
||||
private ApiScenarioReportService apiScenarioReportService;
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
private PerfExecService perfExecService;
|
||||
@Resource
|
||||
private PerformanceReportService performanceReportService;
|
||||
@Resource
|
||||
|
@ -184,6 +181,8 @@ public class TestPlanService {
|
|||
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
|
||||
@Resource
|
||||
private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
|
||||
public synchronized TestPlan addTestPlan(AddTestPlanRequest testPlan) {
|
||||
if (getTestPlanByName(testPlan.getName()).size() > 0) {
|
||||
|
@ -1002,7 +1001,7 @@ public class TestPlanService {
|
|||
if (reportInfoDTO.getPerformanceIdMap() != null) {
|
||||
//执行性能测试任务
|
||||
LoggerUtil.info("开始执行测试计划性能用例 " + planReportId);
|
||||
loadCaseReportMap = this.executeLoadCaseTask(planReportId, runModeConfig, triggerMode, reportInfoDTO.getPerformanceIdMap());
|
||||
loadCaseReportMap = perfExecService.run(planReportId, runModeConfig, triggerMode, reportInfoDTO.getPerformanceIdMap());
|
||||
}
|
||||
if (apiCaseReportMap != null && scenarioReportMap != null && loadCaseReportMap != null) {
|
||||
LoggerUtil.info("开始生成测试计划报告内容 " + planReportId);
|
||||
|
@ -1067,54 +1066,6 @@ public class TestPlanService {
|
|||
return returnMap;
|
||||
}
|
||||
|
||||
private Map<String, String> executeLoadCaseTask(String planReportId, RunModeConfigDTO runModeConfig, String triggerMode, Map<String, String> performanceIdMap) {
|
||||
Map<String, String> loadCaseReportMap = new HashMap<>();
|
||||
for (Map.Entry<String, String> entry : performanceIdMap.entrySet()) {
|
||||
String id = entry.getKey();
|
||||
String caseID = entry.getValue();
|
||||
RunTestPlanRequest performanceRequest = new RunTestPlanRequest();
|
||||
performanceRequest.setId(caseID);
|
||||
performanceRequest.setTestPlanLoadId(id);
|
||||
if (StringUtils.isNotBlank(runModeConfig.getResourcePoolId())) {
|
||||
performanceRequest.setTestResourcePoolId(runModeConfig.getResourcePoolId());
|
||||
}
|
||||
if (StringUtils.equals(ReportTriggerMode.API.name(), triggerMode)) {
|
||||
performanceRequest.setTriggerMode(ReportTriggerMode.TEST_PLAN_API.name());
|
||||
} else {
|
||||
performanceRequest.setTriggerMode(ReportTriggerMode.TEST_PLAN_SCHEDULE.name());
|
||||
}
|
||||
String reportId = null;
|
||||
try {
|
||||
reportId = performanceTestService.run(performanceRequest);
|
||||
if (reportId != null) {
|
||||
loadCaseReportMap.put(id, reportId);
|
||||
//更新关联处的报告
|
||||
TestPlanLoadCaseWithBLOBs loadCase = new TestPlanLoadCaseDTO();
|
||||
loadCase.setId(id);
|
||||
loadCase.setLoadReportId(reportId);
|
||||
loadCase.setStatus(TestPlanLoadCaseStatus.run.name());
|
||||
testPlanLoadCaseService.update(loadCase);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TestPlanLoadCaseWithBLOBs testPlanLoadCase = new TestPlanLoadCaseWithBLOBs();
|
||||
testPlanLoadCase.setId(id);
|
||||
testPlanLoadCase.setLoadReportId(reportId);
|
||||
testPlanLoadCase.setStatus(TestPlanLoadCaseStatus.error.name());
|
||||
testPlanLoadCaseService.update(testPlanLoadCase);
|
||||
LogUtil.error(e);
|
||||
}
|
||||
|
||||
}
|
||||
if (MapUtils.isNotEmpty(loadCaseReportMap)) {
|
||||
//将性能测试加入到队列中
|
||||
apiExecutionQueueService.add(loadCaseReportMap, null, ApiRunMode.TEST_PLAN_PERFORMANCE_TEST.name(),
|
||||
planReportId, null, null, new RunModeConfigDTO());
|
||||
}
|
||||
|
||||
|
||||
return loadCaseReportMap;
|
||||
}
|
||||
|
||||
public String getLogDetails(String id) {
|
||||
TestPlan plan = testPlanMapper.selectByPrimaryKey(id);
|
||||
if (plan != null) {
|
||||
|
|
|
@ -370,11 +370,13 @@ export default {
|
|||
});
|
||||
},
|
||||
refreshStatus() {
|
||||
this.refreshScheduler = setInterval(() => {
|
||||
// 如果有状态不是最终状态则定时查询
|
||||
let arr = this.tableData.filter(data => data.status !== 'Completed' && data.status !== 'Error' && data.status !== 'Saved');
|
||||
arr.length > 0 ? this.initTable() : clearInterval(this.refreshScheduler);
|
||||
}, 8000);
|
||||
// 暂时保留,试运行后再看是否还需要
|
||||
// this.refreshScheduler = setInterval(() => {
|
||||
// // 如果有状态不是最终状态则定时查询
|
||||
// let arr = this.tableData.filter(data => data.status !== 'Completed' && data.status !== 'Error' && data.status !== 'Saved');
|
||||
// arr.length > 0 ? this.initTable() : clearInterval(this.refreshScheduler);
|
||||
// }, 8000);
|
||||
this.initTable();
|
||||
},
|
||||
handleDeleteBatch() {
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + "?", '', {
|
||||
|
|
Loading…
Reference in New Issue