fix(测试计划): 修复测试计划手动执行、jenkins执行、定时任务执行接口案例时可以配置并行、串行以及资源池

修复测试计划手动执行、jenkins执行、定时任务执行接口案例时可以配置并行、串行以及资源池
This commit is contained in:
song-tianyang 2021-11-09 17:59:27 +08:00 committed by song-tianyang
parent 907bd792e6
commit 99d6e8d171
7 changed files with 142 additions and 62 deletions

View File

@ -46,6 +46,10 @@ public class TestPlanReportExecuteCatch {
}
}
public synchronized static boolean containsReport(String reportId){
return testPlanReportMap != null && testPlanReportMap.containsKey(reportId);
}
public synchronized static void updateApiTestPlanExecuteInfo(String reportId,
Map<String, String> apiCaseExecInfo, Map<String, String> apiScenarioCaseExecInfo, Map<String, String> loadCaseExecInfo) {
if(testPlanReportMap != null && testPlanReportMap.containsKey(reportId)){

View File

@ -17,4 +17,6 @@ public class BatchRunDefinitionRequest {
private RunModeConfig config;
//测试计划报告ID 测试计划执行时使用
private String planReportId;
}

View File

@ -352,7 +352,6 @@ public class MockApiUtils {
String baseScript = parseScript(url,headerMap,requestMockParams);
try {
script = baseScript + script;
System.out.println(script);
if(StringUtils.isEmpty(scriptLanguage)){
scriptLanguage = "beanshell";
}

View File

@ -1,6 +1,5 @@
package io.metersphere.track.dto;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.TestPlanReport;
import lombok.Getter;
import lombok.Setter;
@ -17,6 +16,6 @@ import java.util.Map;
public class TestPlanScheduleReportInfoDTO {
private TestPlanReport testPlanReport;
private Map<String, String> planScenarioIdMap = new LinkedHashMap<>();
private Map<ApiTestCaseWithBLOBs, String> apiTestCaseDataMap = new LinkedHashMap<>();
private Map<String, String> apiTestCaseDataMap = new LinkedHashMap<>();
private Map<String, String> performanceIdMap = new LinkedHashMap<>();
}

View File

@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.cache.TestPlanReportExecuteCatch;
import io.metersphere.api.dto.JvmInfoDTO;
import io.metersphere.api.dto.RunModeDataDTO;
import io.metersphere.api.dto.RunRequest;
@ -430,6 +431,11 @@ public class TestPlanApiCaseService {
ExecutorService executorService = Executors.newFixedThreadPool(1, new NamedThreadFactory("TestPlanApiCaseService"));
try {
Thread.currentThread().setName("TestPlanCase串行执行线程");
//记录案例线程结果以及执行失败的案例ID
Map<String, String> executeThreadIdMap = new HashMap<>();
List<String> executeErrorList = new ArrayList<>();
for (TestPlanApiCase testPlanApiCase : executeQueue.keySet()) {
try {
if (executeQueue.get(testPlanApiCase) != null && MessageCache.terminationOrderDeque.contains(executeQueue.get(testPlanApiCase).getId())) {
@ -441,13 +447,15 @@ public class TestPlanApiCaseService {
execResult.setStatus(APITestStatus.Running.name());
reportIds.add(execResult.getId());
RunModeDataDTO modeDataDTO;
String randomUUID = UUID.randomUUID().toString();
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
modeDataDTO = new RunModeDataDTO(testPlanApiCase.getId(), UUID.randomUUID().toString());
modeDataDTO = new RunModeDataDTO(testPlanApiCase.getId(), randomUUID);
} else {
// 生成报告和HashTree
try {
HashTree hashTree = generateHashTree(testPlanApiCase.getId());
modeDataDTO = new RunModeDataDTO(hashTree, UUID.randomUUID().toString());
modeDataDTO = new RunModeDataDTO(hashTree, randomUUID);
} catch (Exception e) {
RunRequest runRequest = new RunRequest();
runRequest.setTestId(testPlanApiCase.getId());
@ -468,7 +476,9 @@ public class TestPlanApiCaseService {
break;
}
}
executeThreadIdMap.put(testPlanApiCase.getApiCaseId(),randomUUID);
} catch (Exception e) {
executeErrorList.add(testPlanApiCase.getApiCaseId());
reportIds.remove(executeQueue.get(testPlanApiCase).getId());
LogUtil.error("执行终止:" + e.getMessage());
break;
@ -484,6 +494,21 @@ public class TestPlanApiCaseService {
example.createCriteria().andIdIn(removeList);
mapper.deleteByExample(example);
}
//如果是测试计划生成报告的执行则更新执行信息执行线程信息
if(TestPlanReportExecuteCatch.containsReport(request.getPlanReportId())){
if (!executeErrorList.isEmpty()) {
Map<String,String> executeErrorMap = new HashMap<>();
for(String id : executeErrorList){
executeErrorMap.put(id,TestPlanApiExecuteStatus.FAILD.name());
}
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(request.getPlanReportId(), executeErrorMap, null, null);
}
if (!executeThreadIdMap.isEmpty()) {
TestPlanReportExecuteCatch.updateTestPlanExecuteResultInfo(request.getPlanReportId(), executeThreadIdMap,null, null);
}
}
} catch (Exception e) {
LogUtil.error(e);
} finally {
@ -502,12 +527,39 @@ public class TestPlanApiCaseService {
sqlSession.commit();
// 开始并发执行
//记录案例线程结果以及执行失败的案例ID
Map<String, String> executeThreadIdMap = new HashMap<>();
List<String> executeErrorList = new ArrayList<>();
for (String reportId : executeQueue.keySet()) {
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
jMeterService.runTest(executeQueue.get(reportId).getId(), reportId, request.getTriggerMode(), null, request.getConfig());
} else {
HashTree hashTree = generateHashTree(executeQueue.get(reportId).getId());
jMeterService.runLocal(reportId,request.getConfig(), hashTree, TriggerMode.BATCH.name(), request.getTriggerMode());
TestPlanApiCase testPlanApiCase = executeQueue.get(reportId);
try {
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
jMeterService.runTest(testPlanApiCase.getId(), reportId, request.getTriggerMode(), null, request.getConfig());
executeThreadIdMap.put(testPlanApiCase.getApiCaseId(),testPlanApiCase.getId());
} else {
HashTree hashTree = generateHashTree(testPlanApiCase.getId());
jMeterService.runLocal(reportId,request.getConfig(), hashTree, TriggerMode.BATCH.name(), request.getTriggerMode());
executeThreadIdMap.put(testPlanApiCase.getApiCaseId(),reportId);
}
}catch (Exception e){
executeErrorList.add(testPlanApiCase.getApiCaseId());
}
}
//如果是测试计划生成报告的执行则更新执行信息执行线程信息
if(TestPlanReportExecuteCatch.containsReport(request.getPlanReportId())){
if (!executeErrorList.isEmpty()) {
Map<String,String> executeErrorMap = new HashMap<>();
for(String id : executeErrorList){
executeErrorMap.put(id,TestPlanApiExecuteStatus.FAILD.name());
}
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(request.getPlanReportId(), executeErrorMap, null, null);
}
if (!executeThreadIdMap.isEmpty()) {
TestPlanReportExecuteCatch.updateTestPlanExecuteResultInfo(request.getPlanReportId(), executeThreadIdMap,null, null);
}
}
}

View File

@ -125,7 +125,7 @@ public class TestPlanReportService {
public TestPlanScheduleReportInfoDTO genTestPlanReportBySchedule(String projectID, String planId, String userId, String triggerMode) {
Map<String, String> planScenarioIdMap = new LinkedHashMap<>();
Map<String, String> apiTestCaseIdMap = new LinkedHashMap<>();
Map<ApiTestCaseWithBLOBs, String> apiTestCaseDataMap = new LinkedHashMap<>();
Map<String, String> apiTestCaseDataMap = new LinkedHashMap<>();
Map<String, String> performanceIdMap = new LinkedHashMap<>();
List<TestPlanApiScenario> testPlanApiScenarioList = extTestPlanScenarioCaseMapper.selectLegalDataByTestPlanId(planId);
@ -152,15 +152,15 @@ public class TestPlanReportService {
if (!apiTestCaseIdMap.isEmpty()) {
ApiTestCaseExample apiTestCaseExample = new ApiTestCaseExample();
apiTestCaseExample.createCriteria().andIdIn(new ArrayList<>(apiTestCaseIdMap.keySet()));
List<ApiTestCaseWithBLOBs> apiCaseList = apiTestCaseMapper.selectByExampleWithBLOBs(apiTestCaseExample);
Map<String, ApiTestCaseWithBLOBs> apiCaseDataMap = new HashMap<>();
List<ApiTestCase> apiCaseList = apiTestCaseMapper.selectByExample(apiTestCaseExample);
Map<String, ApiTestCase> apiCaseDataMap = new HashMap<>();
if (!apiCaseList.isEmpty()) {
apiCaseDataMap = apiCaseList.stream().collect(Collectors.toMap(ApiTestCaseWithBLOBs::getId, k -> k));
apiCaseDataMap = apiCaseList.stream().collect(Collectors.toMap(ApiTestCase::getId, k -> k));
for (String id : apiCaseDataMap.keySet()) {
apiCaseInfoMap.put(id, TestPlanApiExecuteStatus.PREPARE.name());
String testPlanApiCaseId = apiTestCaseIdMap.get(id);
if (StringUtils.isNotEmpty(testPlanApiCaseId)) {
apiTestCaseDataMap.put(apiCaseDataMap.get(id), testPlanApiCaseId);
apiTestCaseDataMap.put(apiCaseDataMap.get(id).getId(), testPlanApiCaseId);
}
}
}

View File

@ -13,6 +13,7 @@ import io.metersphere.api.cache.TestPlanReportExecuteCatch;
import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
@ -20,7 +21,6 @@ import io.metersphere.api.jmeter.JMeterService;
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.api.service.task.NamedThreadFactory;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
@ -144,8 +144,7 @@ public class TestPlanService {
private ExtTestPlanLoadCaseMapper extTestPlanLoadCaseMapper;
@Resource
private ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper;
@Resource
private ApiTestCaseService apiTestCaseService;
@Resource
private PerformanceTestService performanceTestService;
@Resource
@ -1075,7 +1074,7 @@ public class TestPlanService {
TestPlanReport testPlanReport = reportInfoDTO.getTestPlanReport();
Map<String, String> planScenarioIdMap = reportInfoDTO.getPlanScenarioIdMap();
Map<ApiTestCaseWithBLOBs, String> apiTestCaseDataMap = reportInfoDTO.getApiTestCaseDataMap();
Map<String, String> apiTestCaseDataMap = reportInfoDTO.getApiTestCaseDataMap();
Map<String, String> performanceIdMap = reportInfoDTO.getPerformanceIdMap();
String planReportId = testPlanReport.getId();
@ -1135,9 +1134,9 @@ public class TestPlanService {
}
for (Map.Entry<ApiTestCaseWithBLOBs, String> entry : apiTestCaseDataMap.entrySet()) {
ApiTestCaseWithBLOBs model = entry.getKey();
executeApiCaseIdMap.put(model.getId(), TestPlanApiExecuteStatus.RUNNING.name());
for (Map.Entry<String, String> entry : apiTestCaseDataMap.entrySet()) {
String id = entry.getKey();
executeApiCaseIdMap.put(id, TestPlanApiExecuteStatus.RUNNING.name());
}
for (String id : planScenarioIdMap.keySet()) {
executeScenarioCaseIdMap.put(id, TestPlanApiExecuteStatus.RUNNING.name());
@ -1145,10 +1144,29 @@ public class TestPlanService {
testPlanLog.info("ReportId[" + planReportId + "] start run. TestPlanID:[" + testPlanID + "]. Execute api :" + JSONObject.toJSONString(executeApiCaseIdMap) + "; Execute scenario:" + JSONObject.toJSONString(executeScenarioCaseIdMap) + "; Execute performance:" + JSONObject.toJSONString(executePerformanceIdMap));
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(planReportId, executeApiCaseIdMap, executeScenarioCaseIdMap, executePerformanceIdMap);
RunModeConfig runModeConfig = null;
try {
runModeConfig = JSONObject.parseObject(apiRunConfig, RunModeConfig.class);
runModeConfig.setOnSampleError(false);
} catch (Exception e) {
e.printStackTrace();
}
if (runModeConfig == null) {
runModeConfig = new RunModeConfig();
runModeConfig.setMode("serial");
runModeConfig.setReportType("iddReport");
runModeConfig.setEnvMap(new HashMap<>());
runModeConfig.setOnSampleError(false);
}else {
if(runModeConfig.getEnvMap() == null){
runModeConfig.setEnvMap(new HashMap<>());
}
}
//执行接口案例任务
this.executeApiTestCase(triggerMode, planReportId, testPlanID, apiTestCaseDataMap);
this.executeApiTestCase(triggerMode, planReportId,new ArrayList<>(apiTestCaseDataMap.values()), runModeConfig);
//执行场景执行任务
this.executeScenarioCase(planReportId, testPlanID, projectID, apiRunConfig, triggerMode, userId, planScenarioIdMap);
this.executeScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, planScenarioIdMap);
this.listenTaskExecuteStatus(planReportId);
return testPlanReport.getId();
}
@ -1169,37 +1187,56 @@ public class TestPlanService {
});
}
private void executeApiTestCase(String triggerMode, String planReportId, String testPlanId, Map<ApiTestCaseWithBLOBs, String> apiTestCaseDataMap) {
private void executeApiTestCase(String triggerMode, String planReportId, List<String> planCaseIds, RunModeConfig runModeConfig) {
executorService.submit(() -> {
Map<String, String> executeErrorMap = new HashMap<>();
Map<String, String> executeReportIdMap = new HashMap<>();
for (Map.Entry<ApiTestCaseWithBLOBs, String> entry : apiTestCaseDataMap.entrySet()) {
ApiTestCaseWithBLOBs blobs = entry.getKey();
try {
String testId = UUID.randomUUID().toString();
if (StringUtils.equals(triggerMode, ReportTriggerMode.API.name())) {
apiTestCaseService.run(blobs, testId, planReportId, testPlanId, ApiRunMode.JENKINS_API_PLAN.name());
} else if (StringUtils.equals(triggerMode, ReportTriggerMode.MANUAL.name())) {
apiTestCaseService.run(blobs, testId, planReportId, testPlanId, ApiRunMode.MANUAL_PLAN.name());
} else {
apiTestCaseService.run(blobs, testId, planReportId, testPlanId, ApiRunMode.SCHEDULE_API_PLAN.name());
}
executeReportIdMap.put(blobs.getId(),testId);
} catch (Exception e) {
executeErrorMap.put(blobs.getId(), TestPlanApiExecuteStatus.FAILD.name());
}
// Map<String, String> executeErrorMap = new HashMap<>();
// Map<String, String> executeReportIdMap = new HashMap<>();
BatchRunDefinitionRequest request = new BatchRunDefinitionRequest();
// List<String> planIdList = new ArrayList<>(1);
// planIdList.add(testPlanId);
if (StringUtils.equals(triggerMode, ReportTriggerMode.API.name())) {
request.setTriggerMode(ApiRunMode.JENKINS_API_PLAN.name());
} else if (StringUtils.equals(triggerMode, ReportTriggerMode.MANUAL.name())) {
request.setTriggerMode(ApiRunMode.MANUAL_PLAN.name());
} else {
request.setTriggerMode(ApiRunMode.SCHEDULE_API_PLAN.name());
}
if (!executeErrorMap.isEmpty()) {
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(planReportId, executeErrorMap, null, null);
}
if (!executeReportIdMap.isEmpty()) {
TestPlanReportExecuteCatch.updateTestPlanExecuteResultInfo(planReportId, executeReportIdMap,null, null);
}
request.setPlanIds(planCaseIds);
request.setPlanReportId(planReportId);
request.setConfig(runModeConfig);
testPlanApiCaseService.run(request);
// for (Map.Entry<ApiTestCaseWithBLOBs, String> entry : apiTestCaseDataMap.entrySet()) {
// ApiTestCaseWithBLOBs blobs = entry.getKey();
// try {
// String testId = UUID.randomUUID().toString();
//
//
//
//// if (StringUtils.equals(triggerMode, ReportTriggerMode.API.name())) {
//// apiTestCaseService.run(blobs, testId, planReportId, testPlanId, ApiRunMode.JENKINS_API_PLAN.name());
//// } else if (StringUtils.equals(triggerMode, ReportTriggerMode.MANUAL.name())) {
//// apiTestCaseService.run(blobs, testId, planReportId, testPlanId, ApiRunMode.MANUAL_PLAN.name());
//// } else {
//// apiTestCaseService.run(blobs, testId, planReportId, testPlanId, ApiRunMode.SCHEDULE_API_PLAN.name());
//// }
//// executeReportIdMap.put(blobs.getId(),testId);
// } catch (Exception e) {
// executeErrorMap.put(blobs.getId(), TestPlanApiExecuteStatus.FAILD.name());
// }
// }
// if (!executeErrorMap.isEmpty()) {
// TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(planReportId, executeErrorMap, null, null);
// }
// if (!executeReportIdMap.isEmpty()) {
// TestPlanReportExecuteCatch.updateTestPlanExecuteResultInfo(planReportId, executeReportIdMap,null, null);
// }
});
}
private void executeScenarioCase(String planReportId, String testPlanID, String projectID, String apiRunConfig, String triggerMode, String userId, Map<String, String> planScenarioIdMap) {
private void executeScenarioCase(String planReportId, String testPlanID, String projectID, RunModeConfig runModeConfig, String triggerMode, String userId, Map<String, String> planScenarioIdMap) {
executorService.submit(() -> {
if (!planScenarioIdMap.isEmpty()) {
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
@ -1225,19 +1262,6 @@ public class TestPlanService {
scenarioRequest.setTestPlanID(testPlanID);
scenarioRequest.setTestPlanReportId(planReportId);
RunModeConfig runModeConfig = null;
try {
runModeConfig = JSONObject.parseObject(apiRunConfig, RunModeConfig.class);
runModeConfig.setOnSampleError(false);
} catch (Exception e) {
e.printStackTrace();
}
if (runModeConfig == null) {
runModeConfig = new RunModeConfig();
runModeConfig.setMode("serial");
runModeConfig.setReportType("iddReport");
runModeConfig.setOnSampleError(false);
}
scenarioRequest.setConfig(runModeConfig);
this.scenarioRunModeConfig(scenarioRequest);