fix(接口测试): 修复分布式执行相关缺陷

This commit is contained in:
fit2-zhao 2021-12-21 19:53:21 +08:00 committed by fit2-zhao
parent 78e23135df
commit eb80bb6f1e
20 changed files with 191 additions and 105 deletions

View File

@ -7,7 +7,6 @@ import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.automation.parse.ScenarioImport; import io.metersphere.api.dto.automation.parse.ScenarioImport;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.exec.queue.ExecThreadPoolExecutor; import io.metersphere.api.exec.queue.ExecThreadPoolExecutor;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.api.service.ApiAutomationService; import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.base.domain.ApiScenario; import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiScenarioWithBLOBs;
@ -330,7 +329,6 @@ public class ApiAutomationController {
@GetMapping(value = "/stop/{reportId}") @GetMapping(value = "/stop/{reportId}")
public void stop(@PathVariable String reportId) { public void stop(@PathVariable String reportId) {
if (StringUtils.isNotEmpty(reportId)) { if (StringUtils.isNotEmpty(reportId)) {
MessageCache.caseExecResourceLock.remove(reportId);
execThreadPoolExecutor.removeQueue(reportId); execThreadPoolExecutor.removeQueue(reportId);
new LocalRunner().stop(reportId); new LocalRunner().stop(reportId);
} }

View File

@ -47,8 +47,8 @@ public class ApiJmeterFileController {
} }
@GetMapping("download") @GetMapping("download")
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("reportId") String reportId, @RequestParam("runMode") String runMode) { public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("testId") String testId, @RequestParam("reportId") String reportId, @RequestParam("runMode") String runMode, @RequestParam("reportType") String reportType) {
byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId); byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId, reportType);
return ResponseEntity.ok() return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream")) .contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + reportId + "_" + testId + ".zip\"") .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + reportId + "_" + testId + ".zip\"")

View File

@ -24,6 +24,7 @@ import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils; import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.plugin.core.MsParameter; import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.EnvironmentGroupProjectService; import io.metersphere.service.EnvironmentGroupProjectService;
@ -270,6 +271,24 @@ public class ElementUtil {
} }
}; };
public final static List<String> requests = new ArrayList<String>() {{
this.add("HTTPSamplerProxy");
this.add("DubboSampler");
this.add("JDBCSampler");
this.add("TCPSampler");
this.add("JSR223Processor");
this.add("JSR223PreProcessor");
this.add("JSR223PostProcessor");
this.add("JDBCPreProcessor");
this.add("JDBCPostProcessor");
this.add("JmeterElement");
this.add("TestPlan");
this.add("ThreadGroup");
this.add("DNSCacheManager");
this.add("DebugSampler");
this.add("AuthManager");
}};
private static void formatSampler(JSONObject element) { private static void formatSampler(JSONObject element) {
if (element == null || StringUtils.isEmpty(element.getString("type"))) { if (element == null || StringUtils.isEmpty(element.getString("type"))) {
return; return;
@ -340,6 +359,41 @@ public class ElementUtil {
} }
} }
public static void dataFormatting(JSONArray hashTree, String id, String reportType) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
formatSampler(element);
if (element != null && element.get("clazzName") == null && clazzMap.containsKey(element.getString("type"))) {
element.fluentPut("clazzName", clazzMap.get(element.getString("type")));
}
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (element != null && requests.contains(element.getString("type")) && !element.getString("resourceId").contains(id)) {
element.fluentPut("resourceId", id + "=" + element.getString("resourceId"));
}
}
if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, id, reportType);
}
}
}
public static void dataFormatting(JSONObject element, String id, String reportType) {
if (element != null && element.get("clazzName") == null && clazzMap.containsKey(element.getString("type"))) {
element.fluentPut("clazzName", clazzMap.get(element.getString("type")));
}
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (element != null && requests.contains(element.getString("type")) && !element.getString("resourceId").contains(id)) {
element.fluentPut("resourceId", id + "=" + element.getString("resourceId"));
}
}
formatSampler(element);
if (element != null && element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, id, reportType);
}
}
public static void dataSetDomain(JSONArray hashTree, MsParameter msParameter) { public static void dataSetDomain(JSONArray hashTree, MsParameter msParameter) {
try { try {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();

View File

@ -18,7 +18,6 @@ import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil; import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.service.TcpApiParamService; import io.metersphere.api.service.TcpApiParamService;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
@ -120,7 +119,6 @@ public class ApiExecuteService {
} }
List<MsExecResponseDTO> responseDTOS = new LinkedList<>(); List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
for (RunCaseRequest runCaseRequest : executeQueue) { for (RunCaseRequest runCaseRequest : executeQueue) {
MessageCache.caseExecResourceLock.put(runCaseRequest.getReportId(), runCaseRequest.getReport());
responseDTOS.add(exec(runCaseRequest)); responseDTOS.add(exec(runCaseRequest));
} }
return responseDTOS; return responseDTOS;
@ -153,13 +151,14 @@ public class ApiExecuteService {
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testCaseWithBLOBs.getId(), StringUtils.isEmpty(request.getReportId()) ? request.getId() : request.getReportId(), request.getRunMode(), jmeterHashTree); JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(testCaseWithBLOBs.getId(), StringUtils.isEmpty(request.getReportId()) ? request.getId() : request.getReportId(), request.getRunMode(), jmeterHashTree);
jMeterService.run(runRequest); jMeterService.run(runRequest);
} catch (Exception ex) { } catch (Exception ex) {
ApiDefinitionExecResult result = MessageCache.caseExecResourceLock.get(request.getReportId()); ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(request.getReportId());
result.setStatus("error"); if (result != null) {
apiDefinitionExecResultMapper.updateByPrimaryKey(result); result.setStatus("error");
ApiTestCaseWithBLOBs caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getCaseId()); apiDefinitionExecResultMapper.updateByPrimaryKey(result);
caseWithBLOBs.setStatus("error"); ApiTestCaseWithBLOBs caseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getCaseId());
apiTestCaseMapper.updateByPrimaryKey(caseWithBLOBs); caseWithBLOBs.setStatus("error");
MessageCache.caseExecResourceLock.remove(request.getReportId()); apiTestCaseMapper.updateByPrimaryKey(caseWithBLOBs);
}
LogUtil.error(ex.getMessage(), ex); LogUtil.error(ex.getMessage(), ex);
} }
} }

