From 8f3e32840a38822150d17ba315215c4f78c21630 Mon Sep 17 00:00:00 2001 From: liangdaliang Date: Mon, 24 Feb 2025 16:00:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=8F=8A=E6=8A=A5=E5=91=8A=E6=A0=B8=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/common/config/SchedulerConfig.java | 22 +++ .../test/test/service/ITestTaskService.java | 4 +- .../test/service/impl/TaskManagerService.java | 159 ++++++++++++++++++ .../service/impl/TestTaskServiceImpl.java | 42 ++--- 4 files changed, 204 insertions(+), 23 deletions(-) create mode 100644 test-common/src/main/java/com/test/common/config/SchedulerConfig.java create mode 100644 test-test/src/main/java/com/test/test/service/impl/TaskManagerService.java diff --git a/test-common/src/main/java/com/test/common/config/SchedulerConfig.java b/test-common/src/main/java/com/test/common/config/SchedulerConfig.java new file mode 100644 index 0000000..78a5a70 --- /dev/null +++ b/test-common/src/main/java/com/test/common/config/SchedulerConfig.java @@ -0,0 +1,22 @@ +package com.test.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +/** + * @author liangdaliang + * @Description:自定义定时任务配置 + * @date 2025-02-24 10:27 + */ +@Configuration +public class SchedulerConfig { + + @Bean + public ThreadPoolTaskScheduler taskScheduler() { + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(60); // 设置线程池大小 + scheduler.setThreadNamePrefix("TestTaskScheduler-"); + return scheduler; + } +} diff --git a/test-test/src/main/java/com/test/test/service/ITestTaskService.java b/test-test/src/main/java/com/test/test/service/ITestTaskService.java index a80c13f..8752624 100644 --- a/test-test/src/main/java/com/test/test/service/ITestTaskService.java +++ b/test-test/src/main/java/com/test/test/service/ITestTaskService.java @@ -42,10 +42,10 @@ public interface ITestTaskService { /** * 根据测试任务id执行测试定时任务 * @param id 测试定时任务id - * @param isImmediateRun 是否立即执行 * @param triggerType 触发方式:1-定时任务;2-手动 * @param environment 环境 + * @param jmeterHomePath jmeter安装路径 * @return 是否成功 */ - boolean executeTestTaskById(Long id, boolean isImmediateRun, Integer triggerType, String environment); + boolean executeTestTaskById(Long id, Integer triggerType, String environment, String jmeterHomePath); } diff --git a/test-test/src/main/java/com/test/test/service/impl/TaskManagerService.java b/test-test/src/main/java/com/test/test/service/impl/TaskManagerService.java new file mode 100644 index 0000000..40de1a5 --- /dev/null +++ b/test-test/src/main/java/com/test/test/service/impl/TaskManagerService.java @@ -0,0 +1,159 @@ +package com.test.test.service.impl; + +import com.test.common.utils.DateUtils; +import com.test.test.domain.TestTask; +import com.test.test.domain.TestTaskCase; +import com.test.test.domain.TestTaskResult; +import com.test.test.mapper.TestTaskResultMapper; +import com.test.test.service.ITestCaseService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledFuture; +import java.util.stream.Collectors; + +/** + * @author liangdaliang + * @Description:定时任务管理服务 + * @date 2025-02-24 12:52 + */ +@Slf4j +@Service +public class TaskManagerService { + + @Resource + private TestTaskResultMapper testTaskResultMapper; + + @Autowired + private ThreadPoolTaskScheduler taskScheduler; + @Autowired + private ITestCaseService testCaseService; + + // 存储任务和其对应的 ScheduledFuture + private final Map> taskMap = new HashMap<>(); + + /** + * 添加定时任务 + * + * @param testTask 任务 + * @param jmeterHomePath jmeter安装路径 + * @param testTaskCaseList 待执行测试用例列表 + * @param testTaskResult 定时任务结果 + */ + public void addTask(TestTask testTask, String jmeterHomePath, List testTaskCaseList, TestTaskResult testTaskResult) { + Long id = testTask.getId(); + String crontab = testTask.getCrontab(); + // 如果任务已存在,先取消 + if (taskMap.containsKey(id)) { + taskMap.get(id).cancel(true); + } + + // 创建定时任务 + ScheduledFuture future = taskScheduler.schedule( + () -> executeTaskWithTestCases(testTask, jmeterHomePath, testTaskCaseList, testTaskResult), + new CronTrigger(crontab) + ); + + // 将任务添加到 Map 中 + taskMap.put(id, future); + } + + /** + * 执行定时任务,并处理测试用例 + * + * @param testTask 任务 + * @param jmeterHomePath jmeter安装路径 + * @param testTaskCaseList 待执行测试用例列表 + * @param testTaskResult 定时任务结果 + */ + public void executeTaskWithTestCases(TestTask testTask, String jmeterHomePath, List testTaskCaseList, TestTaskResult testTaskResult) { + Long id = testTask.getId(); + List results = new ArrayList<>(); + // 并行开关:0打开;2关闭 + Integer async = testTask.getAsync(); + log.info("Starting task with ID: {}", id); + testTaskResult.setStartTime(DateUtils.getNowDate()); + long startTime = System.currentTimeMillis(); + if (async == 0) { + // 创建任务关联所有测试用例的 CompletableFuture + List> testCaseFutures = new ArrayList<>(); + for (TestTaskCase testTaskCase : testTaskCaseList) { + CompletableFuture future = CompletableFuture.supplyAsync(() -> executeTestCase(testTask, testTaskCase.getCaseId(), jmeterHomePath)); + testCaseFutures.add(future); + } + // 等待所有测试用例完成 + CompletableFuture allFutures = CompletableFuture.allOf( + testCaseFutures.toArray(new CompletableFuture[0]) + ); + // 阻塞等待所有测试用例完成 + allFutures.join(); + // 收集每个测试用例的执行结果 + results = testCaseFutures.stream() + .map(CompletableFuture::join) // 获取每个测试用例的结果 + .collect(Collectors.toList()); + } else { + for (TestTaskCase testTaskCase : testTaskCaseList) { + results.add(executeTestCase(testTask, testTaskCase.getCaseId(), jmeterHomePath)); + } + } + testTaskResult.setCostTime(System.currentTimeMillis() - startTime); + long trueCount = results.stream().filter(result -> result) // 过滤出 true + .count(); // 统计数量 + long falseCount = results.stream().filter(result -> !result) // 过滤出 false + .count(); // 统计数量 + if (falseCount > 0L) { + testTaskResult.setStatus(2); + } else { + testTaskResult.setStatus(1); + } + String result_desc = "总数:" + results.size() + " 成功:" + trueCount + " 失败:" + falseCount; + testTaskResult.setResultDesc(result_desc); + testTaskResult.setCreateTime(DateUtils.getNowDate()); + testTaskResultMapper.insertTestTaskResult(testTaskResult); + // 所有测试用例完成后,标记任务执行结束 + log.info("Task with ID {} completed.", id); + } + + /** + * 执行单个测试用例 + * + * @param testTask 任务 + * @param testCaseId 测试用例ID + * @param jmeterHomePath jmeter安装路径 + * @return 测试用例执行结果(true 表示成功,false 表示失败) + */ + public boolean executeTestCase(TestTask testTask, Long testCaseId, String jmeterHomePath) { + Long taskId = testTask.getId(); + // 失败重试开关:0打开;2关闭 + Integer retry = testTask.getRetry(); + Long retryCount = testTask.getRetryCount(); + try { + // 测试用例执行逻辑 + log.info("Executing test case {} for task {}", testCaseId, taskId); + boolean result = testCaseService.executeTestCaseById(testCaseId, jmeterHomePath); + if (!result && retry == 0) { + if (retryCount != null && retryCount > 0) { + for (int i = 0; i < retryCount; i++) { + result = testCaseService.executeTestCaseById(testCaseId, jmeterHomePath); + if (result) { + break; + } + } + } + } + return result; + } catch (Exception e) { + log.error("Test case {} for task {} failed: ", testCaseId, taskId, e); + return false; + } + } +} diff --git a/test-test/src/main/java/com/test/test/service/impl/TestTaskServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/TestTaskServiceImpl.java index abe059a..7b5136b 100644 --- a/test-test/src/main/java/com/test/test/service/impl/TestTaskServiceImpl.java +++ b/test-test/src/main/java/com/test/test/service/impl/TestTaskServiceImpl.java @@ -3,10 +3,14 @@ package com.test.test.service.impl; import com.test.common.utils.DateUtils; import com.test.test.domain.*; import com.test.test.domain.qo.GroupIdQO; -import com.test.test.mapper.*; +import com.test.test.mapper.TestCaseMapper; +import com.test.test.mapper.TestCaseStepMapper; +import com.test.test.mapper.TestTaskCaseMapper; +import com.test.test.mapper.TestTaskMapper; import com.test.test.service.ITestTaskService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -31,8 +35,8 @@ public class TestTaskServiceImpl implements ITestTaskService { @Resource private TestCaseStepMapper testCaseStepMapper; - @Resource - private TestTaskResultMapper testTaskResultMapper; + @Autowired + private TaskManagerService taskManagerService; /** * 查询自动化测试 @@ -86,13 +90,13 @@ public class TestTaskServiceImpl implements ITestTaskService { /** * 根据测试任务id执行测试定时任务 * @param id 测试定时任务id - * @param isImmediateRun 是否立即执行 * @param triggerType 触发方式:1-定时任务;2-手动 * @param environment 环境 - * @return 是否成功 + * @param jmeterHomePath jmeter安装路径 + * @return 是否执行完成(注:是否成功得看任务结果表) */ @Override - public boolean executeTestTaskById(Long id, boolean isImmediateRun, Integer triggerType, String environment) { + public boolean executeTestTaskById(Long id, Integer triggerType, String environment, String jmeterHomePath) { TestTask testTask = this.selectTestTaskById(id); if (testTask == null || testTask.getStatus() == null || testTask.getStatus() > 0 || "2".equals(testTask.getDelFlag())) { @@ -104,10 +108,7 @@ public class TestTaskServiceImpl implements ITestTaskService { testTaskResult.setTriggerTime(DateUtils.getNowDate()); testTaskResult.setTriggerType(triggerType); testTaskResult.setEnvironment(environment); - String crontab = testTask.getCrontab(); - Integer async = testTask.getAsync(); - Integer retry = testTask.getRetry(); - Long retryCount = testTask.getRetryCount(); + // 测试步骤总数 int caseStepCount = 0; // 查询关联的测试用例列表 List testTaskCaseList = testTaskCaseMapper.selectTestTaskCaseListByTaskId(id); @@ -122,19 +123,18 @@ public class TestTaskServiceImpl implements ITestTaskService { caseStepCount += testCaseStepMapper.selectTestCaseStepList(testCaseStep).size(); } } + // 用例总数 int caseCount = testCaseList.size(); - testTaskResult.setStartTime(DateUtils.getNowDate()); - long startTime = System.currentTimeMillis(); - // 开始执行定时任务逻辑。。。 - - testTaskResult.setStatus(1); - testTaskResult.setCostTime(System.currentTimeMillis() - startTime); testTaskResult.setCaseCount(caseCount); testTaskResult.setCaseStepCount(caseStepCount); - String result_desc = ""; - testTaskResult.setResultDesc(result_desc); - testTaskResult.setCreateTime(DateUtils.getNowDate()); - testTaskResultMapper.insertTestTaskResult(testTaskResult); - return false; + // 开始执行定时任务逻辑。。。 + if (triggerType == 1) { + // 添加定时任务定时执行 + taskManagerService.addTask(testTask, jmeterHomePath, testTaskCaseList, testTaskResult); + } else { + // 手动立即执行 + taskManagerService.executeTaskWithTestCases(testTask, jmeterHomePath, testTaskCaseList, testTaskResult); + } + return true; } }