refactor(接口测试): 优化失败重跑功能

This commit is contained in:
fit2-zhao 2023-02-15 16:12:01 +08:00 committed by fit2-zhao
parent ea7539ba59
commit 77335c5044
14 changed files with 142 additions and 306 deletions

View File

@ -5,10 +5,6 @@ import io.metersphere.api.dto.definition.request.ElementUtil;
import io.metersphere.api.dto.definition.request.MsTestPlan;
import io.metersphere.api.dto.definition.request.MsThreadGroup;
import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.dto.definition.request.sampler.MsDubboSampler;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler;
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
import io.metersphere.api.exec.queue.DBTestQueue;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.NewDriverManager;
@ -22,17 +18,14 @@ import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.base.mapper.plan.TestPlanApiCaseMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.CommonConstants;
import io.metersphere.commons.constants.ElementConstants;
import io.metersphere.commons.constants.PropertyConstant;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.utils.*;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.ProjectJarConfig;
import io.metersphere.dto.ResultDTO;
import io.metersphere.environment.service.BaseEnvironmentService;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.ApiExecutionQueueService;
import io.metersphere.service.ApiRetryOnFailureService;
import io.metersphere.service.RemakeReportService;
import io.metersphere.utils.LoggerUtil;
@ -50,6 +43,7 @@ import java.util.*;
@Transactional(rollbackFor = Exception.class)
public class ApiCaseSerialService {
private final static String PROJECT_ID = "projectId";
public static final String NAME = "name";
@Resource
private JMeterService jMeterService;
@Resource
@ -143,33 +137,30 @@ public class ApiCaseSerialService {
MsThreadGroup group = new MsThreadGroup();
group.setLabel(caseWithBLOBs.getName());
group.setName(runRequest.getReportId());
group.setHashTree(new LinkedList<>());
// 接口用例集成报告
if (StringUtils.isNotEmpty(runRequest.getTestPlanReportId())
&& StringUtils.equals(runRequest.getReportType(), RunModeConstants.SET_REPORT.toString())) {
group.setName(runRequest.getTestPlanReportId());
}
group.setProjectId(caseWithBLOBs.getProjectId());
MsTestElement testElement;
// 数据兼容处理
JSONObject element = JSONUtil.parseObject(caseWithBLOBs.getRequest());
ElementUtil.dataFormatting(element);
String data = element.toString();
parse(element, testId, envId, caseWithBLOBs.getProjectId());
String runData = element.toString();
if (runRequest.isRetryEnable() && runRequest.getRetryNum() > 0) {
// 失败重试
String retryData = apiRetryOnFailureService.retry(data, runRequest.getRetryNum(), true);
data = StringUtils.isNotEmpty(retryData) ? retryData : data;
// 格式化数据
testElement = apiRetryOnFailureService.retryParse(data);
MsTestElement msTestElement = parse(JSON.toJSONString(testElement.getHashTree().get(0)), testId, envId, caseWithBLOBs.getProjectId());
testElement.setHashTree(new LinkedList<>() {{
this.add(msTestElement);
}});
} else {
testElement = parse(data, testId, envId, caseWithBLOBs.getProjectId());
try {
// 失败重试
String retryData = apiRetryOnFailureService.retry(runData, runRequest.getRetryNum(), true);
if (StringUtils.isNotBlank(retryData)) {
runData = retryData;
}
} catch (Exception e) {
LoggerUtil.error("失败重试脚本生成失败 ", runRequest.getReportId(), e);
}
}
group.setHashTree(new LinkedList<>());
group.getHashTree().add(testElement);
group.getHashTree().add(JSONUtil.parseObject(runData, MsTestElement.class));
testPlan.getHashTree().add(group);
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
LoggerUtil.info("用例资源:" + caseWithBLOBs.getName() + ", 生成执行脚本JMX成功", runRequest.getReportId());
@ -177,64 +168,23 @@ public class ApiCaseSerialService {
}
} catch (Exception ex) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(runRequest);
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, runRequest);
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);
remakeReportService.testEnded(runRequest, ex.getMessage());
LoggerUtil.error("用例资源:" + testId + ", 生成执行脚本失败", runRequest.getReportId(), ex);
}
return null;
}
private MsTestElement parse(String api, String planId, String envId, String projectId) {
private void parse(JSONObject element, String testId, String envId, String projectId) {
try {
JSONObject element = JSONUtil.parseObject(api);
LinkedList<MsTestElement> list = new LinkedList<>();
if (element != null && StringUtils.isNotEmpty(element.optString(ElementConstants.HASH_TREE))) {
list.addAll(JSONUtil.readValue(element.optString(ElementConstants.HASH_TREE)));
element.putOpt(NAME, testId);
if (StringUtils.isNotEmpty(envId)) {
element.putOpt(PropertyConstant.ENVIRONMENT, envId);
}
if (element.optString(PropertyConstant.TYPE).equals(ElementConstants.HTTP_SAMPLER)) {
MsHTTPSamplerProxy httpSamplerProxy = JSONUtil.parseObject(element.toString(), MsHTTPSamplerProxy.class);
httpSamplerProxy.setHashTree(list);
httpSamplerProxy.setName(planId);
if (StringUtils.isNotEmpty(envId)) {
httpSamplerProxy.setUseEnvironment(envId);
}
return httpSamplerProxy;
}
if (element.optString(PropertyConstant.TYPE).equals(ElementConstants.TCP_SAMPLER)) {
MsTCPSampler msTCPSampler = JSON.parseObject(api, MsTCPSampler.class);
if (StringUtils.isEmpty(msTCPSampler.getProjectId())) {
msTCPSampler.setProjectId(projectId);
}
if (StringUtils.isNotEmpty(envId)) {
msTCPSampler.setUseEnvironment(envId);
}
msTCPSampler.setHashTree(list);
msTCPSampler.setName(planId);
return msTCPSampler;
}
if (element.optString(PropertyConstant.TYPE).equals(ElementConstants.DUBBO_SAMPLER)) {
MsDubboSampler dubboSampler = JSON.parseObject(api, MsDubboSampler.class);
if (StringUtils.isNotEmpty(envId)) {
dubboSampler.setUseEnvironment(envId);
}
dubboSampler.setHashTree(list);
dubboSampler.setName(planId);
return dubboSampler;
}
if (element.optString(PropertyConstant.TYPE).equals(ElementConstants.JDBC_SAMPLER)) {
MsJDBCSampler jDBCSampler = JSON.parseObject(api, MsJDBCSampler.class);
if (StringUtils.isNotEmpty(envId)) {
jDBCSampler.setUseEnvironment(envId);
}
jDBCSampler.setHashTree(list);
jDBCSampler.setName(planId);
return jDBCSampler;
if (StringUtils.isBlank(element.optString(PROJECT_ID))) {
element.putOpt(PROJECT_ID, projectId);
}
} catch (Exception e) {
LogUtil.error(e);
}
return null;
}
}

View File

@ -174,8 +174,6 @@ public class JMeterService {
engine.start();
} catch (Exception e) {
remakeReportService.testEnded(request, e.getMessage());
redisTemplateService.delete(JmxFileUtil.getExecuteScriptKey(request.getReportId(), request.getTestId()));
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(request.getReportId()));
LoggerUtil.error("调用K8S执行请求[ " + request.getTestId() + " ]失败:", request.getReportId(), e);
}
} else if ((MapUtils.isNotEmpty(request.getExtendedParameters())
@ -208,9 +206,7 @@ public class JMeterService {
apiPoolDebugService.run(request, resources);
} catch (Exception e) {
LoggerUtil.error(e);
remakeReportService.remake(request);
redisTemplateService.delete(JmxFileUtil.getExecuteScriptKey(request.getReportId(), request.getTestId()));
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(request.getReportId()));
remakeReportService.testEnded(request, e.getMessage());
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 执行失败,进行数据回滚:", request.getReportId(), e);
MSException.throwException("调用资源池执行失败,请检查资源池是否配置正常");
}
@ -228,7 +224,7 @@ public class JMeterService {
}
if (config == null) {
LoggerUtil.info("未获取到资源池,请检查配置【系统设置-系统-测试资源池】", request.getReportId());
remakeReportService.remake(request);
remakeReportService.testEnded(request, "未获取到资源池,请检查配置【系统设置-系统-测试资源池】");
return;
}
request.setCorePoolSize(config.getCorePoolSize());
@ -236,12 +232,12 @@ public class JMeterService {
LoggerUtil.info("开始发送请求【 " + request.getTestId() + " 】到 " + config.getUrl() + " 节点执行", request.getReportId());
ResponseEntity<String> result = restTemplate.postForEntity(config.getUrl(), request, String.class);
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
remakeReportService.remake(request);
remakeReportService.testEnded(request, result.getBody());
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 到" + config.getUrl() + " 节点执行失败", request.getReportId());
LoggerUtil.info(result.getBody());
}
} catch (Exception e) {
remakeReportService.remake(request);
remakeReportService.testEnded(request, e.getMessage());
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 执行失败,进行数据回滚:", request.getReportId(), e);
}
}