View File

@ -7,7 +7,6 @@ import io.metersphere.api.exec.scenario.ApiScenarioSerialService;
import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil; import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil;
import io.metersphere.api.exec.utils.GenerateHashTreeUtil; import io.metersphere.api.exec.utils.GenerateHashTreeUtil;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.api.service.ApiExecutionQueueService; import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.base.domain.ApiDefinitionExecResult; import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.base.domain.ApiExecutionQueue; import io.metersphere.base.domain.ApiExecutionQueue;
@ -102,7 +101,6 @@ public class TestPlanApiExecuteService {
ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.addResult(request, testPlanApiCase, APITestStatus.Running.name(), batchMapper); ApiDefinitionExecResult report = ApiDefinitionExecResultUtil.addResult(request, testPlanApiCase, APITestStatus.Running.name(), batchMapper);
executeQueue.put(report.getId(), testPlanApiCase); executeQueue.put(report.getId(), testPlanApiCase);
executeThreadIdMap.put(testPlanApiCase.getId(), report.getId()); executeThreadIdMap.put(testPlanApiCase.getId(), report.getId());
MessageCache.caseExecResourceLock.put(report.getId(), report);
responseDTOS.add(new MsExecResponseDTO(testPlanApiCase.getId(), report.getId(), request.getTriggerMode())); responseDTOS.add(new MsExecResponseDTO(testPlanApiCase.getId(), report.getId(), request.getTriggerMode()));
}); });
sqlSession.flushStatements(); sqlSession.flushStatements();

View File

@ -225,7 +225,7 @@ public class ApiScenarioEnvService {
} }
String definition = apiScenarioWithBLOBs.getScenarioDefinition(); String definition = apiScenarioWithBLOBs.getScenarioDefinition();
MsScenario scenario = JSONObject.parseObject(definition, MsScenario.class); MsScenario scenario = JSONObject.parseObject(definition, MsScenario.class);
GenerateHashTreeUtil.parse(definition, scenario); GenerateHashTreeUtil.parse(definition, scenario, apiScenarioWithBLOBs.getId(), null);
if (StringUtils.equals(environmentType, EnvironmentType.JSON.toString())) { if (StringUtils.equals(environmentType, EnvironmentType.JSON.toString())) {
scenario.setEnvironmentMap(JSON.parseObject(environmentJson, Map.class)); scenario.setEnvironmentMap(JSON.parseObject(environmentJson, Map.class));
} else if (StringUtils.equals(environmentType, EnvironmentType.GROUP.toString())) { } else if (StringUtils.equals(environmentType, EnvironmentType.GROUP.toString())) {
@ -428,4 +428,18 @@ public class ApiScenarioEnvService {
config.setConfig(envConfig); config.setConfig(envConfig);
} }
} }
public Map<String, String> planEnvMap(String testPlanScenarioId) {
Map<String, String> planEnvMap = new HashMap<>();
TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(testPlanScenarioId);
String envJson = planApiScenario.getEnvironment();
String envType = planApiScenario.getEnvironmentType();
String envGroupId = planApiScenario.getEnvironmentGroupId();
if (StringUtils.equals(envType, EnvironmentType.JSON.toString()) && StringUtils.isNotBlank(envJson)) {
planEnvMap = JSON.parseObject(envJson, Map.class);
} else if (StringUtils.equals(envType, EnvironmentType.GROUP.toString()) && StringUtils.isNotBlank(envGroupId)) {
planEnvMap = environmentGroupProjectService.getEnvMap(envGroupId);
}
return planEnvMap;
}
} }

View File

