AI 大模型接入 + 自动化测试(手动/AI/定时三种触发)
- 自动化测试核心(packages/core/src/testing.ts):
- JSONPath 求值($.a.b[0].c)、断言评估(状态码/耗时/Header/Body × 10 种操作)
- 变量提取(响应 → 当前环境,{{var}} 链式传值)、Markdown 报告导出
- 用例模型:场景用例 = 有序步骤(引用 HTTP 接口 + 断言 + 提取),失败后继续可选
- 执行器 testRunner + 定时调度器 scheduler(应用运行期间按间隔自动执行)
- TestingView:用例列表 / 步骤编排 / 断言与提取编辑器 / 报告(统计卡+断言明细+过滤+再次运行+导出)
- AI 助手:OpenAI 兼容客户端(DeepSeek/智谱/Kimi/OpenAI/Ollama 预设)
- 设置 → AI 助手:供应商 CRUD + 测试连接 + 当前使用切换
- AI 生成场景用例:读取集合接口清单 → 编排步骤/断言/提取 → 预览保存
- 入口:侧栏底部「自动化测试」+ ⋯ 菜单;文档新增 /docs/testing /docs/ai
- 新增 11 个引擎单测(总 48 前端用例全绿);本地 E2E:运行通过+断言通过+petId 提取验证
This commit is contained in:
1 parent
9a019408ab
commit
1bcd7be2ac
23 files changed
+2538
-7
No files matched your search
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 定时任务调度器:应用运行期间每 30s 巡检一次,
|
||||
* 对启用且到达间隔的用例自动执行并记录报告(trigger = schedule)。
|
||||
*/
|
||||
import { runTestCase } from "./testRunner";
|
||||
import { useWorkspace } from "./workspaceStore";
|
||||
|
||||
const TICK_MS = 30_000;
|
||||
let timer: ReturnType<typeof setInterval> | null = null;
|
||||
let running = new Set<string>();
|
||||
|
||||
function isDue(intervalMinutes: number, lastRunAt: number | null): boolean {
|
||||
const intervalMs = Math.max(1, intervalMinutes) * 60_000;
|
||||
return lastRunAt === null || Date.now() - lastRunAt >= intervalMs;
|
||||
}
|
||||
|
||||
function tick(): void {
|
||||
const { schedules } = useWorkspace.getState();
|
||||
for (const s of schedules) {
|
||||
if (!s.enabled) continue;
|
||||
if (!isDue(s.intervalMinutes, s.lastRunAt)) continue;
|
||||
if (running.has(s.caseId)) continue;
|
||||
running = new Set([...running, s.caseId]);
|
||||
void runTestCase(s.caseId, "schedule")
|
||||
.catch(() => undefined)
|
||||
.finally(() => {
|
||||
running = new Set([...running].filter((id) => id !== s.caseId));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function startScheduler(): void {
|
||||
if (timer) return;
|
||||
timer = setInterval(tick, TICK_MS);
|
||||
}
|
||||
|
||||
export function stopScheduler(): void {
|
||||
if (timer) clearInterval(timer);
|
||||
timer = null;
|
||||
}
|
||||
|
||||
/** 供 UI 显示:下次预计运行时间(ms 时间戳) */
|
||||
export function nextRunAt(intervalMinutes: number, lastRunAt: number | null): number {
|
||||
const intervalMs = Math.max(1, intervalMinutes) * 60_000;
|
||||
return (lastRunAt ?? Date.now() - intervalMs) + intervalMs;
|
||||
}
|
||||
Reference in new issue
Block a user