fix(测试计划): 修复测试计划批量执行时出现的问题

测试计划批量执行(尤其是串行)时,由于每个测试计划执行是需要记录执行产生的报告并入库,在测试计划数量较多时会出现由于事务导致的数据一致性问题:测试计划批量执行方法还在进行,测试计划报告数据还未入库,但是先执行的测试计划已经执行结束并通过kafka发送回消息。此时由于数据并未入库,也就无法更改测试计划报告状态,导致测试计划报告状态停留在了入库时的running
This commit is contained in:
song-tianyang 2023-04-25 16:27:01 +08:00 committed by 刘瑞斌
parent f1dd651e70
commit 1091268602
4 changed files with 283 additions and 228 deletions

View File

@ -60,7 +60,7 @@ public class TestPlanTestJob extends MsScheduleJob {
// 定时任务指定调用微服务的user
HttpHeaderUtils.runAsUser(baseUserService.getUserDTO(runUserId));
testPlanService.runTestPlan(runResourceId, runProjectId, runUserId, ReportTriggerMode.SCHEDULE.name(), null, ExecutionWay.RUN.name(), config);
testPlanService.runTestPlanBySchedule(runResourceId, runProjectId, runUserId, ReportTriggerMode.SCHEDULE.name(), null, ExecutionWay.RUN.name(), config);
HttpHeaderUtils.clearUser();
}

View File