@ -150,7 +150,7 @@ public class ApiScenarioExecuteService {
responseDTOS.add(new MsExecResponseDTO(JSON.toJSONString(scenarioIds), serialReportId, request.getRunMode())); responseDTOS.add(new MsExecResponseDTO(JSON.toJSONString(scenarioIds), serialReportId, request.getRunMode()));
// 增加并行集合报告 // 增加并行集合报告
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.PARALLEL.toString())) { if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.PARALLEL.toString())) {
apiScenarioReportStructureService.save(apiScenarios, serialReportId); apiScenarioReportStructureService.save(apiScenarios, serialReportId, request.getConfig() != null ? request.getConfig().getReportType() : null);
} }
} }
// 开始执行 // 开始执行
@ -160,7 +160,7 @@ public class ApiScenarioExecuteService {
DBTestQueue executionQueue = apiExecutionQueueService.add(executeQueue, request.getConfig().getResourcePoolId(), ApiRunMode.SCENARIO.name(), serialReportId, reportType, request.getRunMode()); DBTestQueue executionQueue = apiExecutionQueueService.add(executeQueue, request.getConfig().getResourcePoolId(), ApiRunMode.SCENARIO.name(), serialReportId, reportType, request.getRunMode());
if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
if (StringUtils.isNotEmpty(serialReportId)) { if (StringUtils.isNotEmpty(serialReportId)) {
apiScenarioReportStructureService.save(apiScenarios, serialReportId); apiScenarioReportStructureService.save(apiScenarios, serialReportId, request.getConfig() != null ? request.getConfig().getReportType() : null);
} }
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class); ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
@ -267,7 +267,7 @@ public class ApiScenarioExecuteService {
// 生成并行报告和HashTree // 生成并行报告和HashTree
RunModeDataDTO runModeDataDTO = new RunModeDataDTO(report, testPlanScenarioId); RunModeDataDTO runModeDataDTO = new RunModeDataDTO(report, testPlanScenarioId);
if (request.getConfig() != null && !request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { if (request.getConfig() != null && !request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
runModeDataDTO.setHashTree(GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap)); runModeDataDTO.setHashTree(GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap, request.getConfig().getReportType()));
} }
executeQueue.put(report.getId(), runModeDataDTO); executeQueue.put(report.getId(), runModeDataDTO);
} catch (Exception ex) { } catch (Exception ex) {
@ -284,7 +284,7 @@ public class ApiScenarioExecuteService {
// 生成文档结构 // 生成文档结构
if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) { if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) {
apiScenarioReportStructureService.save(scenario, report.getId()); apiScenarioReportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null);
} }
// 重置报告ID // 重置报告ID
reportId = UUID.randomUUID().toString(); reportId = UUID.randomUUID().toString();
@ -317,7 +317,7 @@ public class ApiScenarioExecuteService {
try { try {
RunModeDataDTO runModeDataDTO = new RunModeDataDTO(report, item.getId()); RunModeDataDTO runModeDataDTO = new RunModeDataDTO(report, item.getId());
if (request.getConfig() != null && !request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { if (request.getConfig() != null && !request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) {
HashTree hashTree = GenerateHashTreeUtil.generateHashTree(item, StringUtils.isNotEmpty(serialReportId) ? serialReportId + "-" + i : reportId, new HashMap<>()); HashTree hashTree = GenerateHashTreeUtil.generateHashTree(item, StringUtils.isNotEmpty(serialReportId) ? serialReportId + "-" + i : reportId, new HashMap<>(), request.getConfig().getReportType());
runModeDataDTO.setHashTree(hashTree); runModeDataDTO.setHashTree(hashTree);
} }
executeQueue.put(report.getId(), runModeDataDTO); executeQueue.put(report.getId(), runModeDataDTO);
@ -332,7 +332,7 @@ public class ApiScenarioExecuteService {
} }
// 生成报告结构 // 生成报告结构
if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) { if (request.getConfig() == null || !StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) {
apiScenarioReportStructureService.save(item, report.getId()); apiScenarioReportStructureService.save(item, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null);
} }
// 重置报告ID // 重置报告ID
reportId = UUID.randomUUID().toString(); reportId = UUID.randomUUID().toString();
@ -370,7 +370,7 @@ public class ApiScenarioExecuteService {
apiScenarioReportMapper.insert(report); apiScenarioReportMapper.insert(report);
if (request.isSaved()) { if (request.isSaved()) {
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(request.getScenarioId()); ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(request.getScenarioId());
apiScenarioReportStructureService.save(scenario, report.getId()); apiScenarioReportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null);
} }
uploadBodyFiles(request.getBodyFileRequestIds(), bodyFiles); uploadBodyFiles(request.getBodyFileRequestIds(), bodyFiles);
FileUtils.createBodyFiles(request.getScenarioFileIds(), scenarioFiles); FileUtils.createBodyFiles(request.getScenarioFileIds(), scenarioFiles);

View File

@ -15,17 +15,21 @@ import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler;
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
import io.metersphere.api.exec.utils.GenerateHashTreeUtil; import io.metersphere.api.exec.utils.GenerateHashTreeUtil;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.service.ApiExecutionQueueService;
import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.service.TestResultService;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.HashTreeUtil; import io.metersphere.commons.utils.HashTreeUtil;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants; import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.JmeterRunRequestDTO; import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.ResultDTO;
import io.metersphere.plugin.core.MsTestElement; import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.utils.LoggerUtil; import io.metersphere.utils.LoggerUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -51,6 +55,10 @@ public class ApiScenarioSerialService {
private TestPlanApiCaseMapper testPlanApiCaseMapper; private TestPlanApiCaseMapper testPlanApiCaseMapper;
@Resource @Resource
private ApiTestCaseMapper apiTestCaseMapper; private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
@Resource
private ApiScenarioEnvService apiScenarioEnvService;
public void serial(ApiExecutionQueue executionQueue, ApiExecutionQueueDetail queue) { public void serial(ApiExecutionQueue executionQueue, ApiExecutionQueueDetail queue) {
LoggerUtil.debug("Scenario run-执行脚本装载-进入串行准备"); LoggerUtil.debug("Scenario run-执行脚本装载-进入串行准备");
@ -73,12 +81,22 @@ public class ApiScenarioSerialService {
HashTree hashTree = null; HashTree hashTree = null;
if (StringUtils.isEmpty(executionQueue.getPoolId())) { if (StringUtils.isEmpty(executionQueue.getPoolId())) {
if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(queue.getTestId()); ApiScenarioWithBLOBs scenario = null;
Map<String, String> planEnvMap = new LinkedHashMap<>(); Map<String, String> planEnvMap = new LinkedHashMap<>();
if (StringUtils.isNotEmpty(queue.getEvnMap())) { if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name())) {
scenario = apiScenarioMapper.selectByPrimaryKey(queue.getTestId());
} else {
TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(queue.getTestId());
if (planApiScenario != null) {
planEnvMap = apiScenarioEnvService.planEnvMap(queue.getTestId());
queue.setEvnMap(JSON.toJSONString(planEnvMap));
scenario = apiScenarioMapper.selectByPrimaryKey(planApiScenario.getApiScenarioId());
}
}
if ((planEnvMap == null || planEnvMap.isEmpty()) && StringUtils.isNotEmpty(queue.getEvnMap())) {
planEnvMap = JSON.parseObject(queue.getEvnMap(), Map.class); planEnvMap = JSON.parseObject(queue.getEvnMap(), Map.class);
} }
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, queue.getReportId(), planEnvMap); hashTree = GenerateHashTreeUtil.generateHashTree(scenario, queue.getReportId(), planEnvMap, executionQueue.getReportType());
} else { } else {
hashTree = generateHashTree(queue.getTestId()); hashTree = generateHashTree(queue.getTestId());
} }
@ -86,6 +104,9 @@ public class ApiScenarioSerialService {
this.initEnv(hashTree); this.initEnv(hashTree);
} }
String reportId = StringUtils.isNotEmpty(executionQueue.getReportId()) ? executionQueue.getReportId() : queue.getReportId(); String reportId = StringUtils.isNotEmpty(executionQueue.getReportId()) ? executionQueue.getReportId() : queue.getReportId();
if (!StringUtils.equals(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name())) {
reportId = queue.getReportId();
}
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(queue.getTestId(), reportId, executionQueue.getRunMode(), hashTree); JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(queue.getTestId(), reportId, executionQueue.getRunMode(), hashTree);
runRequest.setReportType(executionQueue.getReportType()); runRequest.setReportType(executionQueue.getReportType());
runRequest.setPool(GenerateHashTreeUtil.isResourcePool(executionQueue.getPoolId())); runRequest.setPool(GenerateHashTreeUtil.isResourcePool(executionQueue.getPoolId()));
@ -96,11 +117,14 @@ public class ApiScenarioSerialService {
// 开始执行 // 开始执行
jMeterService.run(runRequest); jMeterService.run(runRequest);
} catch (Exception e) { } catch (Exception e) {
LogUtil.error("执行终止:" + e.getMessage()); LoggerUtil.error("执行终止:" + e.getMessage());
ResultDTO dto = new ResultDTO();
BeanUtils.copyBean(dto, queue);
dto.setRunType(RunModeConstants.SERIAL.toString());
dto.setReportType(executionQueue.getReportType());
dto.setRunMode(executionQueue.getRunMode());
if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(queue.getReportId()); CommonBeanFactory.getBean(TestResultService.class).testEnded(dto);
report.setStatus(APITestStatus.Error.name());
apiScenarioReportMapper.updateByPrimaryKey(report);
} else { } else {
ApiDefinitionExecResult apiDefinitionExecResult = apiDefinitionExecResultMapper.selectByPrimaryKey(queue.getReportId()); ApiDefinitionExecResult apiDefinitionExecResult = apiDefinitionExecResultMapper.selectByPrimaryKey(queue.getReportId());
if (apiDefinitionExecResult != null) { if (apiDefinitionExecResult != null) {
@ -108,6 +132,7 @@ public class ApiScenarioSerialService {
apiDefinitionExecResultMapper.updateByPrimaryKey(apiDefinitionExecResult); apiDefinitionExecResultMapper.updateByPrimaryKey(apiDefinitionExecResult);
} }
} }
CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto);
} }
} }

