diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/ScenarioStatus.java b/backend/src/main/java/io/metersphere/api/dto/automation/ScenarioStatus.java index d2e33af03a..9697d77940 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/ScenarioStatus.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/ScenarioStatus.java @@ -1,5 +1,7 @@ package io.metersphere.api.dto.automation; +import org.junit.internal.runners.statements.Fail; + public enum ScenarioStatus { - Saved, Success, Fail, Trash,Underway + Saved, Success, Error, Timeout, Fail, Trash, Underway } diff --git a/backend/src/main/java/io/metersphere/api/exec/queue/ExecTask.java b/backend/src/main/java/io/metersphere/api/exec/queue/ExecTask.java index 95159107db..36db9dd81c 100644 --- a/backend/src/main/java/io/metersphere/api/exec/queue/ExecTask.java +++ b/backend/src/main/java/io/metersphere/api/exec/queue/ExecTask.java @@ -1,6 +1,7 @@ package io.metersphere.api.exec.queue; import io.metersphere.api.jmeter.JMeterService; +import io.metersphere.api.jmeter.JmeterThreadUtils; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.dto.JmeterRunRequestDTO; import io.metersphere.utils.LoggerUtil; @@ -23,7 +24,7 @@ public class ExecTask implements Runnable { jMeterService.addQueue(request); if (request.getPool() == null || !request.getPool().isPool()) { Object res = PoolExecBlockingQueueUtil.take(request.getReportId()); - if (res == null) { + if (res == null && !JmeterThreadUtils.isRunning(request.getReportId(), request.getTestId())) { LoggerUtil.info("执行报告:【 " + request.getReportId() + " 】,资源ID【 " + request.getTestId() + " 】执行超时"); } } diff --git a/backend/src/main/java/io/metersphere/api/exec/queue/PoolExecBlockingQueueUtil.java b/backend/src/main/java/io/metersphere/api/exec/queue/PoolExecBlockingQueueUtil.java index 1b8f30dcef..d0bfecc378 100644 --- a/backend/src/main/java/io/metersphere/api/exec/queue/PoolExecBlockingQueueUtil.java +++ b/backend/src/main/java/io/metersphere/api/exec/queue/PoolExecBlockingQueueUtil.java @@ -33,7 +33,7 @@ public class PoolExecBlockingQueueUtil { if (StringUtils.isNotEmpty(key) && !queue.containsKey(key)) { BlockingQueue blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE); queue.put(key, blockingQueue); - return blockingQueue.poll(5, TimeUnit.MINUTES); + return blockingQueue.poll(10, TimeUnit.MINUTES); } } catch (Exception e) { LogUtil.error("初始化队列失败:" + e.getMessage()); diff --git a/backend/src/main/java/io/metersphere/api/exec/utils/ApiDefinitionExecResultUtil.java b/backend/src/main/java/io/metersphere/api/exec/utils/ApiDefinitionExecResultUtil.java index 0fced9c750..dd91cc2794 100644 --- a/backend/src/main/java/io/metersphere/api/exec/utils/ApiDefinitionExecResultUtil.java +++ b/backend/src/main/java/io/metersphere/api/exec/utils/ApiDefinitionExecResultUtil.java @@ -91,7 +91,6 @@ public class ApiDefinitionExecResultUtil { apiResult.setStartTime(System.currentTimeMillis()); apiResult.setType(ApiRunMode.DEFINITION.name()); apiResult.setStatus(status); - return apiResult; } } diff --git a/backend/src/main/java/io/metersphere/api/jmeter/APISingleResultListener.java b/backend/src/main/java/io/metersphere/api/jmeter/APISingleResultListener.java index e43f3dc980..0ebcb56c85 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/APISingleResultListener.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/APISingleResultListener.java @@ -5,10 +5,12 @@ import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil; import io.metersphere.api.service.ApiExecutionQueueService; import io.metersphere.api.service.MsResultService; import io.metersphere.api.service.TestResultService; +import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.dto.ResultDTO; import io.metersphere.jmeter.MsExecListener; import io.metersphere.utils.LoggerUtil; +import org.apache.commons.lang3.StringUtils; import java.util.Map; @@ -18,13 +20,19 @@ public class APISingleResultListener extends MsExecListener { LoggerUtil.info("处理单条执行结果报告【" + dto.getReportId() + " 】,资源【 " + dto.getTestId() + " 】"); dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId())); CommonBeanFactory.getBean(TestResultService.class).saveResults(dto); + + // 更新报告最后接收到请求的时间 + if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCENARIO.name(), + ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), + ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { + CommonBeanFactory.getBean(TestResultService.class).editReportTime(dto); + } } @Override public void testEnded(ResultDTO dto, Map kafkaConfig) { try { LoggerUtil.info("进入TEST-END处理报告【" + dto.getReportId() + " 】整体执行完成;" + dto.getRunMode()); - // 全局并发队列 PoolExecBlockingQueueUtil.offer(dto.getReportId()); dto.setConsole(CommonBeanFactory.getBean(MsResultService.class).getJmeterLogger(dto.getReportId())); diff --git a/backend/src/main/java/io/metersphere/api/jmeter/JmeterThreadUtils.java b/backend/src/main/java/io/metersphere/api/jmeter/JmeterThreadUtils.java index 84eac7d47e..b088d39571 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/JmeterThreadUtils.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/JmeterThreadUtils.java @@ -7,9 +7,7 @@ public class JmeterThreadUtils { private final static String THREAD_SPLIT = " "; public static String stop(String name) { - ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); - int noThreads = currentGroup.activeCount(); Thread[] lstThreads = new Thread[noThreads]; currentGroup.enumerate(lstThreads); @@ -24,4 +22,19 @@ public class JmeterThreadUtils { } return threadNames.toString(); } + + public static boolean isRunning(String reportId, String testId) { + ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); + int noThreads = currentGroup.activeCount(); + Thread[] lstThreads = new Thread[noThreads]; + currentGroup.enumerate(lstThreads); + for (int i = 0; i < noThreads; i++) { + if (StringUtils.isNotEmpty(reportId) && StringUtils.isNotEmpty(lstThreads[i].getName()) && lstThreads[i].getName().startsWith(reportId)) { + return true; + } else if (StringUtils.isNotEmpty(testId) && StringUtils.isNotEmpty(lstThreads[i].getName()) && lstThreads[i].getName().startsWith(testId)) { + return true; + } + } + return false; + } } diff --git a/backend/src/main/java/io/metersphere/api/jmeter/MsKafkaListener.java b/backend/src/main/java/io/metersphere/api/jmeter/MsKafkaListener.java index 104b07b6e9..0ebbf92243 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/MsKafkaListener.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/MsKafkaListener.java @@ -7,6 +7,7 @@ import io.metersphere.api.exec.queue.PoolExecBlockingQueueUtil; import io.metersphere.api.service.ApiEnvironmentRunningParamService; import io.metersphere.api.service.ApiExecutionQueueService; import io.metersphere.api.service.TestResultService; +import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.config.KafkaConfig; import io.metersphere.dto.ResultDTO; @@ -34,6 +35,13 @@ public class MsKafkaListener { // 全局并发队列 PoolExecBlockingQueueUtil.offer(testResult.getReportId()); } else { + // 更新报告最后接收到请求的时间 + if (StringUtils.equalsAny(testResult.getRunMode(), ApiRunMode.SCENARIO.name(), + ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), + ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { + CommonBeanFactory.getBean(TestResultService.class).editReportTime(testResult); + } + testResultService.saveResults(testResult); } LoggerUtil.info("执行内容存储结束"); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java index 9fa47757c0..f4dccca587 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java @@ -187,8 +187,6 @@ public class ApiDefinitionExecResultService { * 定时任务时,userID要改为定时任务中的用户 */ public void saveApiResultByScheduleTask(List requestResults, ResultDTO dto) { - Map apiIdResultMap = new HashMap<>(); - Map caseReportMap = new HashMap<>(); boolean isFirst = true; int countExpectProcessResultCount = 0; if (CollectionUtils.isNotEmpty(requestResults)) { @@ -201,7 +199,7 @@ public class ApiDefinitionExecResultService { for (RequestResult item : requestResults) { if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { - ApiDefinitionExecResult saveResult = this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst); + this.save(item, dto.getReportId(), dto.getConsole(), countExpectProcessResultCount, dto.getRunMode(), dto.getTestId(), isFirst); String status = item.isSuccess() ? "success" : "error"; if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCHEDULE_API_PLAN.name(), ApiRunMode.JENKINS_API_PLAN.name())) { TestPlanApiCase apiCase = testPlanApiCaseService.getById(dto.getTestId()); @@ -214,19 +212,19 @@ public class ApiDefinitionExecResultService { testPlanApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime()); testCaseReviewApiCaseService.setExecResult(dto.getTestId(), status, item.getStartTime()); } - if (StringUtils.isNotEmpty(dto.getTestId())) { - apiIdResultMap.put(dto.getTestId(), item.isSuccess() ? TestPlanApiExecuteStatus.SUCCESS.name() : TestPlanApiExecuteStatus.FAILD.name()); - } - //更新报告ID - caseReportMap.put(dto.getTestId(), saveResult.getId()); isFirst = false; } } } updateTestCaseStates(dto.getTestId()); + Map apiIdResultMap = new HashMap<>(); + long errorSize = requestResults.stream().filter(requestResult -> requestResult.getError() > 0).count(); + String status = errorSize > 0 || requestResults.isEmpty() ? TestPlanApiExecuteStatus.FAILD.name() : TestPlanApiExecuteStatus.SUCCESS.name(); + if (StringUtils.isNotEmpty(dto.getReportId())) { + apiIdResultMap.put(dto.getReportId(), status); + } testPlanLog.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] APICASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap)); TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(dto.getTestPlanReportId(), apiIdResultMap, null, null); - TestPlanReportExecuteCatch.updateTestPlanReport(dto.getTestPlanReportId(), caseReportMap, null); } /** diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index d6bf975adc..415a3a916a 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -22,6 +22,7 @@ import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult; import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest; import io.metersphere.api.exec.api.ApiExecuteService; +import io.metersphere.api.exec.utils.ApiDefinitionExecResultUtil; import io.metersphere.api.parse.ApiImportParser; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.*; @@ -102,16 +103,12 @@ public class ApiDefinitionService { @Resource private ApiTestCaseMapper apiTestCaseMapper; @Resource - private ApiTestEnvironmentService environmentService; - @Resource private EsbApiParamService esbApiParamService; @Resource private TcpApiParamService tcpApiParamService; @Resource private ApiModuleMapper apiModuleMapper; @Resource - private SystemParameterService systemParameterService; - @Resource private TestPlanMapper testPlanMapper; @Resource private NoticeSendService noticeSendService; @@ -855,6 +852,15 @@ public class ApiDefinitionService { * @return */ public MsExecResponseDTO run(RunDefinitionRequest request, List bodyFiles) { + if (!request.isDebug()) { + String testId = request.getTestElement() != null && + CollectionUtils.isNotEmpty(request.getTestElement().getHashTree()) && + CollectionUtils.isNotEmpty(request.getTestElement().getHashTree().get(0).getHashTree()) ? + request.getTestElement().getHashTree().get(0).getHashTree().get(0).getName() : request.getId(); + ApiDefinitionExecResult result = ApiDefinitionExecResultUtil.add(testId, APITestStatus.Running.name(), request.getId()); + result.setTriggerMode(TriggerMode.MANUAL.name()); + apiDefinitionExecResultMapper.insert(result); + } return apiExecuteService.debug(request, bodyFiles); } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java b/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java index d53877f287..652c3209e0 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java @@ -2,6 +2,7 @@ package io.metersphere.api.service; import com.alibaba.fastjson.JSON; import io.metersphere.api.dto.RunModeDataDTO; +import io.metersphere.api.dto.automation.ScenarioStatus; import io.metersphere.api.exec.queue.DBTestQueue; import io.metersphere.api.exec.scenario.ApiScenarioSerialService; import io.metersphere.base.domain.*; @@ -179,9 +180,8 @@ public class ApiExecutionQueueService { public void timeOut() { final int SECOND_MILLIS = 1000; final int MINUTE_MILLIS = 60 * SECOND_MILLIS; - long now = System.currentTimeMillis(); - // 八分钟前的数据 - now = now - 8 * MINUTE_MILLIS; + // 二十分钟前的超时报告 + final long now = System.currentTimeMillis() - (20 * MINUTE_MILLIS); ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample(); example.createCriteria().andCreateTimeLessThan(now); List queueDetails = executionQueueDetailMapper.selectByExample(example); @@ -190,14 +190,14 @@ public class ApiExecutionQueueService { queueDetails.forEach(item -> { if (StringUtils.equalsAny(item.getType(), 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(item.getReportId()); - if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name())) { - report.setStatus("timeout"); + if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name()) && report.getUpdateTime() < now) { + report.setStatus(ScenarioStatus.Timeout.name()); apiScenarioReportMapper.updateByPrimaryKeySelective(report); } } else { ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(item.getReportId()); if (result != null && StringUtils.equalsAny(result.getStatus(), TestPlanReportStatus.RUNNING.name())) { - result.setStatus("timeout"); + result.setStatus(ScenarioStatus.Timeout.name()); apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result); } } @@ -211,8 +211,8 @@ public class ApiExecutionQueueService { if (CollectionUtils.isNotEmpty(executionQueues)) { executionQueues.forEach(item -> { ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId()); - if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name())) { - report.setStatus("timeout"); + if (report != null && StringUtils.equalsAny(report.getStatus(), TestPlanReportStatus.RUNNING.name()) && report.getUpdateTime() < now) { + report.setStatus(ScenarioStatus.Timeout.name()); apiScenarioReportMapper.updateByPrimaryKeySelective(report); } }); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java index 8905e67734..a101e84404 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java @@ -87,6 +87,7 @@ public class ApiScenarioReportService { apiScenarioReportResultService.save(dto.getReportId(), requestResults); } + public ApiScenarioReport testEnded(ResultDTO dto) { if (!StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) { // 更新控制台信息 @@ -96,6 +97,15 @@ public class ApiScenarioReportService { example.createCriteria().andReportIdEqualTo(dto.getReportId()); List requestResults = apiScenarioReportResultMapper.selectByExample(example); + if (StringUtils.isNotEmpty(dto.getTestPlanReportId())) { + String status = getStatus(requestResults, dto); + Map reportMap = new HashMap() {{ + this.put(dto.getReportId(), status); + }}; + testPlanLog.info("TestPlanReportId" + JSONArray.toJSONString(dto.getReportId()) + " EXECUTE OVER. SCENARIO STATUS : " + JSONObject.toJSONString(reportMap)); + TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(dto.getTestPlanReportId(), null, reportMap, null); + } + ApiScenarioReport scenarioReport; if (StringUtils.equals(dto.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) { scenarioReport = updatePlanCase(requestResults, dto); @@ -226,7 +236,7 @@ public class ApiScenarioReportService { } public ApiScenarioReport updatePlanCase(List requestResults, ResultDTO dto) { - long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Error")).count(); + long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count(); TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(dto.getTestId()); if (testPlanApiScenario != null) { if (errorSize > 0) { @@ -234,7 +244,7 @@ public class ApiScenarioReportService { } else { testPlanApiScenario.setLastResult(ScenarioStatus.Success.name()); } - long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Success")).count(); + long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count(); String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size()); testPlanApiScenario.setPassRate(passRate); @@ -245,7 +255,7 @@ public class ApiScenarioReportService { // 更新场景状态 ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId()); if (scenario != null) { - scenario.setLastResult(errorSize > 0 ? "Fail" : "Success"); + scenario.setLastResult(errorSize > 0 ? "Fail" : ScenarioStatus.Success.name()); scenario.setPassRate(passRate); scenario.setReportId(dto.getReportId()); int executeTimes = 0; @@ -256,11 +266,7 @@ public class ApiScenarioReportService { apiScenarioMapper.updateByPrimaryKey(scenario); } } - String status = errorSize > 0 || requestResults.isEmpty() ? "Error" : "Success"; - if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) { - LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时"); - status = "Timeout"; - } + String status = getStatus(requestResults, dto); ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode()); return report; } @@ -269,15 +275,8 @@ public class ApiScenarioReportService { List testPlanReportIdList = new ArrayList<>(); StringBuilder scenarioNames = new StringBuilder(); - Map scenarioAndErrorMap = new HashMap<>(); - Map planScenarioReportMap = new HashMap<>(); - long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Error")).count(); - - String status = errorSize > 0 || requestResults.isEmpty() ? "Error" : "Success"; - if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) { - LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时"); - status = "Timeout"; - } + long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count(); + String status = getStatus(requestResults, dto); ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode()); if (report != null) { if (StringUtils.isNotEmpty(dto.getTestPlanReportId()) && !testPlanReportIdList.contains(dto.getTestPlanReportId())) { @@ -288,15 +287,12 @@ public class ApiScenarioReportService { report.setScenarioId(testPlanApiScenario.getApiScenarioId()); report.setEndTime(System.currentTimeMillis()); apiScenarioReportMapper.updateByPrimaryKeySelective(report); - planScenarioReportMap.put(dto.getTestId(), report.getId()); if (errorSize > 0) { - scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.FAILD.name()); testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name()); } else { - scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.SUCCESS.name()); testPlanApiScenario.setLastResult(ScenarioStatus.Success.name()); } - long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Success")).count(); + long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count(); String passRate = new DecimalFormat("0%").format((float) successSize / requestResults.size()); testPlanApiScenario.setPassRate(passRate); @@ -312,7 +308,7 @@ public class ApiScenarioReportService { if (errorSize > 0) { scenario.setLastResult("Fail"); } else { - scenario.setLastResult("Success"); + scenario.setLastResult(ScenarioStatus.Success.name()); } scenario.setPassRate(passRate); scenario.setReportId(report.getId()); @@ -325,11 +321,6 @@ public class ApiScenarioReportService { apiScenarioMapper.updateByPrimaryKey(scenario); } } - testPlanLog.info("TestPlanReportId" + JSONArray.toJSONString(testPlanReportIdList) + " EXECUTE OVER. SCENARIO STATUS : " + JSONObject.toJSONString(scenarioAndErrorMap)); - for (String item : testPlanReportIdList) { - TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(item, null, scenarioAndErrorMap, null); - TestPlanReportExecuteCatch.updateTestPlanReport(item, null, planScenarioReportMap); - } } return report; } @@ -339,9 +330,9 @@ public class ApiScenarioReportService { if (report != null) { // 更新场景状态 ApiScenarioReportResultExample example = new ApiScenarioReportResultExample(); - example.createCriteria().andReportIdEqualTo(reportId).andStatusEqualTo("Error"); + example.createCriteria().andReportIdEqualTo(reportId).andStatusEqualTo(ScenarioStatus.Error.name()); long size = apiScenarioReportResultMapper.countByExample(example); - report.setStatus(size > 0 ? "Error" : "Success"); + report.setStatus(size > 0 ? ScenarioStatus.Error.name() : ScenarioStatus.Success.name()); report.setEndTime(System.currentTimeMillis()); // 更新控制台信息 apiScenarioReportStructureService.update(reportId, resultService.getJmeterLogger(reportId)); @@ -351,13 +342,10 @@ public class ApiScenarioReportService { } public ApiScenarioReport updateScenario(List requestResults, ResultDTO dto) { - long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Error")).count(); + long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count(); // 更新报告状态 - String status = errorSize > 0 || requestResults.isEmpty() ? "Error" : "Success"; - if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) { - LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时"); - status = "Timeout"; - } + String status = getStatus(requestResults, dto); + ApiScenarioReport report = editReport(dto.getReportType(), dto.getReportId(), status, dto.getRunMode()); // 更新场景状态 ApiScenarioWithBLOBs scenario = apiScenarioMapper.selectByPrimaryKey(dto.getTestId()); @@ -365,8 +353,8 @@ public class ApiScenarioReportService { scenario = apiScenarioMapper.selectByPrimaryKey(report.getScenarioId()); } if (scenario != null) { - scenario.setLastResult(errorSize > 0 ? "Fail" : "Success"); - long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), "Success")).count(); + scenario.setLastResult(errorSize > 0 ? "Fail" : ScenarioStatus.Success.name()); + long successSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Success.name())).count(); scenario.setPassRate(new DecimalFormat("0%").format((float) successSize / requestResults.size())); scenario.setReportId(dto.getReportId()); int executeTimes = 0; @@ -417,7 +405,7 @@ public class ApiScenarioReportService { String event; String status; - if (StringUtils.equals(scenario.getLastResult(), "Success")) { + if (StringUtils.equals(scenario.getLastResult(), ScenarioStatus.Success.name())) { event = NoticeConstants.Event.EXECUTE_SUCCESSFUL; status = "成功"; } else { @@ -707,4 +695,14 @@ public class ApiScenarioReportService { report.setScenarioId(scenarioId); return report; } + + private String getStatus(List requestResults, ResultDTO dto) { + long errorSize = requestResults.stream().filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ScenarioStatus.Error.name())).count(); + String status = errorSize > 0 || requestResults.isEmpty() ? ScenarioStatus.Error.name() : ScenarioStatus.Success.name(); + if (dto != null && dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("TIMEOUT") && (Boolean) dto.getArbitraryData().get("TIMEOUT")) { + LoggerUtil.info("报告 【 " + dto.getReportId() + " 】资源 " + dto.getTestId() + " 执行超时"); + status = ScenarioStatus.Timeout.name(); + } + return status; + } } diff --git a/backend/src/main/java/io/metersphere/api/service/TestResultService.java b/backend/src/main/java/io/metersphere/api/service/TestResultService.java index 8bf1da1f51..f65e71a03a 100644 --- a/backend/src/main/java/io/metersphere/api/service/TestResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/TestResultService.java @@ -3,6 +3,7 @@ package io.metersphere.api.service; import io.metersphere.api.dto.automation.ApiTestReportVariable; import io.metersphere.api.jmeter.ExecutedHandleSingleton; import io.metersphere.base.domain.*; +import io.metersphere.base.mapper.ApiScenarioReportMapper; import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.NoticeConstants; import io.metersphere.commons.constants.ReportTriggerMode; @@ -47,6 +48,8 @@ public class TestResultService { private TestPlanTestCaseService testPlanTestCaseService; @Resource private ApiTestCaseService apiTestCaseService; + @Resource + private ApiScenarioReportMapper apiScenarioReportMapper; public void saveResults(ResultDTO dto) { // 处理环境 @@ -70,6 +73,14 @@ public class TestResultService { updateTestCaseStates(requestResults, dto.getRunMode()); } + public void editReportTime(ResultDTO dto) { + ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(dto.getReportId()); + if (report != null) { + report.setUpdateTime(System.currentTimeMillis()); + apiScenarioReportMapper.updateByPrimaryKey(report); + } + } + public void testEnded(ResultDTO dto) { if (StringUtils.equalsAny(dto.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { ApiScenarioReport scenarioReport = apiScenarioReportService.testEnded(dto);