# ai_test_platform_visual **Repository Path**: test-dev-qa/ai_test_platform_visual ## Basic Information - **Project Name**: ai_test_platform_visual - **Description**: AI 全链路测试平台(作品集):接口/Web UI/桌面视觉/性能四类用例统一管理;大模型生成用例+契约硬闸+双模型交叉审核+脚本自愈(失败→归因→修复→人工评审);敏感数据只走本地模型;Docker 一键部署三容器实跑闭环;554 项测试全绿。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-09-14 - **Last Updated**: 2026-09-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AI 全链路测试平台 > 从 0 到 1 搭建的 AI 测试平台,**本仓库承载平台全部代码**:统一管理接口 / Web UI / QT 桌面端 / 性能四类测试,引入 AI 做用例生成、脚本生成、失败分析(含性能 AI 归因)。 > > 当前真实落地进度(作品集以「真实现 + 诚实标注」为准): > - **QT 视觉执行器(已完成,真实现)**:不依赖控件树、不依赖图像标注,通过「截图 → 识别 → 操作」闭环在真实 Windows 窗口上执行 UI 自动化,全程留截图/录像证据。 > - **接口执行器(已完成,真实现)**:多步骤链式 HTTP 请求 + 四类断言(status/header/body/body_contains),worker 已按 `case.type` 分派,与视觉用例共用同一套任务闭环。 > - **平台(已完成)**:FastAPI 认证(JWT + users 表,20 项契约测试)+ 执行机注册/心跳/轮询拉任务 + 报告中心/追溯中心接真实数据 + 前端 Vue3 自研设计系统(Element Plus 已彻底移除)。 > - **测试套件 A4(已完成)**:多条用例打包一键执行 + 「N 条过了 M 条」汇总报告——套件/执行记录两张表 + suites 路由(CRUD/一键执行/汇总)+ 前端套件管理页,纯加法不碰用例与执行器。 > - **接口用例前端表单化(已完成)**:请求行 / Headers / Body / 提取变量 / 断言五块表单编辑接口用例,编辑态与执行器 steps 契约互转。 > - **环境变量 A5(已完成)**:environments 表 + 环境管理页 + 接口用例执行前选环境——建任务时把 base_url/环境变量注入快照,变量三层(环境 > 用例 > 提取)全部落地,执行器零改动。 > - **Web UI 执行器(已完成,真实现)**:Playwright 驱动浏览器执行「打开页面 → 操作 → 断言」(navigate/click/fill/wait/assert_title/assert_text/assert_visible 七动作 + 五比较符 + `{{变量}}` 渲染 + 每步截图),worker 按 `case.type` 分派,用本项目真实前端登录页跑通端到端。 > - **接口 AI 生成 B1(已完成,真实现)**:接口用例「一句自然语言 → 可执行 steps」——真实 DeepSeek 调用 + 契约硬闸(结构/枚举/引用/有界四类)+ 有界重试 + 混合检索 few-shot + gen_traces 观测落库;产物强制 source=ai + 待确认(人工逐条核对才可执行),冻结回归集 20 条真实基线关键点 100%。 > - **检索升级 B2(已完成)**:多级检索落地——BM25(稀疏) + 本地 BGE-M3 embedding(稠密) 双路 RRF 融合,带相关性闸(绝不硬凑无关示例)与降级留痕;复用识别用它盘活了「标题死匹配」问题(一条已确认用例语义命中已有用例 → 仅提示不造重复);**向量存库**:用例确认时后台任务用独立 session 异步生成 doc_text 向量落库(web_generator 维度供检索直接复用,query 之外候选零 encode)。 > - **脚本自愈 C(已完成,真实现)**:执行失败 → 归因分类(环境 / 脚本错 / 元素失效 / 未知,纯规则不调 LLM)→ 修复建议(DeepSeek 生成 A + 千问审核 B,复用 B2 双模型)→ 人工评审生效(apply / reject,绝不自动改断言骗过自己);额度 2 轮封顶、未配 key 的 service_down 不占额度、Web 空快照直接 not_healable 引导先录控件、Web selector 封闭集 = 快照 ∪ 原用例已用 selector(防过期快照误杀未改动步骤);观测三指标(修复采纳率 / 各归因类别采纳率 / 自愈成功率)。**视觉自愈已接入(2026-09-09)**:qt_visual 失败按消息形态归因(定位失败/assert 未命中 → 元素失效可换图、窗口不在前台 → 环境问题、标题断言/按键名 → 脚本错、其余异常 → 未知),修复 target 封闭集 = variables 定位图清单 ∪ 原用例已用 target(幻影定位图拒)、纯 OCR 文字定位(text,无需定位图)已放行但依赖执行机装 RapidOCR、空清单直接 not_healable 引导先录制、修复不接云端审核(前端落「待人工复核」,与 B3 生成同口径)。 > - **性能压测执行器(已完成,真实现)**:自研 `PerfRunner`(不用 JMeter/Locust——.jmx 与平台用例是两套真相,无法复用已有 runner 的步骤语义),并发单位是「事务」(一条源用例=一个事务,多条=事务链按 `source.case_ids` 语义顺序),每 VU 一线程 + 阶梯加压 ramp_seconds;**跨用例变量「链内传递、链间隔离」**(上游 exports → 下游 seed_vars,作用域=每 VU 每轮独立,绝不共享字典);指标口径 TPS(1s 滑动窗口峰值)/ 平均 RT(仅参考)/ P95·P99(最近秩法)/ 错误率(含断言)/ 峰值并发,另采样「压测机自身 CPU(参考值)」但不采集被压端资源;判定三态(全达标 passed / 任一超阈值 failed / 服务不可达或压测机 CPU≥95% → skipped,绝不假 FAIL)+ 压测执行页 `/cases/:id/perf`(KPI 六卡 + SVG 曲线 + 阈值判定表 + 「试运行一次」)+ 试跑三条出口(报告中心打「试跑」标签可隐藏 / 列表「上次结果」只取非 trial / 试跑报告禁用转缺陷 400)。 > - **边界诚实声明**:performance 的压测执行器已落地(P0-2/P0-5),性能 AI 生成(P1-1)也已落地(2026-09-11:`/api/ai/generate` 新增 performance 分支——自然语言 → 压测场景 `{driver, source, load, thresholds}` 单对象,契约硬闸 `validate_performance_steps` 复用同一函数 + 幻影 case_id 闸(候选清单由后端查库组装「全部 reviewed 接口/Web 用例」)+ few-shot(历史 performance 用例,无则退骨架)+ 产物强制 source=ai + 待确认 + `gen_traces` 溯源(prompt_ver=performance_generate_v1);真实 DeepSeek 调用与本地敏感路径双通道齐备,6 项端点测试锁定);性能 AI 归因(P1-2,`perf_analyses` 表)也已落地(2026-09-11:五类确定性归因 `capacity`/`target_bottleneck`/`source_bug`/`loadgen_limit`/`unknown` 规则优先、LLM 兜底 + 归因建议卡 + 敏感口径只喂指标/错误分类/阶段(步骤原文与变量值一律不喂)走本地 + 转缺陷出口 `source_type=perf`;与自愈分表、性能不产 `revised_steps` 故无 apply/reject,归因幂等,18 项归因端点测试 + 4 项 perf 转缺陷端点测试锁定;前端归因卡已接线——PerfRunView 失败报告内发起归因 → 五类结论 + 建议卡 → 三条出口,trial 报告转缺陷前端禁用 + 后端 400 双保险);`driver=llm`(大模型压测 profile)也已在 P2-3 落地(2026-09-11:同一个 `PerfRunner` 加一个 `driver` 维度——恒为流式、`stream` 不做字段,TTFT/TPOT/tokens·s⁻¹ 口径 + `min_tokens_per_sec` 阈值方向为 ≥,脚本源复用 interface 用例请求体、零新增表列;诚实边界=单机压 LLM 瓶颈常在客户端/网络、定位「多模型横向对比 + 配置回归」不是 GPU 容量规划);且它的定位是「功能脚本快速冒烟压测 + 容量趋势回归」,受 Python GIL / 单机端口与文件句柄 / 浏览器实例数限制,并发能力弱于 JMeter/Locust,不是专业压测工具的替代品;视觉 AI 生成(B3)已落地且真模型端到端已闭环(2026-09-09:契约闸 target ∈ 定位图清单(或纯 OCR 文字定位 text,无需定位图、依赖执行机装 RapidOCR) + 生成器 + 端点分发 + 前端入口齐了;真实 DeepSeek 生成「launch notepad」与「click template:清单内定位图」两轮实测通过、trace 落库 outcome=generated,见「质量保障」);敏感分级 + 本地模型已落地(sensitive 请求走本地 Ollama、数据不出机器,本地未就绪明确 400 拒绝,见「核心特性」);Web AI 生成与双模型交叉审核(Review Model B——DeepSeek 生成 + 千问 Qwen 独立复核)已落地,敏感路径不接云端审核(少一道质量眼,人工复核兜底);Web 自愈的 selector 来源是用例落库的存量 ui_controls 快照(非现场重爬),页面改版后旧快照可能本就陈旧。 > > A from-scratch AI full-chain test platform. This repo hosts the whole platform. Four executors are landed and wired into the same task loop: the QT visual executor (screenshot → recognize → act, verified on real Windows windows), the interface executor (multi-step HTTP + assertions), the Web UI executor (Playwright-driven browser automation), and the performance executor (self-built PerfRunner: threaded ramp-up load, per-VU variable isolation, TPS / P95 / P99 / error-rate metrics and three-state threshold verdicts). AI generation (interface / Web / visual / performance) and self-healing are also landed, and performance AI attribution (deterministic five-category classification with an LLM fallback, plus a defect hand-off) is in place and wired into the perf run page (triggered from a failed report, rendering the category / reason / suggestion card and the three human exits); the `driver=llm` load profile has also landed (streaming chat/completions with TTFT / TPOT / tokens-per-second metrics and an inverted `min_tokens_per_sec` threshold, reusing the same engine behind a `driver` dimension). ## ✨ 核心特性 - **三层分层降级识别**:模板匹配(OpenCV NCC + 多尺度)→ SIFT 特征点(抗缩放/光照)→ OCR 文字定位(RapidOCR 惰性加载,第三层已完整落地:低置信命中单独标 `low_confidence`,与「未找到」可区分)。每层命中都记录 `layer + score`,识别失败时输出各层分数供诊断 - **环境标准化防"假失败"**:执行前强校验分辨率/缩放/主题/色深,不匹配直接 `SKIPPED`——避免"A 机器能跑、B 机器全挂"的灵异事件 - **安全级操作保护**:点击前校验目标窗口仍在前台(防误点其他应用);残留模态对话框检测(脏状态直接 `BLOCKED` 拒绝执行);输入一律走剪贴板粘贴(绕开中文输入法劫持合成按键的坑) - **全链路留证据**:每步保存截图,失败可定位到具体步骤;识别走哪层、分数多少、耗时多少全部可追溯 - **业务结果断言**:`assert_title` 校验窗口标题变化——"动作执行成功"不等于"测试通过",业务结果必须被断言 - **接口执行器**:多步骤链式 HTTP 请求(`{{变量}}` 占位符串联步骤)+ 四类断言(状态码/响应头/响应体字段 JSONPath/整体子串)+ 五个比较符(eq/neq/contains/exists/not_empty);失败信息必带「期望 vs 实际」——为后续大模型自愈铺路 - **Web UI 执行器**:Playwright 驱动浏览器(不用 Selenium——自带浏览器管理 + auto-wait 自动等元素可交互),七动作(navigate/click/fill/wait/assert_title/assert_text/assert_visible)+ 五比较符 + `{{变量}}` 渲染 + 每步截图 + extract 提取变量(title/url/text/attr/cookie 五来源) - **Web UI 执行器健壮性**:浏览器启动失败(chromium 未装/损坏)判 `skipped` 并提示装浏览器、不崩任务;执行前服务可达预检(对首个 navigate 的 url 做 HEAD 探测,连不上判 `skipped` 不等 30s 超时);extract 敏感值打码(≥6 字符长串 → `***`,与接口执行器同一条凭证不落库红线);assert_title 拒绝 exists(标题恒在,exists 是必过绿灯) - **健壮性设计**:token 等提取变量只存执行器内存、用例只存占位符(凭证绝不落库);响应敏感头(Set-Cookie 等)不写入报告;空步骤用例判失败 - **worker 按用例类型分派执行器**:`case.type` 为 interface 走接口执行器、webui 走 WebuiRunner、performance 走 PerfRunner、否则走视觉执行器,四条真实链路共用同一套任务闭环(认领→执行→上报) - **性能压测执行器(P0-2 已落地)**:自研 `PerfRunner`——并发单位是「事务」(一条源用例=一个事务,多条=事务链按 `source.case_ids` 语义顺序),每 VU 一线程 + 阶梯加压 ramp_seconds,到点停派发但在途事务跑完;跨用例变量「链内传递、链间隔离」(上游 exports → 下游 seed_vars,每 VU 每轮独立作用域,绝不共享字典);指标 TPS(1s 滑动窗口峰值)/ 平均 RT / P95·P99(最近秩法)/ 错误率(含断言)/ 峰值并发 + 压测机自身 CPU 参考值;判定三态(全达标 passed / 任一超阈值 failed / 服务不可达或压测机 CPU≥95% → skipped,绝不假 FAIL,零请求必补记 1 错误样本防「0 请求 0 错误=假绿」);`driver=llm` 大模型压测 profile 已在 P2-3 落地(恒为流式 + TTFT/TPOT/tokens·s⁻¹ + `min_tokens_per_sec` 方向 ≥,脚本源只允许 interface) - **性能 AI 归因(P1-2 已落地,2026-09-11 测试锁定)**:failed 压测报告 → 五类确定性归因(`capacity` 只 RT 升无错误 / `target_bottleneck` 错误率随并发同步升 / `source_bug` 源用例断言在压测中失败 / `loadgen_limit` 压测机 CPU 打满或峰值并发压不上 / `unknown` 识别不了),纯规则优先(CPU 打满→loadgen → 源用例失败且非随并发升且 RT 未超→source_bug → 有错误→target_bottleneck → RT 超阈/上升且无错→capacity → 峰值 VU 不达标→loadgen),规则命中直接落 `perf_analyses`、**绝不白烧 token**,仅 `unknown` 才叫 LLM 兜底(拿不准就老实说 unknown,不伪装);产物 = 归因 + 建议卡(三出口人工闭环:`source_bug` 去修源用例 / `capacity`·`target_bottleneck` 去转缺陷 / 配置错去编辑重跑),**性能不产 `revised_steps` 故无 apply/reject,与 `heal_traces` 分表**;`source_type=perf` 转缺陷复用现有工单(试跑报告被闸 400);敏感口径 §7.4:提示词只喂指标/错误分类/阶段,步骤原文与变量值一律不喂、敏感用例走本地模型,本地未就绪 400 不落库;同任务归因幂等(`_latest` 命中直接返回);**前端归因卡已接线**(`frontend/src/api/perf.js` + PerfRunView——失败报告内发起归因 → 五类结论 + 建议卡 → 三条出口,trial 报告转缺陷前端禁用 + 后端 400 双保险,非 failed 不给归因入口,卡片明确写「不产脚本修复、无采纳/驳回」) - **接口 AI 生成(B1 已落地)**:接口用例一句自然语言生成可执行 steps——真实 DeepSeek 调用 + 契约硬闸(结构/枚举/引用/有界四类校验)+ 有界重试(网络错退避、非 JSON/坏契约降温度回炉)+ 混合检索 few-shot + gen_traces 观测落库(temperature 记最后一次实际调用、attempts 重试率、任务终态回填 exec_report_id、确认时异步生成 doc_text 向量落库供检索复用);产物强制 source=ai + 待确认,绝不静默入库;复用命中只提示不造重复用例 - **脚本自愈(C 已落地)**:失败报告 → 归因四分类(环境 / 脚本错 / 元素失效 / 未知,纯规则不调 LLM)→ 修复建议(复用 B2 双模型:DeepSeek 生成 A + 千问审核 B)→ 人工评审 apply / reject 才生效(修复版永远只进 pending_review、绝不自动写回原用例);额度 2 轮封顶、未配 key 的 service_down 不占额度、Web 空快照挡下并引导先录控件、Web selector 封闭集 = 快照 ∪ 原用例已用 selector(防过期快照误杀未改动步骤);观测三指标(修复采纳率 / 各归因类别采纳率 / 自愈成功率) - **敏感分级 + 本地模型(已落地,真机验证)**:勾「敏感内容」的请求只准走本地 Ollama(Qwen-VL 多模态,数据不出机器、零云费用),本地未就绪明确 400 拒绝、绝不静默回落云端;敏感标记持久化进用例,事后「AI 自愈」同样路由本地 + 契约闸禁明文凭证字面量(password/secret/token 字段值必须 `{{变量}}` 引用);`OLLAMA_BASE_URL / OLLAMA_MODEL / OLLAMA_TIMEOUT` 配置见 `backend/.env.example` - **评审 agent 自己也要被审(误判率 → 自动关维度,已落地)**:打分卡全量进 review_meta,人工确认时对比 raw_output 原始 steps 算出人工修改率(manual_modify_rate)随 gen_traces 落库——这就是评审的「地面真值」;逐维度对账机判 vs 人工结论(判 pass 但人改得多=漏判、判 fail 但人没改=误报),某维度样本≥5 且误判率≥50% 自动关闭该维度(从评审提示词与 verdict 推导中豁免,review_meta.disabled_dims 留痕可复盘)——判不准的维度不再反复误伤生成结果;数据经 GET /api/ai/alerts 暴露、Dashboard 监控卡展示 ## 🧪 真实验证(非玩具 Demo) 四条真机验证,全部对应仓库里可重跑的证据(docx §6.2 同源同口径): **① 纯视觉 QT 端到端(上次验证:2026-09 初,依赖本机界面)**——Windows 11 真实记事本「另存为」完整流程: ``` 用例: notepad_saveas_flow_v2 状态: PASSED [PASS] 步骤1 click layer=template score=0.9999 点击"文件"菜单 [PASS] 步骤3 click layer=feature score=1.0000 点击"另存为"(模板未过阈值,特征点层兜底命中) [PASS] 步骤5 click layer=template score=0.9972 点击文件名输入框(确保焦点) [PASS] 步骤6 type 输入 visual_test_demo.txt(剪贴板粘贴,绕开 IME) [PASS] 步骤7 press 回车保存 [PASS] 步骤9 assert_title 标题断言命中: 'visual_test_demo.txt - Notepad' 汇总: 通过 9/9 耗时 8515.7ms (文件真实生成,双重验证业务成功) ``` > 诚实边界:基准图按当时界面录制(`baselines/` + 用例 `cases/notepad_saveas_v2.json` 均入库可重跑),系统更新/主题变化后需用 `scripts/record_baseline.py` 重录再跑——录制型视觉自动化的固有前提。 **② 接口/Web/自愈真·端到端(2026-09-07,`scripts/e2e_real.py` 一次全链路跑通)**:真 DeepSeek 生成 + 千问 qwen-plus 独立审核双链路落 trace——接口生成审核 verdict=hint 并自主挑出「明文密码违反安全合规」(换脑价值);Web 生成 5 步 verdict=pass;自愈两个真实脚本 bug 对照——C1 提取路径笔误复验 failed(诚实展示「自愈不保证 100% 灵、靠复验闸兜底」)、C2 期望值笔误一次修对复验 passed。 **③ 敏感分级真机验证(2026-09-08,本机 Ollama + qwen2.5vl:7b)**:sensitive=true → 200 本地生成、trace 记 `provider_a=local / cost_a=0`、不接云端审核;停掉 Ollama → 400「本地模型服务未就绪」且不建 trace;重启 → 恢复生成(模型热加载秒回)。 **④ OCR 第三层真机验证(2026-09-08)**:真实 RapidOCR 冒烟——合成"登录"图命中 score=1.0、坐标误差实测 3.2px(测试锁上限 <20px;文档不写比测试更紧的承诺,防 OCR 退化时测试还绿、文档先变假话)。 ## 📁 目录结构 ``` ├── executor/ # 执行端核心(纯 Python,无平台绑定) │ ├── visual_engine.py # 三层降级识别引擎(视觉执行器) │ ├── interface_runner.py # 接口执行器(多步骤 HTTP + 四类断言,独立 InterfaceRunner 类) │ ├── web_runner.py # Web UI 执行器(Playwright 七动作 + 断言,独立 WebuiRunner 类) │ ├── perf_runner.py # 性能压测执行器(独立 PerfRunner 类:线程池阶梯加压 + 链级变量隔离 + 阈值判定三态;按 driver 分派 http(TPS/P95/P99/错误率)或 llm(流式读 + TTFT/TPOT/tokens·s⁻¹)) │ ├── contracts.py # 执行契约上限常量(VU_MAX/DURATION_MAX/DRIVERS/两组阈值键,接口·Web·性能共用) │ ├── screen.py # 窗口定位/截图/坐标换算(Win32 + mss) │ ├── operator.py # 键鼠操作封装(剪贴板输入/前台安全闸/右键) │ ├── env_check.py # 环境指纹采集与强校验 │ ├── runner.py # 视觉执行状态机(自检→定位→脏检测→步骤→报告) │ ├── worker.py # 常驻守护进程(注册/心跳/轮询拉任务/按 type 分派执行器/上报) │ ├── remote.py # 远控通道(画面反显 + 命令下行 + 打开程序) │ ├── program_scan.py # 本机程序扫描(开始菜单/App Paths 合并去重) │ ├── llm/ # 大模型生成管线(B1/B2 生成 + C 自愈:client/schema/retrieve/interface_generator/web_generator/heal_generator/reviewer/prompts/trace) │ └── agent.py # CLI 入口 ├── backend/ # 平台后端(FastAPI) │ ├── app/ # 认证、用例、任务、报告、追溯、节点、模块树 │ └── tests/ # 契约测试 ├── frontend/ # 平台前端(Vue3 + 自研设计系统,Element Plus 已移除) │ └── src/ # 登录/用例管理/录制工作台/报告/追溯/仪表盘/远控/压测执行页(/cases/:id/perf) ├── cases/ # 用例(JSON 声明式) │ ├── interface_demo.json # 接口执行器最小演示用例 │ └── webui_demo.json # Web UI 执行器演示用例(真实前端登录页表单交互) ├── baselines/ # 基准图库(版本化资产,含 .json 元数据 sidecar) ├── eval/ # 冻结回归集(20 条真实 DeepSeek 基线 + run_regression.py,关键点 100%) ├── docs/ # 需求文档 / 原型 / 从0到1全链路记录 / 应聘者视角文档 └── scripts/ # 基准图录制 / 自测 / Word 应聘文档生成 ``` ## 🚀 快速开始 ```bash pip install -r requirements.txt # Web UI 执行器需要配套浏览器(Playwright 自带浏览器管理,一条命令拉好 chromium)。 # 默认从 playwright 官方 CDN 下载,国内网络常卡死;卡住时加镜像: # set PLAYWRIGHT_DOWNLOAD_HOST=https://registry.npmmirror.com/-/binary/playwright python -m playwright install chromium ``` > **平台模式(跑起完整产品)**: > 1. 后端:`cd backend && pip install -r requirements.txt && python -m alembic upgrade head && python -m uvicorn app.main:app --port 8000`(`backend/seed_admin.py` 幂等创建管理员 alice/alice123;`OLLAMA_*` 等环境变量见 `backend/.env.example`) > 2. 前端:`cd frontend && npm install && npm run dev` → http://localhost:5173(/api 代理到 8000,免 CORS) > 3. 执行机(可选,视觉/接口/Web 三类型执行都靠它):`python -m executor.worker` > 4. 登录后建模块 → 建用例 → 确认 → 建任务,看「任务 → 执行机认领 → 报告/追溯」完整闭环 > **容器化一键部署(阶段二 —— Docker,PostgreSQL + 前后端一条命令拉起)**: > ```bash > cp .env.example .env > # 必填 SECRET_KEY(随机长串);DEEPSEEK_API_KEY / REVIEW_API_KEY 也要非空——production > # 守卫要求三者都必须注入才允许 backend 启动。只想看平台界面时可临时用占位串,对应 > # 生成/审核端点会走 service_down 优雅降级(不会崩),配好真 key 后重启即恢复。 > docker compose up -d --build # db(postgres) + backend(FastAPI) + frontend(nginx) > ``` > 前端 http://localhost:5173,后端 http://localhost:8000,`/api`(含 WebSocket) 由 Nginx 反代。数据层 PostgreSQL 挂卷持久化,后端启动自动 `alembic upgrade head` 建表。 > > 诚实边界(Docker 形态 vs 本机形态的差异,绝不把"规划当已做"): > - 执行机(视觉/OCR/浏览器 GUI)**不进容器**——pyautogui/cv2/Playwright 需本机界面栈,仍在宿主机跑 `python -m executor.worker` 连平台;容器只跑「用例管理 + AI 生成 + 自愈编排」。 > - BGE-M3 语义复用依赖 sentence-transformers/torch(重),默认**不打包进后端镜像**,容器内触发生成并发的语义检索会走降级;需要完整语义检索可自行把该依赖追加进 backend/Dockerfile。 > - Ollama 底座默认经 `host.docker.internal:11434` 连宿主机(Windows/Mac Desktop);Linux 需 `extra_hosts` 或改用宿主机 IP,按 OLLAMA_BASE_URL 覆盖。 > - ⚠️ Docker 首次实跑已闭环(2026-09-10,本机 Docker Desktop 4.90 + WSL2 + 国内镜像加速):`compose up` 三容器全绿——db(PostgreSQL16) healthy、backend 迁移成功监听 8000、frontend(nginx) 5173;端到端冒烟(注册→登录→查用例→查缺陷)全通。途中修了 3 个本机 SQLite 测不出的真 bug:迁移默认值 `sa.text("0")`→`sa.false()`(PG 跨方言)、requirements 补 requests/playwright(顶层 import,缺了容器启动即崩)——教训是「镜像只装 requirements,本机全局环境藏依赖」= 容器启动即崩的隐形雷。数据持久化在 pgdata 卷,`docker compose up -d` 可随时重启拉起。 > **持续集成(阶段二 —— CI/CD,GitHub Actions 全量回归)**: > 工作流已就位 `.github/workflows/ci.yml`:push 到 main / 发起 PR → 在 `windows-latest` 云端干净环境重跑全量 `pytest`(backend + executor,含 `import pyautogui/cv2` 的对账与视觉测试)。由于 Actions 只在 GitHub 触发,而仓库 `origin` 目前在 Gitee,需先把仓库镜像推到一个 GitHub 私有仓: > ```bash > git remote add github https://github.com/<你的账号>/<镜像仓>.git > git push github main # 推送即触发 Actions 全量回归 > ``` > 诚实边界:GitHub 直连不通(gh auth 超时)目前登录不了,云端 Actions **尚无真实触发记录**;Gitee 流水线(Gitee Go)自 2022 年起已暂停个人用户开通,同样不可用。等效替代已落地——pre-push 钩子(**可分发**:脚本已入仓 `scripts/git-hooks/pre-push`,clone 后 `cp scripts/git-hooks/pre-push .git/hooks/pre-push` 即装,换台机器也有这道闸):每次 `git push`(推 Gitee)前自动从仓库根跑全量 `python -m pytest`(702 项),全绿放行、红了拦截推送,2026-09-10 已两次实测触发(push b60a5b4..834bcbd、834bcbd..7296758 均通过)。另一处如实差异——CI 不安装 rapidocr,OCR 冒烟用例走 `pytest.skip`(仍绿、计数 -1),本机装了才凑满全 702。 # 1. 跑自测(无需 GUI,合成图 + mock) python scripts/self_test.py # 2. 录制基准图:打开记事本,框选一个控件(如"文件"菜单) python scripts/record_baseline.py my_button # 瞬时控件(下拉菜单)用延时模式: python scripts/record_baseline.py menu_item --delay=3 # 3. 编写用例 JSON(参考 cases/notepad_saveas_v2.json) # 4. 执行(真实操作鼠标键盘,期间勿碰) python -m executor.agent --case cases/notepad_saveas_v2.json ``` > ⚠️ 环境要求:Windows(依赖 Win32 API);用例的 `environment` 字段需与执行机器一致(分辨率/缩放),否则会被环境校验拦截——这是设计行为,不是 bug。 ## 🏗 架构与设计决策 | 决策 | 理由 | |------|------| | 纯视觉而非控件树(UIA/pywinauto) | 跨应用、不怕无障碍接口/自绘控件;代价是识别可靠性,用"分层降级+环境标准化+全链路证据"工程化弥补 | | 识别结果统一 `MatchResult` 结构 | 上层只拆一个盒子;新增识别层不影响调用方;`layer/score` 为数据驱动调优留口 | | 基准图与识别同源截图管线 | 150% 缩放下通用截图工具截逻辑像素、执行端截物理像素,尺寸差 1.5 倍直接匹配失败 | | 输入走剪贴板而非模拟按键 | 中文输入法会拦截模拟按键进入合成状态,Enter 被用于"上屏候选词"而非触发按钮 | | 点击前校验前台窗口 | 测试工具误操作真实软件是安全问题;宁可失败不盲点 | ## 📊 质量保障 - 11 项自测全过(识别正/负例、降级链、坐标换算、BGR 通道序、环境自检;OCR 兜底断言已随 RapidOCR 落地同步更新) - 锁定测试防回归:OCR 三层降级链(test_visual_engine 13 项,含真实 RapidOCR 冒烟——合成"登录"图命中 score=1.0、坐标误差 <20px)+ 截图通道反转 + 操作副作用 + 录制工具质量预检 + 状态机场景断言 - 后端契约测试 + executor 单元测试全绿(内存库 + dependency_overrides 隔离,不碰真实库;假对象驱动,不真开浏览器、不真打大模型 API) - 一条命令全量回归:根目录 `pytest`(pytest.ini 已配置 testpaths + pythonpath,同时收 backend/tests 与 executor)共 **702 项全绿**(backend 契约 344 + executor 单元 358;2026-09-13 实测分项——含 B3 视觉 39 项:visual_schema 23 + visual_generator 11 + 端点 5;BGE-M3 离线加载策略 3 项:缓存命中走 local_files_only、缓存缺失回退联网、自定义模型名透传;视觉自愈 19 项:executor 归因 9 + 修复生成器 7 + 后端端点 3;缺陷工单 19 项:报告建缺陷 / heal 建缺陷 / perf 建缺陷 / 关键字·状态·来源过滤 / 无来源 422 / 改不存在 404 / 状态非法 422 / 来源绑定校验 / perf 转缺陷 trial 闸 400 / perf 来源绑定校验 422 / perf 分析不存在 404 / 纯空格标题兜底 / LIKE 转义 / 试跑报告转缺陷 400 / 正式报告 trial=false 仍可转;性能压测 28 项:链内变量传递 / 链间隔离 / 判定三态 / 结构性不满足 blocked / 链级打码 / 指标算法 / 时序采样落证据文件 / 流式读逐 chunk 计时(TTFT/TPOT 非零)/ usage 优先取 completion_tokens 且缺失按 chunk 估算并标 `tokens_estimated` / `min_tokens_per_sec` 方向 ≥ / reached 语义(连不上判 skipped、渲染失败计入错误率)/ 畸形 SSE 行不炸 VU 线程(list、null、choices 非 list 均落单条失败样本而非线程消失);性能契约 33 项:performance 场景 schema 与上限校验 + `driver` 分叉(`driver=llm` 只允许 interface 源、Web 源被拒、未知 driver 直接拒、顶层键封闭集不收 `stream`);性能 AI 生成 6 项:成功闭环(dict 产物 + prompt 版本分组)/ 幻影 case_id 拒绝 / 无候选前置拒绝 / 未配 key 降级 / 敏感走本地 / 上下文装载筛选;性能 AI 归因 18 项:鉴权 / 任务·报告校验与 passed 拒绝 400 / 五类规则命中(provider=rule、token=0)/ 同任务幂等命中 / unknown 无 key 兜底 unknown / unknown LLM 生成与非法产物回退 unknown / 敏感本地未就绪 400 不落库 / 敏感本地生成 / 敏感规则命中不调模型 / §7.4 白名单不泄步骤原文与变量值 / 归因列表查询与任务不存在 404;性能归因前端接线:failed 报告只读拉历史归因 + 发起归因 → 归因卡 + 建议卡 + 转缺陷入口,trial 转缺陷禁用,随 npm run build 通过) - 多轮代码 review 累计修复 80+ 条问题(含 Docker 实跑 + 阶段二专项 review 8 类:CI 依赖漏抄、密钥入镜像层、缺陷来源张冠李戴、敏感输入泄出报告等),每条配"发现→判断→修复→锁定→沉淀"闭环 ## 🗺 Roadmap - [x] 后端平台化:FastAPI 认证骨架(JWT + users 表 + 生产守卫) - [x] 用例管理:用例 CRUD + 模块树(文件夹)+ 拖拽移动 + 批量删除 - [x] 执行闭环:执行机注册/心跳/轮询拉任务/按类型分派/回报结果 - [x] QT 视觉执行器(真实现) - [x] 接口执行器(真实现:多步骤 HTTP + 四类断言) - [x] 报告中心 / 追溯中心 接真实数据(步骤证据截图回放 + 视频) - [x] 前端自研设计系统(Element Plus 彻底移除) - [x] 接口执行器增量:`{{变量}}` 占位符替换、extract 提取、重试退避、服务可达预检 - [x] 测试套件(批量执行 + 汇总报告,A4 阶段) - [x] 接口用例前端表单化(请求五块表单编辑,与执行器 steps 契约互转) - [x] 环境变量(environments 表 + 注入快照,变量三层全部落地,A5 阶段) - [x] Web UI 执行器(Playwright 七动作 + 断言 + `{{变量}}` + 每步截图;WebStepEditor 前端表单化) - [x] Web UI 执行器健壮性 + extract(提取变量五来源 + 敏感值打码 + 服务可达预检/浏览器启动失败判 skipped + 用例变量名全链路白名单) - [x] 接口 AI 生成(B1:自然语言 → 接口 steps,契约硬闸 + 待确认 + gen_traces 观测 + 冻结回归集,真实 DeepSeek) - [x] 检索升级(B2:BM25 + BGE-M3 双路 RRF 混合检索 + 相关性闸 + 降级留痕 + 语义复用防重 + 确认时异步向量存库) - [x] 向量存库接线(B2:gen_embedding 三列落库 + query 外候选零 encode) - [x] Web UI AI 生成(B2:自然语言 → Web 七动作序列,契约硬闸 + 幻影 selector 闸 + AI 来源溯源;控件清单从真实页面收集——/api/webui/controls 用 Playwright 抓 DOM 生成唯一 CSS selector,替代演示 mock) - [x] 双模型交叉审核(B2:真·双模型——DeepSeek 生成 + 千问 Qwen 独立复核,scorecard 过闸 + b_failed 不阻塞 + A/B 各记一套 token/cost;未配审核 key 明确不审、绝不回退自审) - [x] 脚本自愈(失败分析 + 归因分类 + 修复建议 + 人工评审闸,绝不自动改断言骗过自己) - [x] 性能压测执行器(P0-2:自研 PerfRunner——线程池阶梯加压 + 链级变量隔离 + TPS/P95/P99/错误率 + 阈值判定三态,2026-09-10 测试锁定) - [x] 压测执行页与试跑三出口(P0-5:`/cases/:id/perf` KPI 六卡 + SVG 曲线 + 阈值判定表 + 试运行/停止;试跑报告禁用转缺陷 400,2026-09-10) - [x] 性能 AI 生成(P1-1:自然语言 → 压测场景 `{driver, source, load, thresholds}`,契约硬闸 + 幻影 case_id 闸 + 待确认 + `gen_traces` 溯源,与接口/Web/视觉同一 AI 基建;2026-09-11 测试锁定) - [x] 性能 AI 归因(P1-2:failed 报告 → 五类确定性归因(规则优先、LLM 只兜 unknown)+ 归因建议卡 + 敏感口径 §7.4 只喂指标/走本地 + `source_type=perf` 转缺陷出口 + 同任务幂等;与自愈分表、不产 `revised_steps` 无 apply/reject + **前端归因卡已接线**(失败报告内发起归因/五类展示/三出口,trial 转缺陷禁用),2026-09-11 测试锁定) - [x] 压测进套件 + 报告中心接线(P2-1:测试套件页新增「性能套件」Tab,套件可按 `type=performance` 建/跑并把环境注入其引用的脚本源用例(P2-4 起含 interface/Web 源,夜间容量回归);套件汇总报告里性能用例给「查看压测报告」直达 `/cases/:id/perf`;报告中心新增压测报告回看——阈值判定表 + 指标网格 + 时序证据 + 跳执行页;`trial` 试跑报告禁用转缺陷(前端禁用 + 后端 report/perf 双入口 400),2026-09-11 测试锁定) - [x] 大模型压测 profile(P2-3:同一个 `PerfRunner` 加 `driver` 维度——恒为流式、`stream` 不做字段,TTFT/TPOT/tokens·s⁻¹ 口径 + `min_tokens_per_sec` 方向 ≥,脚本源只允许 interface(prompt 写在请求体)、webui 源被契约闸拒;token 缺失按 chunk 估算并在 summary 标 `tokens_estimated`;执行页按 driver 切 KPI 卡/曲线/判定表,2026-09-11 测试锁定) - [x] 压测机能力上报(P2-2:`ExecutorNode.capabilities` 承载执行机注册/心跳上报的 `{max_vu,max_duration_seconds}`(环境变量优先、缺省按 CPU 核数估算 VU,入口用 ceiling 夹一次防"自报天文数字架空闸");`resolve_perf_limits` 解析生效上限——建用例按平台保守默认(200 VU/1800s)、建任务按目标执行机能力再卡一次,超限 **422 即拒**(不让它跑到执行机才失败);闸的判定规则一行没改,只换"比较的上限值"的来源;执行机管理页展示各节点上限、压测执行页明示所选机器上限并提前高亮超限,2026-09-11 测试锁定) - [x] webui 环境注入统一放开(P2-4:压测场景引用 webui 源时同样注入环境变量/`{{base_url}}`(webui 执行器本支持 `{{变量}}` 渲染),与 interface 源同一口径;**仅放开压测内的 webui 源**——webui 用例单独执行传 `environment_id` 仍 400,现有行为不变,2026-09-11 测试锁定) - [x] OCR 层接入(RapidOCR 第三层:惰性加载 + 三层降级闭环 + 低置信诊断,2026-09-08 测试锁定 + 真机验证) - [x] 敏感分级 + 本地模型(Ollama + Qwen-VL:sensitive 请求本地处理数据不出机器,生成/自愈双入口红线 + 契约闸凭证规则,2026-09-08 review 收口) ## License MIT