View File

@ -32,16 +32,16 @@ public class GenerateHashTreeUtil {
public static MsScenario parseScenarioDefinition(String scenarioDefinition) { public static MsScenario parseScenarioDefinition(String scenarioDefinition) {
MsScenario scenario = JSONObject.parseObject(scenarioDefinition, MsScenario.class); MsScenario scenario = JSONObject.parseObject(scenarioDefinition, MsScenario.class);
parse(scenarioDefinition, scenario); parse(scenarioDefinition, scenario, scenario.getId(), null);
return scenario; return scenario;
} }
public static void parse(String scenarioDefinition, MsScenario scenario) { public static void parse(String scenarioDefinition, MsScenario scenario, String id, String reportType) {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try { try {
JSONObject element = JSON.parseObject(scenarioDefinition); JSONObject element = JSON.parseObject(scenarioDefinition);
ElementUtil.dataFormatting(element); ElementUtil.dataFormatting(element, id, reportType);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取 // 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) { if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
@ -99,7 +99,7 @@ public class GenerateHashTreeUtil {
return null; return null;
} }
public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap) { public static HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap, String reportType) {
HashTree jmeterHashTree = new HashTree(); HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan(); MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>()); testPlan.setHashTree(new LinkedList<>());
@ -112,7 +112,7 @@ public class GenerateHashTreeUtil {
if (planEnvMap != null && planEnvMap.size() > 0) { if (planEnvMap != null && planEnvMap.size() > 0) {
scenario.setEnvironmentMap(planEnvMap); scenario.setEnvironmentMap(planEnvMap);
} }
GenerateHashTreeUtil.parse(item.getScenarioDefinition(), scenario); GenerateHashTreeUtil.parse(item.getScenarioDefinition(), scenario, item.getId(), reportType);
group.setEnableCookieShare(scenario.isEnableCookieShare()); group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>(); LinkedList<MsTestElement> scenarios = new LinkedList<>();

View File

@ -12,9 +12,6 @@ public class FixedTask {
@Scheduled(cron = "0 */5 * * * ?") @Scheduled(cron = "0 */5 * * * ?")
public void execute() { public void execute() {
if (MessageCache.caseExecResourceLock.size() > 10000) {
MessageCache.caseExecResourceLock.clear();
}
if (queueService == null) { if (queueService == null) {
queueService = CommonBeanFactory.getBean(ApiExecutionQueueService.class); queueService = CommonBeanFactory.getBean(ApiExecutionQueueService.class);
} }

View File

@ -107,7 +107,11 @@ public class JMeterService {
if (baseInfo != null) { if (baseInfo != null) {
platformUrl = baseInfo.getUrl(); platformUrl = baseInfo.getUrl();
} }
platformUrl += "/api/jmeter/download?testId=" + request.getTestId() + "&reportId=" + request.getReportId() + "&runMode=" + request.getRunMode(); platformUrl += "/api/jmeter/download?testId="
+ request.getTestId()
+ "&reportId=" + request.getReportId()
+ "&runMode=" + request.getRunMode()
+ "&reportType=" + request.getReportType();
request.setPlatformUrl(platformUrl); request.setPlatformUrl(platformUrl);
request.setKafkaConfig(KafkaConfig.getKafka()); request.setKafkaConfig(KafkaConfig.getKafka());

View File

@ -1,7 +1,5 @@
package io.metersphere.api.jmeter; package io.metersphere.api.jmeter;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import javax.websocket.Session; import javax.websocket.Session;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -11,8 +9,6 @@ import java.util.concurrent.ConcurrentHashMap;
public class MessageCache { public class MessageCache {
public final static ConcurrentHashMap<String, Session> reportCache = new ConcurrentHashMap<>(); public final static ConcurrentHashMap<String, Session> reportCache = new ConcurrentHashMap<>();
// 用例并发锁
public final static ConcurrentHashMap<String, ApiDefinitionExecResult> caseExecResourceLock = new ConcurrentHashMap<>();
public final static Map<String, Long> jmeterLogTask = new HashMap<>(); public final static Map<String, Long> jmeterLogTask = new HashMap<>();

View File

@ -721,7 +721,7 @@ public class ApiAutomationService {
if (scenario == null) { if (scenario == null) {
return null; return null;
} }
GenerateHashTreeUtil.parse(apiScenario.getScenarioDefinition(), scenario); GenerateHashTreeUtil.parse(apiScenario.getScenarioDefinition(), scenario, apiScenario.getId(), null);
String environmentType = apiScenario.getEnvironmentType(); String environmentType = apiScenario.getEnvironmentType();
String environmentJson = apiScenario.getEnvironmentJson(); String environmentJson = apiScenario.getEnvironmentJson();
String environmentGroupId = apiScenario.getEnvironmentGroupId(); String environmentGroupId = apiScenario.getEnvironmentGroupId();

View File

@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.cache.TestPlanReportExecuteCatch; import io.metersphere.api.cache.TestPlanReportExecuteCatch;
import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult; import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiDefinitionMapper; import io.metersphere.base.mapper.ApiDefinitionMapper;
@ -320,34 +319,22 @@ public class ApiDefinitionExecResultService {
private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, int expectProcessResultCount, String type, String testId, boolean isFirst) { private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, int expectProcessResultCount, String type, String testId, boolean isFirst) {
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
ApiDefinitionExecResult saveResult = MessageCache.caseExecResourceLock.get(reportId); ApiDefinitionExecResult saveResult = new ApiDefinitionExecResult();
if (saveResult == null) {
saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId);
}
item.getResponseResult().setConsole(console); item.getResponseResult().setConsole(console);
boolean saved = true; saveResult.setId(reportId);
if (saveResult == null || expectProcessResultCount > 1) { saveResult.setActuator("LOCAL");
saveResult = new ApiDefinitionExecResult(); saveResult.setName(item.getName());
if (isFirst) { if (StringUtils.equals(type, ApiRunMode.JENKINS_API_PLAN.name())) {
saveResult.setId(reportId); saveResult.setTriggerMode(TriggerMode.API.name());
} else { } else if (StringUtils.equals(type, ApiRunMode.MANUAL_PLAN.name())) {
saveResult.setId(UUID.randomUUID().toString()); saveResult.setTriggerMode(TriggerMode.MANUAL.name());
} } else {
saveResult.setActuator("LOCAL"); saveResult.setTriggerMode(TriggerMode.SCHEDULE.name());
saveResult.setName(item.getName()); }
if (StringUtils.equals(type, ApiRunMode.JENKINS_API_PLAN.name())) { saveResult.setType(type);
saveResult.setTriggerMode(TriggerMode.API.name()); saveResult.setCreateTime(item.getStartTime());
} else if (StringUtils.equals(type, ApiRunMode.MANUAL_PLAN.name())) { if (SessionUtils.getUser() != null) {
saveResult.setTriggerMode(TriggerMode.MANUAL.name()); saveResult.setUserId(SessionUtils.getUser().getId());
} else {
saveResult.setTriggerMode(TriggerMode.SCHEDULE.name());
}
saveResult.setType(type);
saveResult.setCreateTime(item.getStartTime());
if (SessionUtils.getUser() != null) {
saveResult.setUserId(SessionUtils.getUser().getId());
}
saved = false;
} }
String status = item.isSuccess() ? "success" : "error"; String status = item.isSuccess() ? "success" : "error";
@ -367,14 +354,7 @@ public class ApiDefinitionExecResultService {
if (StringUtils.isNotEmpty(saveResult.getTriggerMode()) && saveResult.getTriggerMode().equals("CASE")) { if (StringUtils.isNotEmpty(saveResult.getTriggerMode()) && saveResult.getTriggerMode().equals("CASE")) {
saveResult.setTriggerMode(TriggerMode.MANUAL.name()); saveResult.setTriggerMode(TriggerMode.MANUAL.name());
} }
if (!saved) { apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
apiDefinitionExecResultMapper.insert(saveResult);
} else {
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
}
if (StringUtils.isNotEmpty(reportId)) {
MessageCache.caseExecResourceLock.remove(reportId);
}
return saveResult; return saveResult;
} }
return null; return null;

View File

@ -58,7 +58,7 @@ public class ApiJmeterFileService {
return listBytesToZip(files); return listBytesToZip(files);
} }
public byte[] downloadJmeterFiles(String runMode, String remoteTestId, String reportId) { public byte[] downloadJmeterFiles(String runMode, String remoteTestId, String reportId, String reportType) {
Map<String, String> planEnvMap = new HashMap<>(); Map<String, String> planEnvMap = new HashMap<>();
ApiScenarioWithBLOBs scenario = null; ApiScenarioWithBLOBs scenario = null;
if (StringUtils.equalsAny(runMode, ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) { if (StringUtils.equalsAny(runMode, ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
@ -96,7 +96,7 @@ public class ApiJmeterFileService {
planEnvMap = environmentGroupProjectService.getEnvMap(envGroupId); planEnvMap = environmentGroupProjectService.getEnvMap(envGroupId);
} }
} }
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap); hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap, reportType);
} }
return zipFilesToByteArray((reportId + "_" + remoteTestId), hashTree); return zipFilesToByteArray((reportId + "_" + remoteTestId), hashTree);
} }

View File

@ -43,7 +43,12 @@ public class ApiScenarioReportResultService {
report.setId(UUID.randomUUID().toString()); report.setId(UUID.randomUUID().toString());
result.setEndTime(System.currentTimeMillis()); result.setEndTime(System.currentTimeMillis());
if (result.getResponseResult() != null) { if (result.getResponseResult() != null) {
result.getResponseResult().setResponseTime((result.getEndTime() - result.getStartTime())); long time = result.getEndTime() - result.getStartTime();
if (time > 0) {
result.getResponseResult().setResponseTime(time);
} else {
result.setEndTime(result.getEndTime());
}
} }
String resourceId = result.getResourceId(); String resourceId = result.getResourceId();
if (StringUtils.isNotEmpty(resourceId) && resourceId.contains("_")) { if (StringUtils.isNotEmpty(resourceId) && resourceId.contains("_")) {

View File

@ -8,6 +8,7 @@ import io.metersphere.api.dto.StepTreeDTO;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiScenarioReportResultMapper; import io.metersphere.base.mapper.ApiScenarioReportResultMapper;
import io.metersphere.base.mapper.ApiScenarioReportStructureMapper; import io.metersphere.base.mapper.ApiScenarioReportStructureMapper;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.RequestResult; import io.metersphere.dto.RequestResult;
import io.metersphere.utils.LoggerUtil; import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -32,10 +33,10 @@ public class ApiScenarioReportStructureService {
private static final List<String> requests = Arrays.asList("HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "JSR223Processor", "AbstractSampler"); private static final List<String> requests = Arrays.asList("HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "JSR223Processor", "AbstractSampler");
public void save(List<ApiScenarioWithBLOBs> apiScenarios, String reportId) { public void save(List<ApiScenarioWithBLOBs> apiScenarios, String reportId, String reportType) {
List<StepTreeDTO> dtoList = new LinkedList<>(); List<StepTreeDTO> dtoList = new LinkedList<>();
for (ApiScenarioWithBLOBs bos : apiScenarios) { for (ApiScenarioWithBLOBs bos : apiScenarios) {
StepTreeDTO dto = dataFormatting(bos); StepTreeDTO dto = dataFormatting(bos, reportType);
dtoList.add(dto); dtoList.add(dto);
} }
if (LoggerUtil.getLogger().isDebugEnabled()) { if (LoggerUtil.getLogger().isDebugEnabled()) {
@ -44,9 +45,9 @@ public class ApiScenarioReportStructureService {
this.save(reportId, dtoList); this.save(reportId, dtoList);
} }
public void save(ApiScenarioWithBLOBs apiScenario, String reportId) { public void save(ApiScenarioWithBLOBs apiScenario, String reportId, String reportType) {
List<StepTreeDTO> dtoList = new LinkedList<>(); List<StepTreeDTO> dtoList = new LinkedList<>();
StepTreeDTO dto = dataFormatting(apiScenario); StepTreeDTO dto = dataFormatting(apiScenario, reportType);
dtoList.add(dto); dtoList.add(dto);
this.save(reportId, dtoList); this.save(reportId, dtoList);
} }
@ -70,28 +71,40 @@ public class ApiScenarioReportStructureService {
} }
} }
public static StepTreeDTO dataFormatting(ApiScenarioWithBLOBs apiScenario) { public static StepTreeDTO dataFormatting(ApiScenarioWithBLOBs apiScenario, String reportType) {
JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition()); JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition());
StepTreeDTO dto = null; StepTreeDTO dto = null;
if (element != null && element.getBoolean("enable")) { if (element != null && element.getBoolean("enable")) {
dto = new StepTreeDTO(apiScenario.getName(), element.getString("resourceId"), element.getString("type"), element.getIntValue("index")); String resourceId = element.getString("resourceId");
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (StringUtils.isNotEmpty(resourceId) && StringUtils.isNotEmpty(apiScenario.getId()) && !resourceId.contains(apiScenario.getId())) {
resourceId = apiScenario.getId() + "=" + element.getString("resourceId");
}
}
dto = new StepTreeDTO(apiScenario.getName(), resourceId, element.getString("type"), element.getIntValue("index"));
if (element.containsKey("hashTree") && !requests.contains(dto.getType())) { if (element.containsKey("hashTree") && !requests.contains(dto.getType())) {
JSONArray elementJSONArray = element.getJSONArray("hashTree"); JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, dto); dataFormatting(elementJSONArray, dto, apiScenario.getId(), reportType);
} }
} }
return dto; return dto;
} }
public static void dataFormatting(JSONArray hashTree, StepTreeDTO dto) { public static void dataFormatting(JSONArray hashTree, StepTreeDTO dto, String id, String reportType) {
for (int i = 0; i < hashTree.size(); i++) { for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i); JSONObject element = hashTree.getJSONObject(i);
if (element != null && element.getBoolean("enable")) { if (element != null && element.getBoolean("enable")) {
StepTreeDTO children = new StepTreeDTO(element.getString("name"), element.getString("resourceId"), element.getString("type"), element.getIntValue("index")); String resourceId = element.getString("resourceId");
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (StringUtils.isNotEmpty(resourceId) && StringUtils.isNotEmpty(id) && !resourceId.contains(id)) {
resourceId = id + "=" + element.getString("resourceId");
}
}
StepTreeDTO children = new StepTreeDTO(element.getString("name"), resourceId, element.getString("type"), element.getIntValue("index"));
dto.getChildren().add(children); dto.getChildren().add(children);
if (element.containsKey("hashTree") && !requests.contains(children.getType())) { if (element.containsKey("hashTree") && !requests.contains(children.getType())) {
JSONArray elementJSONArray = element.getJSONArray("hashTree"); JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, children); dataFormatting(elementJSONArray, children, id, reportType);
} }
} }
} }
@ -127,7 +140,7 @@ public class ApiScenarioReportStructureService {
} }
} }
private void calculateStep(List<StepTreeDTO> dtoList, AtomicLong stepError) { private void calculateStep(List<StepTreeDTO> dtoList, AtomicLong stepError, AtomicLong stepTotal) {
for (StepTreeDTO step : dtoList) { for (StepTreeDTO step : dtoList) {
// 失败结果数量 // 失败结果数量
AtomicLong error = new AtomicLong(); AtomicLong error = new AtomicLong();
@ -135,6 +148,9 @@ public class ApiScenarioReportStructureService {
if (error.longValue() > 0) { if (error.longValue() > 0) {
stepError.set((stepError.longValue() + 1)); stepError.set((stepError.longValue() + 1));
} }
if (CollectionUtils.isNotEmpty(step.getChildren())) {
stepTotal.set((stepTotal.longValue() + step.getChildren().size()));
}
} }
} }
@ -194,8 +210,6 @@ public class ApiScenarioReportStructureService {
ApiScenarioReportStructureWithBLOBs scenarioReportStructure = reportStructureWithBLOBs.get(0); ApiScenarioReportStructureWithBLOBs scenarioReportStructure = reportStructureWithBLOBs.get(0);
List<StepTreeDTO> stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class); List<StepTreeDTO> stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class);
reportDTO.setScenarioStepTotal(stepList.size());
// 匹配结果 // 匹配结果
Map<String, List<ApiScenarioReportResult>> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId)); Map<String, List<ApiScenarioReportResult>> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId));
this.reportFormatting(stepList, maps); this.reportFormatting(stepList, maps);
@ -213,7 +227,9 @@ public class ApiScenarioReportStructureService {
reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue())); reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue()));
AtomicLong stepError = new AtomicLong(); AtomicLong stepError = new AtomicLong();
calculateStep(stepList, stepError); AtomicLong stepTotal = new AtomicLong();
calculateStep(stepList, stepError, stepTotal);
reportDTO.setScenarioStepTotal(stepTotal.longValue());
reportDTO.setScenarioStepError(stepError.longValue()); reportDTO.setScenarioStepError(stepError.longValue());
reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue())); reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue()));