@ -0,0 +1,224 @@
package io.metersphere.plan.service;
import io.metersphere.base.domain.TestPlanWithBLOBs;
import io.metersphere.base.mapper.TestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.commons.constants.TestPlanReportStatus;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.*;
import io.metersphere.plan.dto.ExecutionWay;
import io.metersphere.plan.request.api.TestPlanRunRequest;
import io.metersphere.plan.service.remote.api.PlanApiAutomationService;
import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService;
import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService;
import io.metersphere.plan.service.remote.performance.PerfExecService;
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
import io.metersphere.plan.service.remote.ui.PlanUiAutomationService;
import io.metersphere.plan.utils.TestPlanRequestUtil;
import io.metersphere.utils.LoggerUtil;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@Transactional
public class TestPlanExecuteService {
@Resource
@Lazy
private TestPlanService testPlanService;
@Resource
private TestPlanReportService testPlanReportService;
@Resource
private PlanTestPlanApiCaseService planTestPlanApiCaseService;
@Resource
private PlanTestPlanScenarioCaseService planTestPlanScenarioCaseService;
@Resource
private PerfExecService perfExecService;
@Resource
private PlanTestPlanUiScenarioCaseService planTestPlanUiScenarioCaseService;
@Resource
private PlanApiAutomationService planApiAutomationService;
@Resource
private PlanUiAutomationService planUiAutomationService;
@Resource
private TestPlanMapper testPlanMapper;
@Resource
private ExtTestPlanMapper extTestPlanMapper;
/**
* 执行测试计划流程是会调用其它服务的执行方法并通过kafka传递信息给test-track服务来判断测试计划是否执行结束
* 执行方法采用单独的事务控制执行完了就提交让测试报告以及包括执行内容的数据及时入库
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public String runTestPlan(String testPlanId, String projectId, String userId, String triggerMode, String planReportId, String executionWay, String apiRunConfig) {
RunModeConfigDTO runModeConfig = null;
try {
runModeConfig = JSON.parseObject(apiRunConfig, RunModeConfigDTO.class);
} catch (Exception e) {
LogUtil.error(e);
}
if (runModeConfig == null) {
runModeConfig = this.buildRunModeConfigDTO();
}
//环境参数为空时依据测试计划保存的环境执行
if (((StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && StringUtils.isBlank(runModeConfig.getEnvironmentGroupId()))
|| (!StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && MapUtils.isEmpty(runModeConfig.getEnvMap()) && MapUtils.isEmpty(runModeConfig.getTestPlanDefaultEnvMap())))
&& !StringUtils.equals(executionWay, ExecutionWay.RUN.name())) {
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
if (StringUtils.isNotEmpty(testPlanWithBLOBs.getRunModeConfig())) {
try {
Map json = JSON.parseMap(testPlanWithBLOBs.getRunModeConfig());
TestPlanRequestUtil.changeStringToBoolean(json);
TestPlanRunRequest testPlanRunRequest = JSON.parseObject(JSON.toJSONString(json), TestPlanRunRequest.class);
if (testPlanRunRequest != null) {
String envType = testPlanRunRequest.getEnvironmentType();
Map<String, String> envMap = testPlanRunRequest.getEnvMap();
String environmentGroupId = testPlanRunRequest.getEnvironmentGroupId();
runModeConfig = testPlanService.getRunModeConfigDTO(testPlanRunRequest, envType, envMap, environmentGroupId, testPlanId);
runModeConfig.setTestPlanDefaultEnvMap(testPlanRunRequest.getTestPlanDefaultEnvMap());
if (!testPlanRunRequest.isRunWithinResourcePool()) {
runModeConfig.setResourcePoolId(null);
}
}
} catch (Exception e) {
LogUtil.error("获取测试计划保存的环境信息出错!", e);
}
}
}
if (planReportId == null) {
planReportId = UUID.randomUUID().toString();
}
if (testPlanService.haveExecCase(testPlanId, true)) {
testPlanService.verifyPool(projectId, runModeConfig);
}
//创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数
TestPlanScheduleReportInfoDTO reportInfoDTO = testPlanService.genTestPlanReport(planReportId, testPlanId, userId, triggerMode, runModeConfig);
LoggerUtil.info("预生成测试计划报告【" + reportInfoDTO.getTestPlanReport() != null ? reportInfoDTO.getTestPlanReport().getName() : StringUtils.EMPTY + "】计划报告ID[" + planReportId + "]");
List<TestPlanApiDTO> apiTestCases = null;
List<TestPlanScenarioDTO> scenarioCases = null;
List<TestPlanUiScenarioDTO> uiScenarios = null;
Map<String, String> loadCaseReportMap = null;
if (MapUtils.isNotEmpty(reportInfoDTO.getApiTestCaseDataMap())) {
try {
apiTestCases = planTestPlanApiCaseService.getFailureListByIds(reportInfoDTO.getApiTestCaseDataMap().keySet());
} catch (Exception e) {
LogUtil.error("测试计划执行查询接口用例失败!", e);
}
}
if (MapUtils.isNotEmpty(reportInfoDTO.getPlanScenarioIdMap())) {
try {
scenarioCases = planTestPlanScenarioCaseService.getFailureListByIds(reportInfoDTO.getPlanScenarioIdMap().keySet());
} catch (Exception e) {
LogUtil.error("测试计划执行查询场景用例失败!", e);
}
}
if (MapUtils.isNotEmpty(reportInfoDTO.getUiScenarioIdMap())) {
try {
uiScenarios = planTestPlanUiScenarioCaseService.getFailureListByIds(reportInfoDTO.getUiScenarioIdMap().keySet());
} catch (Exception e) {
LogUtil.error("测试计划执行查询UI用例失败!", e);
}
}
boolean haveApiCaseExec = false, haveScenarioCaseExec = false, haveLoadCaseExec = false, haveUICaseExec = false;
if (CollectionUtils.isNotEmpty(apiTestCases)) {
//执行接口案例任务
LoggerUtil.info("开始执行测试计划接口用例 " + planReportId);
try {
Map<String, String> apiCaseReportMap = testPlanService.executeApiTestCase(triggerMode, planReportId, userId, testPlanId, runModeConfig);
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
haveApiCaseExec = true;
for (TestPlanApiDTO dto : apiTestCases) {
dto.setReportId(apiCaseReportMap.get(dto.getId()));
}
}
} catch (Exception e) {
apiTestCases = null;
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划接口用例失败! ", e);
}
}
if (CollectionUtils.isNotEmpty(scenarioCases)) {
//执行场景执行任务
LoggerUtil.info("开始执行测试计划场景用例 " + planReportId);
try {
Map<String, String> scenarioReportMap = testPlanService.executeScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
if (MapUtils.isNotEmpty(scenarioReportMap)) {
haveScenarioCaseExec = true;
List<TestPlanScenarioDTO> removeDTO = new ArrayList<>();
for (TestPlanScenarioDTO dto : scenarioCases) {
if (scenarioReportMap.containsKey(dto.getId())) {
dto.setReportId(scenarioReportMap.get(dto.getId()));
} else {
removeDTO.add(dto);
}
}
if (CollectionUtils.isNotEmpty(removeDTO)) {
scenarioCases.removeAll(removeDTO);
}
}
} catch (Exception e) {
scenarioCases = null;
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划场景用例失败! ", e);
}
}
if (MapUtils.isNotEmpty(reportInfoDTO.getPerformanceIdMap())) {
//执行性能测试任务
LoggerUtil.info("开始执行测试计划性能用例 " + planReportId);
try {
loadCaseReportMap = perfExecService.executeLoadCase(planReportId, runModeConfig, testPlanService.transformationPerfTriggerMode(triggerMode), reportInfoDTO.getPerformanceIdMap());
if (MapUtils.isNotEmpty(loadCaseReportMap)) {
haveLoadCaseExec = true;
}
} catch (Exception e) {
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划性能用例失败! ", e);
}
}
if (CollectionUtils.isNotEmpty(uiScenarios)) {
//执行UI场景执行任务
LoggerUtil.info("开始执行测试计划 UI 场景用例 " + planReportId);
try {
Map<String, String> uiScenarioReportMap = testPlanService.executeUiScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getUiScenarioIdMap());
if (MapUtils.isNotEmpty(uiScenarioReportMap)) {
haveUICaseExec = true;
for (TestPlanUiScenarioDTO dto : uiScenarios) {
dto.setReportId(uiScenarioReportMap.get(dto.getId()));
}
}
} catch (Exception e) {
uiScenarios = null;
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划 UI 用例失败! ", e);
}
}
LoggerUtil.info("开始生成测试计划报告内容 " + planReportId);
testPlanReportService.createTestPlanReportContentReportIds(planReportId, apiTestCases, scenarioCases, uiScenarios, loadCaseReportMap);
if (!haveApiCaseExec && !haveScenarioCaseExec && !haveLoadCaseExec && !haveUICaseExec) {
//如果没有执行的自动化用例调用结束测试计划的方法 因为方法中包含着测试计划执行队列的处理逻辑
testPlanReportService.testPlanExecuteOver(planReportId, TestPlanReportStatus.COMPLETED.name());
}
return planReportId;
}
private RunModeConfigDTO buildRunModeConfigDTO() {
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
runModeConfig.setMode(RunModeConstants.SERIAL.name());
runModeConfig.setReportType("iddReport");
runModeConfig.setEnvMap(new HashMap<>());
runModeConfig.setOnSampleError(false);
return runModeConfig;
}
}

View File

@ -468,12 +468,6 @@ public class TestPlanReportService {
testPlanReportMapper.insert(testPlanReport);
if (runInfoDTO != null) {
//runInfoDTO 不为Null时是执行测试计划行为触发的要更新TestPlan状态为进行中
testPlan.setStatus(TestPlanStatus.Underway.name());
testPlanMapper.updateByPrimaryKeySelective(testPlan);
}
TestPlanScheduleReportInfoDTO returnDTO = new TestPlanScheduleReportInfoDTO();
returnDTO.setTestPlanReport(testPlanReport);
return returnDTO;

View File

@ -7,7 +7,6 @@ import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanReportMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException;
@ -43,7 +42,6 @@ import io.metersphere.plan.request.ui.UiPlanReportRequest;
import io.metersphere.plan.service.remote.api.PlanApiAutomationService;
import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService;
import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService;
import io.metersphere.plan.service.remote.performance.PerfExecService;
import io.metersphere.plan.service.remote.performance.PlanTestPlanLoadCaseService;
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
import io.metersphere.plan.service.remote.ui.PlanUiAutomationService;
@ -132,14 +130,11 @@ public class TestPlanService {
@Resource
private TestCaseTestMapper testCaseTestMapper;
@Resource
private ExtTestPlanReportMapper extTestPlanReportMapper;
@Resource
private TestPlanReportService testPlanReportService;
@Lazy
@Resource
private IssuesService issuesService;
@Resource
private PerfExecService perfExecService;
@Resource
private TestPlanPrincipalService testPlanPrincipalService;
@Resource
@ -158,6 +153,8 @@ public class TestPlanService {
private ObjectMapper objectMapper;
@Resource
private ApiPoolDebugService apiPoolDebugService;
@Resource
private TestPlanExecuteService testPlanExecuteService;
public TestPlan addTestPlan(AddTestPlanRequest testPlan) {
if (getTestPlanByName(testPlan.getName()).size() > 0) {
@ -904,171 +901,6 @@ public class TestPlanService {
return testPlanReportService.genTestPlanReportBySchedule(planReportId, planId, userId, triggerMode, runModeConfigDTO);
}
public String runTestPlan(String testPlanId, String projectId, String userId, String triggerMode, String
planReportId, String executionWay, String apiRunConfig) {
RunModeConfigDTO runModeConfig = null;
try {
runModeConfig = JSON.parseObject(apiRunConfig, RunModeConfigDTO.class);
} catch (Exception e) {
LogUtil.error(e);
}
if (runModeConfig == null) {
runModeConfig = buildRunModeConfigDTO();
}
//环境参数为空时依据测试计划保存的环境执行
if (((StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && StringUtils.isBlank(runModeConfig.getEnvironmentGroupId()))
|| (!StringUtils.equals("GROUP", runModeConfig.getEnvironmentType()) && MapUtils.isEmpty(runModeConfig.getEnvMap()) && MapUtils.isEmpty(runModeConfig.getTestPlanDefaultEnvMap())))
&& !StringUtils.equals(executionWay, ExecutionWay.RUN.name())) {
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
if (StringUtils.isNotEmpty(testPlanWithBLOBs.getRunModeConfig())) {
try {
Map json = JSON.parseMap(testPlanWithBLOBs.getRunModeConfig());
TestPlanRequestUtil.changeStringToBoolean(json);
TestPlanRunRequest testPlanRunRequest = JSON.parseObject(JSON.toJSONString(json), TestPlanRunRequest.class);
if (testPlanRunRequest != null) {
String envType = testPlanRunRequest.getEnvironmentType();
Map<String, String> envMap = testPlanRunRequest.getEnvMap();
String environmentGroupId = testPlanRunRequest.getEnvironmentGroupId();
runModeConfig = getRunModeConfigDTO(testPlanRunRequest, envType, envMap, environmentGroupId, testPlanId);
runModeConfig.setTestPlanDefaultEnvMap(testPlanRunRequest.getTestPlanDefaultEnvMap());
if (!testPlanRunRequest.isRunWithinResourcePool()) {
runModeConfig.setResourcePoolId(null);
}
}
} catch (Exception e) {
LogUtil.error("获取测试计划保存的环境信息出错!", e);
}
}
}
if (planReportId == null) {
planReportId = UUID.randomUUID().toString();
}
if (haveExecCase(testPlanId, true)) {
this.verifyPool(projectId, runModeConfig);
}
//创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数
TestPlanScheduleReportInfoDTO reportInfoDTO = this.genTestPlanReport(planReportId, testPlanId, userId, triggerMode, runModeConfig);
//定时任务执行重新设置实际开始时间
if (StringUtils.equals(triggerMode, TriggerMode.SCHEDULE.name())) {
TestPlanWithBLOBs testPlanWithBLOBs = new TestPlanWithBLOBs();
testPlanWithBLOBs.setId(testPlanId);
testPlanWithBLOBs.setActualStartTime(System.currentTimeMillis());
testPlanMapper.updateByPrimaryKeySelective(testPlanWithBLOBs);
}
//测试计划准备执行取消测试计划的实际结束时间
extTestPlanMapper.updateActualEndTimeIsNullById(testPlanId);
LoggerUtil.info("预生成测试计划报告【" + reportInfoDTO.getTestPlanReport() != null ? reportInfoDTO.getTestPlanReport().getName() : StringUtils.EMPTY + "】计划报告ID[" + planReportId + "]");
List<TestPlanApiDTO> apiTestCases = null;
List<TestPlanScenarioDTO> scenarioCases = null;
List<TestPlanUiScenarioDTO> uiScenarios = null;
Map<String, String> loadCaseReportMap = null;
if (MapUtils.isNotEmpty(reportInfoDTO.getApiTestCaseDataMap())) {
try {
apiTestCases = planTestPlanApiCaseService.getFailureListByIds(reportInfoDTO.getApiTestCaseDataMap().keySet());
} catch (Exception e) {
LogUtil.error("测试计划执行查询接口用例失败!", e);
}
}
if (MapUtils.isNotEmpty(reportInfoDTO.getPlanScenarioIdMap())) {
try {
scenarioCases = planTestPlanScenarioCaseService.getFailureListByIds(reportInfoDTO.getPlanScenarioIdMap().keySet());
} catch (Exception e) {
LogUtil.error("测试计划执行查询场景用例失败!", e);
}
}
if (MapUtils.isNotEmpty(reportInfoDTO.getUiScenarioIdMap())) {
try {
uiScenarios = planTestPlanUiScenarioCaseService.getFailureListByIds(reportInfoDTO.getUiScenarioIdMap().keySet());
} catch (Exception e) {
LogUtil.error("测试计划执行查询UI用例失败!", e);
}
}
boolean haveApiCaseExec = false, haveScenarioCaseExec = false, haveLoadCaseExec = false, haveUICaseExec = false;
if (CollectionUtils.isNotEmpty(apiTestCases)) {
//执行接口案例任务
LoggerUtil.info("开始执行测试计划接口用例 " + planReportId);
try {
Map<String, String> apiCaseReportMap = this.executeApiTestCase(triggerMode, planReportId, userId, testPlanId, runModeConfig);
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
haveApiCaseExec = true;
for (TestPlanApiDTO dto : apiTestCases) {
dto.setReportId(apiCaseReportMap.get(dto.getId()));
}
}
} catch (Exception e) {
apiTestCases = null;
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划接口用例失败! ", e);
}
}
if (CollectionUtils.isNotEmpty(scenarioCases)) {
//执行场景执行任务
LoggerUtil.info("开始执行测试计划场景用例 " + planReportId);
try {
Map<String, String> scenarioReportMap = this.executeScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
if (MapUtils.isNotEmpty(scenarioReportMap)) {
haveScenarioCaseExec = true;
List<TestPlanScenarioDTO> removeDTO = new ArrayList<>();
for (TestPlanScenarioDTO dto : scenarioCases) {
if (scenarioReportMap.containsKey(dto.getId())) {
dto.setReportId(scenarioReportMap.get(dto.getId()));
} else {
removeDTO.add(dto);
}
}
if (CollectionUtils.isNotEmpty(removeDTO)) {
scenarioCases.removeAll(removeDTO);
}
}
} catch (Exception e) {
scenarioCases = null;
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划场景用例失败! ", e);
}
}
if (MapUtils.isNotEmpty(reportInfoDTO.getPerformanceIdMap())) {
//执行性能测试任务
LoggerUtil.info("开始执行测试计划性能用例 " + planReportId);
try {
loadCaseReportMap = perfExecService.executeLoadCase(planReportId, runModeConfig, transformationPerfTriggerMode(triggerMode), reportInfoDTO.getPerformanceIdMap());
if (MapUtils.isNotEmpty(loadCaseReportMap)) {
haveLoadCaseExec = true;
}
} catch (Exception e) {
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划性能用例失败! ", e);
}
}
if (CollectionUtils.isNotEmpty(uiScenarios)) {
//执行UI场景执行任务
LoggerUtil.info("开始执行测试计划 UI 场景用例 " + planReportId);
try {
Map<String, String> uiScenarioReportMap = this.executeUiScenarioCase(planReportId, testPlanId, projectId, runModeConfig, triggerMode, userId, reportInfoDTO.getUiScenarioIdMap());
if (MapUtils.isNotEmpty(uiScenarioReportMap)) {
haveUICaseExec = true;
for (TestPlanUiScenarioDTO dto : uiScenarios) {
dto.setReportId(uiScenarioReportMap.get(dto.getId()));
}
}
} catch (Exception e) {
uiScenarios = null;
LoggerUtil.info("测试报告" + planReportId + "本次执行测试计划 UI 用例失败! ", e);
}
}
LoggerUtil.info("开始生成测试计划报告内容 " + planReportId);
testPlanReportService.createTestPlanReportContentReportIds(planReportId, apiTestCases, scenarioCases, uiScenarios, loadCaseReportMap);
if (!haveApiCaseExec && !haveScenarioCaseExec && !haveLoadCaseExec && !haveUICaseExec) {
//如果没有执行的自动化用例调用结束测试计划的方法 因为方法中包含着测试计划执行队列的处理逻辑
testPlanReportService.testPlanExecuteOver(planReportId, TestPlanReportStatus.COMPLETED.name());
}
return planReportId;
}
public void verifyPool(String projectId, RunModeConfigDTO runConfig) {
// 检查是否禁用了本地执行
apiPoolDebugService.verifyPool(projectId, runConfig);
@ -1080,7 +912,7 @@ public class TestPlanService {
* @param triggerMode
* @return
*/
private String transformationPerfTriggerMode(String triggerMode) {
public String transformationPerfTriggerMode(String triggerMode) {
if (StringUtils.equalsIgnoreCase(triggerMode, ReportTriggerMode.SCHEDULE.name())) {
return ReportTriggerMode.TEST_PLAN_SCHEDULE.name();
} else if (StringUtils.equalsIgnoreCase(triggerMode, ReportTriggerMode.API.name())) {
@ -1090,16 +922,7 @@ public class TestPlanService {
}
}
private RunModeConfigDTO buildRunModeConfigDTO() {
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
runModeConfig.setMode(RunModeConstants.SERIAL.name());
runModeConfig.setReportType("iddReport");
runModeConfig.setEnvMap(new HashMap<>());
runModeConfig.setOnSampleError(false);
return runModeConfig;
}
private Map<String, String> executeApiTestCase(String triggerMode, String planReportId, String userId, String
public Map<String, String> executeApiTestCase(String triggerMode, String planReportId, String userId, String
testPlanId, RunModeConfigDTO runModeConfig) {
BatchRunDefinitionRequest request = new BatchRunDefinitionRequest();
request.setTriggerMode(triggerMode);
@ -1111,9 +934,9 @@ public class TestPlanService {
return this.parseMsExecResponseDTOToTestIdReportMap(dtoList);
}
private Map<String, String> executeScenarioCase(String planReportId, String testPlanID, String
public Map<String, String> executeScenarioCase(String planReportId, String testPlanID, String
projectID, RunModeConfigDTO runModeConfig, String triggerMode, String
userId, Map<String, String> planScenarioIdMap) {
userId, Map<String, String> planScenarioIdMap) {
if (!planScenarioIdMap.isEmpty()) {
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
String scenarioReportID = UUID.randomUUID().toString();
@ -1146,9 +969,9 @@ public class TestPlanService {
}
}
private Map<String, String> executeUiScenarioCase(String planReportId, String testPlanID, String
public Map<String, String> executeUiScenarioCase(String planReportId, String testPlanID, String
projectID, RunModeConfigDTO runModeConfig, String triggerMode, String
userId, Map<String, String> planScenarioIdMap) {
userId, Map<String, String> planScenarioIdMap) {
if (!planScenarioIdMap.isEmpty()) {
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
String scenarioReportID = UUID.randomUUID().toString();
@ -2007,13 +1830,24 @@ public class TestPlanService {
runModeConfig.setResourcePoolId(null);
}
String apiRunConfig = JSON.toJSONString(runModeConfig);
return this.runTestPlan(testPlanId, testplanRunRequest.getProjectId(),
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(), testplanRunRequest.getReportId(), testplanRunRequest.getExecutionWay(), apiRunConfig);
//执行测试计划行为要更新TestPlan状态为进行中并重置实际结束时间
this.updateTestPlanExecuteInfo(testPlanId, TestPlanStatus.Underway.name());
String apiRunConfig = JSON.toJSONString(runModeConfig);
return testPlanExecuteService.runTestPlan(testPlanId, testplanRunRequest.getProjectId(),
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(), testplanRunRequest.getReportId(), testplanRunRequest.getExecutionWay(), apiRunConfig);
}
private RunModeConfigDTO getRunModeConfigDTO(TestPlanRunRequest testplanRunRequest, String
private void updateTestPlanExecuteInfo(String testPlanId, String status) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(testPlanId);
if (testPlan != null) {
testPlan.setStatus(status);
testPlan.setActualEndTime(null);
testPlanMapper.updateByPrimaryKey(testPlan);
}
}
public RunModeConfigDTO getRunModeConfigDTO(TestPlanRunRequest testplanRunRequest, String
envType, Map<String, String> envMap, String environmentGroupId, String testPlanId) {
RunModeConfigDTO runModeConfig = new RunModeConfigDTO();
if (!testplanRunRequest.isRunWithinResourcePool()) {
@ -2251,13 +2085,13 @@ public class TestPlanService {
TestPlanWithBLOBs testPlan = testPlanMap.get(id);
String planReportId = UUID.randomUUID().toString();
//创建测试报告
//检查资源池运行情况
RunModeConfigDTO runModeConfigDTO = JSON.parseObject(testPlan.getRunModeConfig(), RunModeConfigDTO.class);
runModeConfigDTO = ObjectUtils.isEmpty(runModeConfigDTO) ? new RunModeConfigDTO() : runModeConfigDTO;
if (haveExecCase(testPlan.getId(), true)) {
this.verifyPool(testPlan.getProjectId(), runModeConfigDTO);
}
this.genTestPlanReport(planReportId, testPlan.getId(), request.getUserId(), request.getTriggerMode(), runModeConfigDTO);
//测试计划准备执行取消测试计划的实际结束时间
extTestPlanMapper.updateActualEndTimeIsNullById(testPlan.getId());
executeQueue.put(testPlan.getId(), planReportId);
@ -2265,14 +2099,14 @@ public class TestPlanService {
LoggerUtil.info("开始生成测试计划队列");
//生成测试计划队列
List<TestPlanExecutionQueue> planExecutionQueues = getTestPlanExecutionQueues(request, executeQueue);
if (CollectionUtils.isNotEmpty(planExecutionQueues)) {
//串行存储队列并行在目前的业务需求下不需要存储
if (CollectionUtils.isNotEmpty(planExecutionQueues) && StringUtils.equalsIgnoreCase(request.getMode(), "serial")) {
testPlanExecutionQueueService.batchSave(planExecutionQueues);
}
// 开始选择执行模式
runByMode(request, testPlanMap, planExecutionQueues);
}
@ -2299,33 +2133,24 @@ public class TestPlanService {
private void runByMode(TestPlanRunRequest
request, Map<String, TestPlanWithBLOBs> testPlanMap, List<TestPlanExecutionQueue> planExecutionQueues) {
if (CollectionUtils.isNotEmpty(planExecutionQueues)) {
User user = SessionUtils.getUser();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("TEST_PLAN_BATCH" + System.currentTimeMillis());
HttpHeaderUtils.runAsUser(user);
if (StringUtils.equalsIgnoreCase(request.getMode(), RunModeConstants.SERIAL.name())) {
TestPlanExecutionQueue planExecutionQueue = planExecutionQueues.get(0);
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
Map jsonObject = JSON.parseMap(testPlan.getRunModeConfig());
TestPlanRequestUtil.changeStringToBoolean(jsonObject);
TestPlanRunRequest runRequest = JSON.parseObject(JSON.toJSONString(jsonObject), TestPlanRunRequest.class);
runRequest.setReportId(planExecutionQueue.getReportId());
runPlan(runRequest);
} else {
for (TestPlanExecutionQueue planExecutionQueue : planExecutionQueues) {
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
Map jsonObject = JSON.parseMap(testPlan.getRunModeConfig());
TestPlanRequestUtil.changeStringToBoolean(jsonObject);
TestPlanRunRequest runRequest = JSON.parseObject(JSON.toJSONString(jsonObject), TestPlanRunRequest.class);
runRequest.setReportId(planExecutionQueue.getReportId());
runPlan(runRequest);
}
}
if (StringUtils.equalsIgnoreCase(request.getMode(), RunModeConstants.SERIAL.name())) {
TestPlanExecutionQueue planExecutionQueue = planExecutionQueues.get(0);
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
Map jsonObject = JSON.parseMap(testPlan.getRunModeConfig());
TestPlanRequestUtil.changeStringToBoolean(jsonObject);
TestPlanRunRequest runRequest = JSON.parseObject(JSON.toJSONString(jsonObject), TestPlanRunRequest.class);
runRequest.setReportId(planExecutionQueue.getReportId());
runPlan(runRequest);
} else {
for (TestPlanExecutionQueue planExecutionQueue : planExecutionQueues) {
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
Map jsonObject = JSON.parseMap(testPlan.getRunModeConfig());
TestPlanRequestUtil.changeStringToBoolean(jsonObject);
TestPlanRunRequest runRequest = JSON.parseObject(JSON.toJSONString(jsonObject), TestPlanRunRequest.class);
runRequest.setReportId(planExecutionQueue.getReportId());
runPlan(runRequest);
}
});
thread.start();
}
}
}
@ -2431,4 +2256,16 @@ public class TestPlanService {
}
return testPlanReportDataStruct;
}
//这个方法是为定时任务调用的
public String runTestPlanBySchedule(String testPlanId, String projectId, String userId, String triggerMode, String planReportId, String executionWay, String apiRunConfig) {
//定时任务执行重新设置实际开始时间
if (StringUtils.equals(triggerMode, TriggerMode.SCHEDULE.name())) {
TestPlanWithBLOBs testPlanWithBLOBs = new TestPlanWithBLOBs();
testPlanWithBLOBs.setId(testPlanId);
testPlanWithBLOBs.setActualStartTime(System.currentTimeMillis());
testPlanMapper.updateByPrimaryKeySelective(testPlanWithBLOBs);
}
return testPlanExecuteService.runTestPlan(testPlanId, projectId, userId, triggerMode, planReportId, executionWay, apiRunConfig);
}
}