自动化测试定时任务
This commit is contained in:
@@ -15,6 +15,7 @@ import com.test.test.domain.qo.IDQO;
|
||||
import com.test.test.service.ITestTaskLogService;
|
||||
import com.test.test.service.ITestTaskResultService;
|
||||
import com.test.test.service.ITestTaskService;
|
||||
import com.test.test.task.TestTaskManager;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -42,6 +43,9 @@ public class TestTaskController extends BaseController {
|
||||
@Resource
|
||||
private ITestTaskLogService taskLogService;
|
||||
|
||||
@Resource
|
||||
private TestTaskManager testTaskManager;
|
||||
|
||||
/**
|
||||
* 查询定时任务列表
|
||||
*/
|
||||
@@ -90,9 +94,20 @@ public class TestTaskController extends BaseController {
|
||||
@Log(title = "定时任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
public AjaxResult add(@RequestBody TestTask testTask) {
|
||||
try {
|
||||
testTask.setCreateBy(getLoginUser().getUsername());
|
||||
testTask.setCreateTime(DateUtils.getNowDate());
|
||||
return toAjax(testTaskService.insertTestTask(testTask));
|
||||
int result = testTaskService.insertTestTask(testTask);
|
||||
|
||||
// 如果任务状态是启用且没有被删除,则添加到定时任务管理器
|
||||
if (testTask.getStatus() == 0 && "0".equals(testTask.getDelFlag())) {
|
||||
testTaskManager.addNewTask(testTask);
|
||||
}
|
||||
|
||||
return toAjax(result);
|
||||
} catch (Exception e) {
|
||||
return error("新增失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +116,23 @@ public class TestTaskController extends BaseController {
|
||||
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
public AjaxResult edit(@RequestBody TestTask testTask) {
|
||||
return toAjax(testTaskService.updateTestTask(testTask));
|
||||
try {
|
||||
// 获取原任务信息
|
||||
TestTask originalTask = testTaskService.selectTestTaskById(testTask.getId()).getTask();
|
||||
|
||||
// 更新任务
|
||||
int result = testTaskService.updateTestTask(testTask);
|
||||
|
||||
// 如果状态或crontab发生变化,更新定时任务
|
||||
if (testTask.getStatus() != originalTask.getStatus() ||
|
||||
!testTask.getCrontab().equals(originalTask.getCrontab())) {
|
||||
testTaskManager.updateTask(testTask);
|
||||
}
|
||||
|
||||
return toAjax(result);
|
||||
} catch (Exception e) {
|
||||
return error("修改失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +141,14 @@ public class TestTaskController extends BaseController {
|
||||
@Log(title = "定时任务", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/del")
|
||||
public AjaxResult remove(@RequestBody IDQO qo) {
|
||||
try {
|
||||
// 先从定时任务管理器中移除
|
||||
testTaskManager.removeTask(qo.getId());
|
||||
// 再删除数据库记录
|
||||
return toAjax(testTaskService.deleteTestTaskById(qo.getId()));
|
||||
} catch (Exception e) {
|
||||
return error("删除失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,6 +164,4 @@ public class TestTaskController extends BaseController {
|
||||
});
|
||||
return toAjax(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -102,14 +102,40 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
|
||||
// 配置 ChromeOptions
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
options.addArguments("--headless");
|
||||
// 基本设置
|
||||
options.addArguments("--headless=new"); // 使用新的无头模式
|
||||
options.addArguments("--no-sandbox");
|
||||
options.addArguments("--disable-dev-shm-usage");
|
||||
options.addArguments("--remote-allow-origins=*");
|
||||
|
||||
// 禁用各种功能以提高稳定性
|
||||
options.addArguments("--disable-gpu");
|
||||
options.addArguments("--disable-extensions");
|
||||
options.addArguments("--disable-plugins");
|
||||
options.addArguments("--disable-software-rasterizer");
|
||||
options.addArguments("--disable-browser-side-navigation");
|
||||
options.addArguments("--disable-infobars");
|
||||
options.addArguments("--disable-notifications");
|
||||
|
||||
// 设置窗口大小和内存限制
|
||||
options.addArguments("--window-size=1920,1080");
|
||||
options.addArguments("--disable-dev-shm-usage");
|
||||
options.addArguments("--incognito"); // 无痕模式
|
||||
|
||||
// 添加性能和稳定性相关的参数
|
||||
options.addArguments("--disable-background-networking");
|
||||
options.addArguments("--disable-background-timer-throttling");
|
||||
options.addArguments("--disable-client-side-phishing-detection");
|
||||
options.addArguments("--disable-default-apps");
|
||||
options.addArguments("--disable-hang-monitor");
|
||||
options.addArguments("--disable-popup-blocking");
|
||||
options.addArguments("--disable-prompt-on-repost");
|
||||
options.addArguments("--disable-sync");
|
||||
options.addArguments("--metrics-recording-only");
|
||||
options.addArguments("--no-first-run");
|
||||
options.addArguments("--safebrowsing-disable-auto-update");
|
||||
options.addArguments("--password-store=basic");
|
||||
options.addArguments("--use-mock-keychain");
|
||||
|
||||
// 创建 ChromeDriver
|
||||
WebDriver driver = new ChromeDriver(options);
|
||||
|
||||
149
test-test/src/main/java/com/test/test/task/TestTaskManager.java
Normal file
149
test-test/src/main/java/com/test/test/task/TestTaskManager.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package com.test.test.task;
|
||||
|
||||
import com.test.test.domain.TestTask;
|
||||
import com.test.test.domain.qo.GroupIdQO;
|
||||
import com.test.test.service.ITestTaskService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.support.CronTrigger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
/**
|
||||
* 定时任务管理器
|
||||
* 负责调度和执行定时任务
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TestTaskManager {
|
||||
|
||||
@Resource
|
||||
private ITestTaskService testTaskService;
|
||||
|
||||
@Resource
|
||||
private TaskScheduler taskScheduler;
|
||||
|
||||
@Value("${test.jmeterHomePath:/opt/apache-jmeter}")
|
||||
private String jmeterHomePath;
|
||||
|
||||
// 用于存储正在运行的任务
|
||||
private final Map<Long, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
loadTasks(); // 初始化时加载所有启用的定时任务
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始加载所有启用的定时任务
|
||||
*/
|
||||
private void loadTasks() {
|
||||
try {
|
||||
GroupIdQO qo = new GroupIdQO();
|
||||
List<TestTask> tasks = testTaskService.selectTestTaskList(qo);
|
||||
if (tasks != null) {
|
||||
tasks.stream()
|
||||
.filter(task -> task != null
|
||||
&& task.getStatus() != null
|
||||
&& task.getStatus() == 0
|
||||
&& "0".equals(task.getDelFlag()))
|
||||
.forEach(this::scheduleTask);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("加载定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务
|
||||
*/
|
||||
public void updateTask(TestTask task) {
|
||||
log.info("更新任务 {}", task.getId());
|
||||
Long taskId = task.getId();
|
||||
|
||||
// 先取消现有任务
|
||||
if (scheduledTasks.containsKey(taskId)) {
|
||||
scheduledTasks.get(taskId).cancel(true);
|
||||
scheduledTasks.remove(taskId);
|
||||
}
|
||||
|
||||
// 如果任务状态是启用且没有被删除,则重新调度
|
||||
if (task.getStatus() == 0 && "0".equals(task.getDelFlag())) {
|
||||
log.info("启动任务:{}", task.getId());
|
||||
scheduleTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新任务到定时调度
|
||||
*/
|
||||
public void addNewTask(TestTask task) {
|
||||
// 只有当任务状态是启用且没有被删除时才创建定时任务
|
||||
if (task.getStatus() == 0 && "0".equals(task.getDelFlag())) {
|
||||
log.info("加入定时任务:{}", task.getId());
|
||||
scheduleTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除定时任务
|
||||
*/
|
||||
public void removeTask(Long taskId) {
|
||||
if (scheduledTasks.containsKey(taskId)) {
|
||||
scheduledTasks.get(taskId).cancel(true);
|
||||
scheduledTasks.remove(taskId);
|
||||
log.info("已移除定时任务: {}", taskId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量移除定时任务
|
||||
*/
|
||||
public void removeTasks(Long[] taskIds) {
|
||||
for (Long taskId : taskIds) {
|
||||
removeTask(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调度单个任务
|
||||
*/
|
||||
private void scheduleTask(TestTask task) {
|
||||
try {
|
||||
if (task.getCrontab() == null || task.getCrontab().trim().isEmpty()) {
|
||||
log.error("任务 [{}] 的cron表达式为空", task.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
CronTrigger trigger = new CronTrigger(task.getCrontab());
|
||||
ScheduledFuture<?> future = taskScheduler.schedule(
|
||||
() -> executeTask(task), trigger
|
||||
);
|
||||
scheduledTasks.put(task.getId(), future);
|
||||
log.info("成功调度任务: {}", task.getName());
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("无效的cron表达式: " + task.getCrontab(), e);
|
||||
} catch (Exception e) {
|
||||
log.error("调度任务时发生错误: " + task.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行单个任务
|
||||
*/
|
||||
private void executeTask(TestTask task) {
|
||||
try {
|
||||
log.info("开始执行任务: {}", task.getName());
|
||||
testTaskService.executeTestTaskById(task.getId(), 1, null, jmeterHomePath, "system");
|
||||
} catch (Exception e) {
|
||||
log.error("执行任务 [{}] 时发生错误", task.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,9 @@
|
||||
<select id="selectTestTaskList" parameterType="GroupIdQO" resultMap="TestTaskResult">
|
||||
<include refid="selectTestTaskVo"/>
|
||||
<where>
|
||||
<if test="groupId != null">
|
||||
group_id = #{groupId}
|
||||
</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
@@ -116,7 +116,7 @@ export default {
|
||||
},
|
||||
// 删除
|
||||
hadleClickDelete(val) {
|
||||
this.$modal.confirm('确认删除元素' + '?').then(() => {
|
||||
this.$modal.confirm('确认删除该场景' + '?').then(() => {
|
||||
deleteAutomation(val.id).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
@@ -129,13 +129,23 @@ export default {
|
||||
},
|
||||
// 查看
|
||||
handleClickDetail(val) {
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: '执行中...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
executeAutomationData({ id: val.id }).then(res => {
|
||||
loading.close();
|
||||
if (res.code === 200) {
|
||||
this.$modal.msgSuccess("执行成功");
|
||||
} else {
|
||||
this.$modal.msgSuccess("执行失败");
|
||||
this.$modal.msgError("执行失败");
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
loading.close();
|
||||
this.$modal.msgError("执行失败");
|
||||
});
|
||||
},
|
||||
// 分页
|
||||
handleSizeChange(val) {
|
||||
|
||||
Reference in New Issue
Block a user