View File

@ -114,7 +114,6 @@ public class RemakeReportService {
} }
} }
} }
MessageCache.caseExecResourceLock.remove(request.getReportId());
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e);
} }
@ -143,6 +142,5 @@ public class RemakeReportService {
} }
report.setStatus(APITestStatus.Error.name()); report.setStatus(APITestStatus.Error.name());
apiScenarioReportMapper.insert(report); apiScenarioReportMapper.insert(report);
MessageCache.caseExecResourceLock.remove(report.getId());
} }
} }

View File

@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.automation.TaskRequest; import io.metersphere.api.dto.automation.TaskRequest;
import io.metersphere.api.exec.queue.ExecThreadPoolExecutor; import io.metersphere.api.exec.queue.ExecThreadPoolExecutor;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper; import io.metersphere.base.mapper.ApiScenarioReportMapper;
@ -124,7 +123,6 @@ public class TaskService {
result.setStatus("STOP"); result.setStatus("STOP");
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result); apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
actuator = result.getActuator(); actuator = result.getActuator();
MessageCache.caseExecResourceLock.remove(result.getId());
} }
} else if (StringUtils.equals(request.getType(), "SCENARIO")) { } else if (StringUtils.equals(request.getType(), "SCENARIO")) {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId()); ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
@ -145,7 +143,6 @@ public class TaskService {
item.setStatus("STOP"); item.setStatus("STOP");
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(item); apiDefinitionExecResultMapper.updateByPrimaryKeySelective(item);
actuator = item.getActuator(); actuator = item.getActuator();
MessageCache.caseExecResourceLock.remove(item.getId());
request.setReportId(item.getId()); request.setReportId(item.getId());
extracted(poolMap, request, actuator); extracted(poolMap, request, actuator);
} }