View File

@ -400,7 +400,7 @@
<update id="updateAllStatus">
update api_definition_exec_result
set status="STOPPED"
where status in ('Rerunning', 'Running', 'PENDING')
where status in ('Rerunning', 'Running')
</update>
</mapper>

View File

@ -487,7 +487,7 @@
<update id="updateAllStatus">
update api_scenario_report
set status="STOPPED"
where status in ('Rerunning', 'Running', 'PENDING')
where status in ('Rerunning', 'Running')
</update>
</mapper>

View File

@ -32,7 +32,6 @@ import java.util.List;
import java.util.Map;
public class GenerateHashTreeUtil {
public static MsScenario parseScenarioDefinition(String scenarioDefinition) {
if (StringUtils.isNotEmpty(scenarioDefinition)) {
MsScenario scenario = JSON.parseObject(scenarioDefinition, MsScenario.class);
@ -148,9 +147,15 @@ public class GenerateHashTreeUtil {
String data = definition;
// 失败重试
if (runRequest.isRetryEnable() && runRequest.getRetryNum() > 0) {
ApiRetryOnFailureService apiRetryOnFailureService = CommonBeanFactory.getBean(ApiRetryOnFailureService.class);
String retryData = apiRetryOnFailureService.retry(data, runRequest.getRetryNum(), false);
data = StringUtils.isNotEmpty(retryData) ? retryData : data;
try {
ApiRetryOnFailureService apiRetryOnFailureService = CommonBeanFactory.getBean(ApiRetryOnFailureService.class);
String retryData = apiRetryOnFailureService.retry(data, runRequest.getRetryNum(), false);
if (StringUtils.isNotBlank(retryData)) {
data = retryData;
}
} catch (Exception e) {
LoggerUtil.error("失败重试脚本生成失败 ", runRequest.getReportId(), e);
}
}
GenerateHashTreeUtil.parse(data, scenario);
@ -169,7 +174,7 @@ public class GenerateHashTreeUtil {
LoggerUtil.info("场景资源:" + item.getName() + ", 生成执行脚本JMX成功", runRequest.getReportId());
} catch (Exception ex) {
remakeException(runRequest);
remakeException(runRequest, ex);
LoggerUtil.error("场景资源:" + item.getName() + ", 生成执行脚本失败", runRequest.getReportId(), ex);
return null;
}
@ -178,9 +183,9 @@ public class GenerateHashTreeUtil {
return jmeterHashTree;
}
public static void remakeException(JmeterRunRequestDTO runRequest) {
public static void remakeException(JmeterRunRequestDTO runRequest, Exception e) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(runRequest);
remakeReportService.testEnded(runRequest, e.getMessage());
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, runRequest);
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);

View File

@ -31,7 +31,7 @@ public class RequestParamsUtil {
public static void rollback(JmeterRunRequestDTO runRequest, Exception e) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(runRequest);
remakeReportService.testEnded(runRequest, e.getMessage());
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, runRequest);
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);

View File

@ -1,7 +1,6 @@
package io.metersphere.service;
import io.metersphere.api.dto.definition.request.controller.MsRetryLoopController;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.plugin.core.MsTestElement;
@ -45,8 +44,7 @@ public class ApiRetryOnFailureService {
public MsTestElement retryParse(String data) {
try {
MsRetryLoopController controller = JSON.parseObject(data, MsRetryLoopController.class);
return controller;
return JSONUtil.parseObject(data, MsRetryLoopController.class);
} catch (Exception e) {
LogUtil.error(e);
}
@ -78,7 +76,7 @@ public class ApiRetryOnFailureService {
loopController.setEnable(true);
loopController.setResourceId(UUID.randomUUID().toString());
JSONObject whileObj = JSONUtil.parseObject(JSON.toJSONString(loopController));
JSONObject whileObj = JSONUtil.parseObject(JSONUtil.toJSONString(loopController));
JSONArray hashTree = new JSONArray();
hashTree.put(element);

View File

@ -1,149 +1,21 @@
package io.metersphere.service;
import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil;
import io.metersphere.base.domain.ApiDefinitionExecResultWithBLOBs;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiScenarioReport;
import io.metersphere.base.domain.ApiScenarioReportWithBLOBs;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.TestPlanApiCase;
import io.metersphere.base.domain.TestPlanApiScenario;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiDefinitionMapper;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.ApiTestCaseMapper;
import io.metersphere.base.mapper.plan.TestPlanApiCaseMapper;
import io.metersphere.base.mapper.plan.TestPlanApiScenarioMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.api.jmeter.utils.JmxFileUtil;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.commons.utils.FixedCapacityUtil;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.ResultDTO;
import io.metersphere.commons.utils.FixedCapacityUtil;
import io.metersphere.utils.LoggerUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
@Service
public class RemakeReportService {
@Resource
private ApiScenarioReportMapper apiScenarioReportMapper;
@Resource
private ApiScenarioMapper apiScenarioMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private ApiDefinitionMapper apiDefinitionMapper;
@Resource
private ApiDefinitionExecResultMapper execResultMapper;
@Resource
private TestPlanApiCaseMapper testPlanApiCaseMapper;
@Resource
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
public void remake(JmeterRunRequestDTO request) {
try {
// 清理零时报告
if (StringUtils.equalsAnyIgnoreCase(request.getRunMode(), ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) {
ApiDefinitionExecResultWithBLOBs result = execResultMapper.selectByPrimaryKey(request.getReportId());
if (result != null) {
result.setStatus(ApiReportStatus.ERROR.name());
result.setEndTime(System.currentTimeMillis());
execResultMapper.updateByPrimaryKeySelective(result);
TestPlanApiCase testPlanApiCase = testPlanApiCaseMapper.selectByPrimaryKey(request.getTestId());
if (testPlanApiCase != null) {
testPlanApiCase.setStatus(ApiReportStatus.ERROR.name());
testPlanApiCase.setUpdateTime(System.currentTimeMillis());
testPlanApiCaseMapper.updateByPrimaryKeySelective(testPlanApiCase);
}
}
} else if (StringUtils.equals(request.getRunMode(), ApiRunMode.DEFINITION.name())) {
ApiDefinitionExecResultWithBLOBs result = execResultMapper.selectByPrimaryKey(request.getReportId());
if (result != null) {
result.setStatus(ApiReportStatus.ERROR.name());
result.setEndTime(System.currentTimeMillis());
execResultMapper.updateByPrimaryKeySelective(result);
ApiTestCaseWithBLOBs apiTestCase = apiTestCaseMapper.selectByPrimaryKey(request.getTestId());
if (apiTestCase != null) {
apiTestCase.setStatus(ApiReportStatus.ERROR.name());
apiTestCase.setUpdateTime(System.currentTimeMillis());
apiTestCaseMapper.updateByPrimaryKeySelective(apiTestCase);
ApiDefinitionWithBLOBs apiDefinitionWithBLOBs = apiDefinitionMapper.selectByPrimaryKey(apiTestCase.getApiDefinitionId());
if (apiDefinitionWithBLOBs.getProtocol().equals("HTTP")) {
apiDefinitionWithBLOBs.setToBeUpdated(true);
apiDefinitionWithBLOBs.setToBeUpdateTime(System.currentTimeMillis());
apiDefinitionMapper.updateByPrimaryKey(apiDefinitionWithBLOBs);
}
}
}
} else if (StringUtils.equals(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
if (report != null) {
report.setEndTime(System.currentTimeMillis());
report.setStatus(ApiReportStatus.ERROR.name());
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
if (testPlanApiScenario != null) {
testPlanApiScenario.setLastResult(ApiReportStatus.ERROR.name());
testPlanApiScenario.setPassRate("0%");
testPlanApiScenario.setReportId(report.getId());
testPlanApiScenario.setUpdateTime(report.getCreateTime());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
}
apiScenarioReportMapper.updateByPrimaryKey(report);
}
} else if (StringUtils.equalsAny(request.getRunMode(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
ApiScenarioReportWithBLOBs report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
if (report != null) {
report.setEndTime(System.currentTimeMillis());
report.setStatus(ApiReportStatus.ERROR.name());
String planScenarioId = report.getScenarioId();
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(planScenarioId);
if (testPlanApiScenario != null) {
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
report.setEndTime(System.currentTimeMillis());
testPlanApiScenario.setLastResult(ApiReportStatus.ERROR.name());
testPlanApiScenario.setPassRate("0%");
testPlanApiScenario.setReportId(report.getId());
testPlanApiScenario.setUpdateTime(report.getCreateTime());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
}
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
}
} else {
ApiScenarioReportWithBLOBs report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
if (report != null && !StringUtils.equals(request.getRunType(), RunModeConstants.SERIAL.toString())) {
report.setStatus(ApiReportStatus.ERROR.name());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
}
if (StringUtils.isNotEmpty(request.getTestId())) {
ApiScenarioWithBLOBs scenarioWithBLOBs = apiScenarioMapper.selectByPrimaryKey(request.getTestId());
if (scenarioWithBLOBs != null) {
scenarioWithBLOBs.setLastResult(ApiReportStatus.ERROR.name());
scenarioWithBLOBs.setPassRate("0%");
scenarioWithBLOBs.setReportId(report.getId());
scenarioWithBLOBs.setExecuteTimes(1);
apiScenarioMapper.updateByPrimaryKeySelective(scenarioWithBLOBs);
}
}
}
// 处理队列
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, request);
dto.setQueueId(request.getQueueId());
dto.setTestId(request.getTestId());
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);
} catch (Exception e) {
LogUtil.error(e);
}
}
private RedisTemplateService redisTemplateService;
public void testEnded(JmeterRunRequestDTO request, String errorMsg) {
try {
@ -151,7 +23,7 @@ public class RemakeReportService {
BeanUtils.copyBean(dto, request);
dto.setQueueId(request.getQueueId());
dto.setTestId(request.getTestId());
dto.setRemake(true);
LoggerUtil.info("进入异常结果处理:" + dto.getRunMode() + " 整体处理完成", dto.getReportId());
// 全局并发队列
PoolExecBlockingQueueUtil.offer(dto.getReportId());
@ -170,6 +42,9 @@ public class RemakeReportService {
}
} catch (Exception e) {
LoggerUtil.error("回退报告异常", request.getReportId(), e);
}finally {
redisTemplateService.delete(JmxFileUtil.getExecuteScriptKey(request.getReportId(), request.getTestId()));
redisTemplateService.delete(JmxFileUtil.getExecuteFileKeyInRedis(request.getReportId()));
}
}
}

View File

@ -4,16 +4,19 @@ import io.metersphere.api.dto.automation.ApiTestReportVariable;
import io.metersphere.api.exec.scenario.ApiEnvironmentRunningParamService;
import io.metersphere.api.jmeter.utils.ReportStatusUtil;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.plan.TestPlanApiScenarioMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.enums.ExecutionExecuteTypeEnum;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.vo.ResultVO;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.dto.RequestResult;
import io.metersphere.dto.ResponseResult;
import io.metersphere.dto.ResultDTO;
import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService;
@ -23,12 +26,12 @@ import io.metersphere.service.scenario.ApiScenarioExecutionInfoService;
import io.metersphere.service.scenario.ApiScenarioReportService;
import io.metersphere.service.scenario.ApiScenarioReportStructureService;
import io.metersphere.service.scenario.ApiScenarioService;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.*;
@Service
@ -54,7 +57,9 @@ public class TestResultService {
@Resource
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
@Resource
BaseShareInfoService baseShareInfoService;
private BaseShareInfoService baseShareInfoService;
@Resource
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
// 场景
private static final List<String> scenarioRunModes = new ArrayList<>() {{
@ -65,6 +70,12 @@ public class TestResultService {
this.add(ApiRunMode.JENKINS_SCENARIO_PLAN.name());
}};
private static final List<String> planRunModes = new ArrayList<>() {{
this.add(ApiRunMode.SCENARIO_PLAN.name());
this.add(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
this.add(ApiRunMode.JENKINS_SCENARIO_PLAN.name());
}};
// 接口测试 用例/接口
private static final List<String> caseRunModes = new ArrayList<>() {{
this.add(ApiRunMode.DEFINITION.name());
@ -79,6 +90,12 @@ public class TestResultService {
this.add(ApiRunMode.MANUAL_PLAN.name());
}};
private static final List<String> apiRunModes = new ArrayList<>() {{
this.add(ApiRunMode.DEFINITION.name());
this.add(ApiRunMode.API_PLAN.name());
this.add(ApiRunMode.SCHEDULE_API_PLAN.name());
}};
/**
* 执行结果存储
*
@ -194,69 +211,75 @@ public class TestResultService {
}
if (scenarioRunModes.contains(dto.getRunMode())) {
ApiScenarioReport scenarioReport = edit(dto);
if (scenarioReport != null) {
String environment = StringUtils.EMPTY;
//执行人
String userName = StringUtils.EMPTY;
//负责人
String principal = StringUtils.EMPTY;
if (scenarioReport == null) {
return;
}
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(scenarioReport.getScenarioId());
if (apiScenario != null) {
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
scenarioExecutionInfoService.insertExecutionInfo(dto.getTestId(), scenarioReport.getStatus(), scenarioReport.getTriggerMode(), scenarioReport.getProjectId() == null ? apiScenario.getProjectId() : scenarioReport.getProjectId(), ExecutionExecuteTypeEnum.TEST_PLAN.name(), apiScenario.getVersionId());
} else {
scenarioExecutionInfoService.insertExecutionInfo(scenarioReport.getScenarioId(), scenarioReport.getStatus(), scenarioReport.getTriggerMode(), scenarioReport.getProjectId() == null ? apiScenario.getProjectId() : scenarioReport.getProjectId(), ExecutionExecuteTypeEnum.BASIC.name(), apiScenario.getVersionId());
}
environment = apiScenarioReportService.getEnvironment(apiScenario);
userName = apiAutomationService.getUser(apiScenario.getUserId());
principal = apiAutomationService.getUser(apiScenario.getPrincipal());
} else {
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(scenarioReport.getScenarioId());
if (testPlanApiScenario != null) {
apiScenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId());
if (apiScenario != null) {
scenarioExecutionInfoService.insertExecutionInfo(testPlanApiScenario.getId(), scenarioReport.getStatus(), scenarioReport.getTriggerMode(), scenarioReport.getProjectId() == null ? apiScenario.getProjectId() : scenarioReport.getProjectId(), ExecutionExecuteTypeEnum.TEST_PLAN.name(), apiScenario.getVersionId());
}
String environment = StringUtils.EMPTY;
//执行人
String userName = StringUtils.EMPTY;
//负责人
String principal = StringUtils.EMPTY;
if (planRunModes.contains(dto.getRunMode())) {
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(scenarioReport.getScenarioId());
if (testPlanApiScenario != null) {
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId());
if (apiScenario != null) {
scenarioExecutionInfoService.insertScenarioInfo(apiScenario, scenarioReport, dto);
}
}
} else {
ApiScenarioWithBLOBs apiScenario = apiScenarioMapper.selectByPrimaryKey(scenarioReport.getScenarioId());
scenarioExecutionInfoService.insertScenarioInfo(apiScenario, scenarioReport, dto);
environment = apiScenarioReportService.getEnvironment(apiScenario);
userName = apiAutomationService.getUser(apiScenario.getUserId());
principal = apiAutomationService.getUser(apiScenario.getPrincipal());
}
//报告内容
ApiTestReportVariable reportTask = new ApiTestReportVariable();
reportTask.setStatus(scenarioReport.getStatus());
reportTask.setId(scenarioReport.getId());
reportTask.setTriggerMode(scenarioReport.getTriggerMode());
reportTask.setName(scenarioReport.getName());
reportTask.setExecutor(userName);
reportTask.setUserId(scenarioReport.getUserId());
reportTask.setPrincipal(principal);
reportTask.setExecutionTime(DateUtils.getTimeString(scenarioReport.getUpdateTime()));
reportTask.setEnvironment(environment);
reportTask.setProjectId(scenarioReport.getProjectId());
//报告内容
ApiTestReportVariable reportTask = new ApiTestReportVariable();
reportTask.setStatus(scenarioReport.getStatus());
reportTask.setId(scenarioReport.getId());
reportTask.setTriggerMode(scenarioReport.getTriggerMode());
reportTask.setName(scenarioReport.getName());
reportTask.setExecutor(userName);
reportTask.setUserId(scenarioReport.getUserId());
reportTask.setPrincipal(principal);
reportTask.setExecutionTime(DateUtils.getTimeString(scenarioReport.getUpdateTime()));
reportTask.setEnvironment(environment);
reportTask.setProjectId(scenarioReport.getProjectId());
if (reportTask != null) {
if (StringUtils.equals(ReportTriggerMode.API.name(), reportTask.getTriggerMode()) || StringUtils.equals(ReportTriggerMode.SCHEDULE.name(), reportTask.getTriggerMode())) {
sendTask(reportTask, dto.getTestId());
}
if (reportTask != null) {
if (StringUtils.equals(ReportTriggerMode.API.name(), reportTask.getTriggerMode())
|| StringUtils.equals(ReportTriggerMode.SCHEDULE.name(), reportTask.getTriggerMode())) {
sendTask(reportTask, dto.getTestId());
}
}
} else if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name())) {
ApiDefinitionExecResultWithBLOBs record = new ApiDefinitionExecResultWithBLOBs();
record.setId(dto.getReportId());
record.setStatus(ApiReportStatus.STOPPED.name());
} else if (apiRunModes.contains(dto.getRunMode()) && dto.isRemake()) {
// 只处理RUNNING中的执行报告
updateRunningResult(dto);
}
}
ApiDefinitionExecResultExample example = new ApiDefinitionExecResultExample();
example.createCriteria().andIdEqualTo(dto.getReportId()).andStatusEqualTo(ApiReportStatus.RUNNING.name());
apiDefinitionExecResultService.updateByExampleSelective(record, example);
private void updateRunningResult(ResultDTO dto) {
ApiDefinitionExecResultWithBLOBs result = apiDefinitionExecResultMapper.selectByPrimaryKey(dto.getReportId());
if (result != null && StringUtils.equals(ApiReportStatus.RUNNING.name(), result.getStatus())) {
result.setStatus(ApiReportStatus.PENDING.name());
RequestResult item = new RequestResult();
ResponseResult responseResult = new ResponseResult();
responseResult.setConsole(dto.getConsole());
item.setResponseResult(responseResult);
result.setContent(JSON.toJSONString(item));
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(result);
if (StringUtils.isNotEmpty(dto.getTestId())) {
ApiTestCaseWithBLOBs apiTestCase = new ApiTestCaseWithBLOBs();
apiTestCase.setLastResultId(dto.getReportId());
apiTestCase.setId(dto.getTestId());
apiTestCase.setStatus(record.getStatus());
apiTestCase.setStatus(result.getStatus());
apiTestCaseService.updateByPrimaryKeySelective(apiTestCase);
}
}
}

View File

@ -1,9 +1,9 @@
package io.metersphere.service.scenario;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.request.RelationshipEdgeRequest;
import io.metersphere.service.RelationshipEdgeService;
import io.metersphere.util.ObjectUtil;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -57,7 +57,7 @@ public class ApiAutomationRelationshipEdgeService {
List<String> referenceRelationships = new ArrayList<>();
if (scenarioWithBLOBs.getScenarioDefinition().contains("\"referenced\":\"REF\"")) {
// 深度解析对比防止是复制的关系
JSONObject element = ObjectUtil.parseObject(scenarioWithBLOBs.getScenarioDefinition());
JSONObject element = JSONUtil.parseObject(scenarioWithBLOBs.getScenarioDefinition());
// 历史数据处理
this.relationships(element.getJSONArray("hashTree"), referenceRelationships);
}

View File

@ -1,14 +1,14 @@
package io.metersphere.service.scenario;
import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioExample;
import io.metersphere.base.domain.ScenarioExecutionInfo;
import io.metersphere.base.domain.ScenarioExecutionInfoExample;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ScenarioExecutionInfoMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.enums.ExecutionExecuteTypeEnum;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.ResultDTO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
@ -16,6 +16,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.UUID;
@ -45,6 +46,15 @@ public class ApiScenarioExecutionInfoService {
}
}
@Lazy
public void insertScenarioInfo(ApiScenarioWithBLOBs apiScenario, ApiScenarioReport scenarioReport, ResultDTO dto) {
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
this.insertExecutionInfo(dto.getTestId(), scenarioReport.getStatus(), scenarioReport.getTriggerMode(), scenarioReport.getProjectId() == null ? apiScenario.getProjectId() : scenarioReport.getProjectId(), ExecutionExecuteTypeEnum.TEST_PLAN.name(), apiScenario.getVersionId());
} else {
this.insertExecutionInfo(scenarioReport.getScenarioId(), scenarioReport.getStatus(), scenarioReport.getTriggerMode(), scenarioReport.getProjectId() == null ? apiScenario.getProjectId() : scenarioReport.getProjectId(), ExecutionExecuteTypeEnum.BASIC.name(), apiScenario.getVersionId());
}
}
public void insertExecutionInfoByScenarioList(List<ApiScenario> apiScenarios, String status, String triggerMode, String projectId, String executeType) {
for (ApiScenario apiScenario : apiScenarios) {
this.insertExecutionInfo(apiScenario.getId(), status, triggerMode, projectId, executeType, apiScenario.getVersionId());

View File

@ -1,22 +0,0 @@
package io.metersphere.util;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.JSON;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import java.util.Map;
public class ObjectUtil {
public static JSONObject parseObject(String value) {
try {
if (StringUtils.isEmpty(value)) {
MSException.throwException("value is null");
}
Map<String, Object> map = JSON.parseObject(value, Map.class);
return new JSONObject(map);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -17,6 +17,7 @@ public class ResultDTO {
private String runType;
private String console;
private String runningDebugSampler;
private boolean isRemake;
// 失败重试
private boolean retryEnable;
/**

View File

@ -241,7 +241,7 @@
AND t.user_id = #{request.executor}
</if>
AND (t.integrated_report_id IS NULL OR t.integrated_report_id = 'null')
AND t.status IN ("running","starting","pending")
AND t.status ="running"
) as apiTotal ,
(SELECT
count( t.id )