View File

@ -21,7 +21,7 @@
<template slot="label"> <template slot="label">
<span class="console">{{ $t('api_test.definition.request.console') }}</span> <span class="console">{{ $t('api_test.definition.request.console') }}</span>
</template> </template>
<pre>{{ content.console }}</pre> <ms-code-edit :mode="'text'" :read-only="true" :data.sync="content.console" height="calc(100vh - 500px)"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@ -50,6 +50,7 @@ import {RequestFactory} from "../../definition/model/ApiTestModel";
import {windowPrint, getUUID, getCurrentProjectID} from "@/common/js/utils"; import {windowPrint, getUUID, getCurrentProjectID} from "@/common/js/utils";
import {getScenarioReport, getShareScenarioReport} from "@/network/api"; import {getScenarioReport, getShareScenarioReport} from "@/network/api";
import {STEP} from "@/business/components/api/automation/scenario/Setting"; import {STEP} from "@/business/components/api/automation/scenario/Setting";
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
export default { export default {
name: "MsApiReport", name: "MsApiReport",
@ -57,6 +58,7 @@ export default {
MsApiReportViewHeader, MsApiReportViewHeader,
MsApiReportExport, MsApiReportExport,
MsMainContainer, MsMainContainer,
MsCodeEdit,
MsContainer, MsScenarioResults, MsRequestResultTail, MsMetricChart, MsScenarioResult, MsRequestResult MsContainer, MsScenarioResults, MsRequestResultTail, MsMetricChart, MsScenarioResult, MsRequestResult
}, },
data() { data() {
@ -526,7 +528,10 @@ export default {
.report-container .is-active .fail { .report-container .is-active .fail {
color: inherit; color: inherit;
} }
.report-console {
height: calc(100vh - 270px);
overflow-y: auto;
}
.export-button { .export-button {
float: right; float: right;
} }