# autotest **Repository Path**: xpaly3000/autotest ## Basic Information - **Project Name**: autotest - **Description**: 一个能全自动录制浏览起操作,并回放的项目。集成了LLM对话,定时任务,压力测试。完全由GLM5 vibe coding开发。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-24 - **Last Updated**: 2026-06-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![输入图片说明](72adc5d1af2992f93d4969e15a492975.png) # WebAutoRecorder - Web自动化录制回放测试平台 一款零代码的 Web 自动化测试工具,支持录制用户操作、自动生成测试脚本、一键回放执行测试。 ## 功能特性 - **零代码录制** - 通过浏览器录制用户操作,自动生成测试脚本 - **智能定位** - 多策略元素定位(data-testid → id → name → text → CSS路径),支持自愈修复 - **事件合并** - 智能合并重复事件(输入防抖 800ms、点击冷却 300ms、滚动节流 500px) - **智能等待** - 综合网络空闲、DOM稳定、CSS动画完成、Loading消失等多维检测 - **可视化编辑** - 流程图形式编辑测试步骤,支持分支条件、循环控制 - **变量系统** - 三层作用域(step/session/global),支持数据提取与参数化 - **LLM集成** - 内置LLM对话节点,支持验证码/二维码识别、图像分析 - **插件系统** - 支持调用外部程序(二进制、Java、Python、JS脚本等),结果输出到变量 - **多标签页** - 自动处理多标签页场景,独立操作 - **HTML报告** - 生成详细的测试报告,包含步骤截图 - **实时通信** - WebSocket实时推送录制进度和回放状态 ## 技术栈 | 层级 | 技术 | 版本 | 用途 | |------|------|------|------| | **浏览器驱动** | Playwright | 1.40+ | CDP协议,浏览器自动化 | | **后端框架** | FastAPI | 0.100+ | 异步Web框架 | | **ORM** | SQLAlchemy | 2.0+ | 数据库ORM(异步) | | **前端框架** | Vue 3 | 3.4+ | 响应式UI | | **UI组件** | Element Plus | 2.5+ | 企业级组件库 | | **流程图** | Vue Flow | 1.48+ | 可视化流程编辑 | | **状态管理** | Pinia | 2.1+ | 全局状态管理 | | **HTTP客户端** | Axios | 1.6+ | API请求 | | **构建工具** | Vite | 5.0+ | 前端构建 | | **模板引擎** | Jinja2 | 3.0+ | HTML报告模板 | ## 快速开始 ### 环境要求 - Python 3.10+ - Node.js 18+ - Google Chrome(默认浏览器) - Chromium(通过 Playwright 安装,作为备用浏览器) > 默认使用 SQLite,无需额外安装数据库。如需 PostgreSQL/Redis,按配置文件配置即可。 ### 安装依赖 ```bash # 后端 cd backend pip install -r requirements.txt playwright install chromium # 可选备用浏览器 # 前端 cd frontend npm install ``` ### 配置 编辑 `config/settings.yaml`,按需修改配置: ```yaml app: host: "0.0.0.0" port: 8000 debug: true database: type: sqlite # sqlite 或 postgresql name: webautorecorder browser: default_browser: chrome headless: false viewport: width: 1920 height: 1080 recorder: input_debounce: 800 # 输入防抖(ms) click_cooldown: 300 # 点击冷却(ms) scroll_threshold: 500 # 滚动合并阈值(px) player: default_speed: normal # slow / normal / fast retry_count: 2 # 失败重试次数 screenshot: on_fail # always / on_fail / never step_delay: 500 # 步骤间延迟(ms) waiter: network_idle_timeout: 10000 # 网络空闲等待(ms) dom_stable_timeout: 5000 # DOM稳定等待(ms) animation_timeout: 5000 # 动画完成等待(ms) llm: api_base: http://localhost:8080/v1 api_key: "" model: Qwen3.5-4B-Q3_K_M timeout: 30000 storage: cases_dir: data/cases reports_dir: data/reports screenshots_dir: screenshots ``` ### 启动服务 **方式一:交互式启动脚本(推荐)** ```bash python start.py ``` 提供菜单选择启动/停止前端和后端服务。 **方式二:手动启动** ```bash # 后端(端口 8000) cd backend python -m app.main # 前端(端口 3000) cd frontend npm run dev ``` 访问 http://localhost:3000 开始使用。 --- ## 页面导航 | 路径 | 页面 | 功能 | |------|------|------| | `/cases` | 用例管理 | 创建、编辑、导入导出、批量执行测试用例 | | `/recorder` | 录制 | 启动浏览器录制用户操作,实时生成测试步骤 | | `/player` | 回放 | 执行测试用例,实时显示进度和结果 | | `/reports` | 报告 | 查看历史测试报告,统计摘要 | | `/settings/llm` | LLM设置 | 配置LLM模型(API地址、密钥、模型名称) | | `/llm-logs` | LLM日志 | 查看LLM调用历史和统计 | | `/plugins` | 插件管理 | 管理外部程序插件 | --- ## 支持的动作类型 ### 基础动作 | 动作 | 说明 | 配置项 | |------|------|--------| | `open` | 打开页面 | URL | | `click` | 点击元素 | CSS选择器 | | `input` | 输入文本 | 选择器 + 输入值 | | `select` | 下拉选择 | 选择器 + 选项值 | | `wait` | 等待 | 超时时间(秒) | | `hover` | 悬停元素 | CSS选择器 | | `scroll` | 滚动页面 | 坐标偏移 | | `press` | 按键 | 按键名(Enter、Tab等) | ### 数据处理 | 动作 | 说明 | 配置项 | |------|------|--------| | `extract` | 提取元素数据到变量 | 选择器 + 提取类型(text/html/attribute/value/image) + 变量名 + 后置处理器 | ### 验证动作 | 动作 | 说明 | 配置项 | |------|------|--------| | `assert` | 断言验证 | 选择器 + 断言类型 + 期望值 | | `assert_output` | 断言并输出到变量 | 同上 + 变量名 | | `screenshot` | 页面截图 | - | ### 高级动作 | 动作 | 说明 | 配置项 | |------|------|--------| | `execute_script` | 执行JS脚本 | JavaScript代码 + 输出变量 | | `llm_chat` | LLM对话 | 提示词 + 图片来源 + 输出变量 | | `get_screenshot` | 获取元素截图 | 选择器 + 输出变量 | | `custom_action` | 自定义动作 | 处理器 + 输入/输出变量 | | `wait_input` | 等待人工输入 | 提示文本 | | `plugin` | 执行插件 | 插件选择 + 参数 + 输出变量 | --- ## 变量系统 ### 三层作用域 | 作用域 | 生命周期 | 使用场景 | |--------|---------|---------| | `step` | 当前步骤结束后清除 | 临时中转 | | `session` | 整个用例执行期间有效(默认) | 步骤间传递数据 | | `global` | 跨用例持久化 | 全局共享数据 | ### 使用方式 - **引用变量**: `${var_name}` 或 `${var_name:default_value}` - **存储变量**: 提取动作、LLM对话、插件执行等会自动存储到指定变量 - **后置处理器**: 支持正则提取、JSONPath、去空格、字符串替换 ### 典型流程 ``` 步骤1: EXTRACT → 提取商品名到 ${product_name} 步骤2: INPUT → 输入 ${product_name} 到搜索框 步骤3: LLM_CHAT → 分析 ${captcha_image},输出到 ${ocr_result} 步骤4: INPUT → 输入 ${ocr_result} 到验证码框 ``` --- ## 智能定位器 元素定位策略按优先级依次尝试: ``` 1. data-testid → [data-testid="xxx"] 2. id → #element_id 3. name → [name="xxx"] 4. placeholder → [placeholder="xxx"] 5. aria-label → [aria-label="xxx"] 6. role + name → role=button[name="xxx"] 7. text content → text="xxx" 8. parent container → .parent > .child 9. text combo → :has-text() 组合 10. index → element:nth-child(n) 11. full CSS path → body > div > ... > element ``` 定位失败时自动尝试备选策略和自愈修复。 --- ## 插件系统 插件系统支持在测试流程中调用外部程序(二进制程序、Java、Python、Node.js、Shell 脚本等),执行结果可通过变量在步骤间传递。 ### 使用流程 1. 在「插件管理」页面创建插件,配置名称、类型、参数定义 2. 上传插件文件(可执行文件、脚本等) 3. 在流程编辑器中拖入「执行插件」节点,选择插件并填写参数 4. 插件执行后,stdout 输出自动存入指定的变量,后续步骤可通过 `${变量名}` 引用 ### 命令模板 通过 `command_template` 控制如何调用插件程序,支持以下占位符: | 占位符 | 说明 | |--------|------| | `{path}` | 可执行文件绝对路径 | | `{params}` | 按参数定义自动生成的参数字符串 | | `{参数名}` | 直接引用某个参数的值 | 插件类型对应的默认命令模板: | 类型 | 默认模板 | 示例 | |------|---------|------| | 二进制 | `{path} {params}` | `./program --name "张三"` | | Java | `java -jar {path} {params}` | `java -jar app.jar --name "张三"` | | Python | `python {path} {params}` | `python script.py --name "张三"` | | Node.js | `node {path} {params}` | `node script.js --name "张三"` | | Shell | `bash {path} {params}` | `bash script.sh --name "张三"` | 支持直接引用参数值,适合位置参数与关键参数混合的场景: ``` python {path} {url} --output {output_dir} ``` ### 参数格式 通过 `args_format` 控制参数的生成格式: | 格式 | 示例 | 适用场景 | |------|------|---------| | `long_flag` | `--name "张三" --count 10` | GNU 风格(默认) | | `short_flag` | `-n "张三" -c 10` | 短横风格 | | `positional` | `"张三" 10` | 位置参数 | | `equals` | `--name="张三" --count=10` | 等号风格 | ### 参数定义 每个参数支持以下配置: | 字段 | 说明 | |------|------| | `name` | 参数标识(英文,用于命令行) | | `label` | 显示名称 | | `type` | 类型:string / integer / float / boolean / json | | `required` | 是否必填 | | `default` | 默认值 | | `value_source` | 值来源:`fixed`(固定值)或 `variable`(流程变量引用) | 当 `value_source` 为 `variable` 时,参数值支持 `${var_name}` 变量引用,执行前会自动解析为实际值。 ### 输出变量 插件执行完成后,stdout 内容自动存储到指定的输出变量中。变量作用域支持 step(步骤级)、session(会话级,推荐)、global(全局级)。 ### 插件 API | 接口 | 方法 | 说明 | |------|------|------| | `/api/plugins` | GET | 获取插件列表(分页、搜索、类型过滤) | | `/api/plugins/all` | GET | 获取所有活跃插件(流程编辑器选择用) | | `/api/plugins` | POST | 创建插件 | | `/api/plugins/{id}` | GET | 获取插件详情 | | `/api/plugins/{id}` | PUT | 更新插件 | | `/api/plugins/{id}` | DELETE | 删除插件 | | `/api/plugins/{id}/upload` | POST | 上传插件文件 | | `/api/plugins/execute` | POST | 测试执行插件 | ### 示例:创建一个 Python 插件 1. 编写 Python 脚本 `hello.py`: ```python import argparse parser = argparse.ArgumentParser() parser.add_argument("--name", required=True) parser.add_argument("--count", type=int, default=1) args = parser.parse_args() print(f"Hello {args.name}! Count: {args.count}") ``` 2. 在插件管理页面创建插件: - 名称:`打招呼脚本` - 类型:Python - 命令模板:`python {path} {params}`(自动生成) - 参数格式:`long_flag`(默认) - 参数定义:`name`(必填) + `count`(整数, 默认1) - 输出变量:`greet_result` 3. 上传 `hello.py` 文件 4. 在流程中使用: - 拖入「执行插件」节点 - 选择「打招呼脚本」 - 填写参数:name = `${username}`(引用前面步骤提取的变量) - 后续步骤使用 `${greet_result}` 获取输出 --- ## 项目结构 ``` autotest/ ├── backend/ # 后端代码 (Python/FastAPI) │ ├── app/ │ │ ├── api/ # API接口层 │ │ │ ├── __init__.py # 路由注册 │ │ │ ├── cases.py # 用例管理接口 │ │ │ ├── llm_config.py # LLM配置接口 │ │ │ ├── llm_log.py # LLM日志接口 │ │ │ ├── play.py # 回放执行接口 │ │ │ ├── plugin.py # 插件管理接口 │ │ │ ├── record.py # 录制接口 │ │ │ ├── report.py # 报告接口 │ │ │ └── websocket.py # WebSocket实时通信 │ │ ├── core/ # 核心引擎层 │ │ │ ├── browser.py # 浏览器控制器 │ │ │ ├── condition_evaluator.py # 条件分支评估器 │ │ │ ├── control_flow_player.py # 分支流程播放器 │ │ │ ├── error_handler.py # 错误处理器 │ │ │ ├── event_merger.py # 事件合并器 │ │ │ ├── executor.py # 动作执行器 │ │ │ ├── extractor.py # 元素数据提取器 │ │ │ ├── generator.py # 报告生成器 │ │ │ ├── llm_chat_handler.py # LLM对话处理器 │ │ │ ├── llm_client.py # LLM API客户端 │ │ │ ├── llm_logger.py # LLM日志记录器 │ │ │ ├── locator.py # 智能元素定位器 │ │ │ ├── player.py # 回放器核心 │ │ │ ├── plugin_executor.py # 插件执行器 │ │ │ ├── recorder.py # 录制器 │ │ │ ├── script_loader.py # 注入脚本加载器 │ │ │ ├── variable_context.py # 变量上下文管理 │ │ │ ├── waiter.py # 智能等待器 │ │ │ └── processors/ # 后置处理器 │ │ │ ├── base.py # 处理器基类 │ │ │ ├── chain.py # 处理器链 │ │ │ ├── json_path.py # JSONPath处理器 │ │ │ ├── regex.py # 正则处理器 │ │ │ └── transform.py # 转换处理器 │ │ ├── models/ # 数据模型 (Pydantic) │ │ │ ├── case.py # 测试用例模型 │ │ │ ├── condition.py # 条件分支模型 │ │ │ ├── extract.py # 提取配置模型 │ │ │ ├── llm_config.py # LLM配置模型 │ │ │ ├── llm_log.py # LLM日志模型 │ │ │ ├── plugin.py # 插件数据模型 │ │ │ ├── result.py # 执行结果模型 │ │ │ └── step.py # 测试步骤模型 │ │ ├── services/ # 业务逻辑层 │ │ │ ├── base.py # 基础服务 │ │ │ ├── case_service.py # 用例服务 │ │ │ ├── play_service.py # 回放服务 │ │ │ ├── plugin_service.py # 插件服务 │ │ │ ├── record_service.py # 录制服务 │ │ │ └── report_service.py # 报告服务 │ │ ├── storage/ # 数据持久化层 │ │ │ ├── case_store.py # 用例存储 │ │ │ ├── llm_log_store.py # LLM日志存储 │ │ │ ├── plugin_store.py # 插件存储 │ │ │ └── result_store.py # 结果存储 │ │ ├── config.py # 配置管理 │ │ └── main.py # FastAPI入口 │ └── requirements.txt │ ├── frontend/ # 前端代码 (Vue 3) │ ├── src/ │ │ ├── views/ # 页面组件 │ │ │ ├── CaseList.vue # 用例管理 │ │ │ ├── Recorder.vue # 录制页面 │ │ │ ├── Player.vue # 回放页面 │ │ │ ├── Report.vue # 报告中心 │ │ │ ├── LLMSettings.vue # LLM配置 │ │ │ ├── LLMLogs.vue # LLM日志 │ │ │ └── PluginManage.vue # 插件管理 │ │ ├── components/flow/ # 流程图组件 │ │ │ ├── FlowCanvas.vue # 流程画布 │ │ │ ├── PropertyPanel.vue # 属性面板 │ │ │ ├── NodePanel.vue # 节点面板 │ │ │ ├── PlayFlowPanel.vue # 回放流程面板 │ │ │ ├── ConditionEditor.vue # 条件编辑器 │ │ │ ├── EdgeConditionEditor.vue # 边条件编辑器 │ │ │ ├── edges/ │ │ │ │ └── ConditionEdge.vue # 条件边 │ │ │ └── nodes/ │ │ │ ├── ActionNode.vue # 标准动作节点 │ │ │ ├── CustomNode.vue # 高级动作节点 │ │ │ ├── StartNode.vue # 开始节点 │ │ │ └── EndNode.vue # 结束节点 │ │ ├── api/index.js # API封装 │ │ ├── router.js # 路由配置 │ │ ├── utils/websocket.js # WebSocket工具 │ │ ├── composables/useFlowGraph.js # 流程图组合式API │ │ ├── main.js # 前端入口 │ │ └── App.vue # 根组件 │ ├── package.json │ └── vite.config.js │ ├── config/ # 配置文件 │ └── settings.yaml # 主配置文件 │ ├── data/ # 数据目录 │ ├── cases/ # 测试用例数据 │ ├── reports/ # 测试报告 │ ├── plugins/ # 插件文件存储 │ └── *.db # SQLite数据库文件 │ ├── screenshots/ # 截图目录 ├── templates/ # 报告HTML模板 ├── start.py # 交互式启动脚本 └── 需求说明书.md # 详细需求文档 ``` --- ## API 接口总览 ### 录制接口 (`/api/record`) | 接口 | 方法 | 说明 | |------|------|------| | `/api/record/start` | POST | 开始录制 | | `/api/record/status` | GET | 获取录制状态 | | `/api/record/pause` | POST | 暂停录制 | | `/api/record/resume` | POST | 继续录制 | | `/api/record/stop` | POST | 停止录制 | | `/api/record/steps` | GET | 获取录制的步骤 | | `/api/record/steps/add` | POST | 手动添加步骤 | | `/api/record/steps/{stepId}` | PUT/DELETE | 更新/删除步骤 | | `/api/record/pick/start` | POST | 开始元素选取 | | `/api/record/pick/stop` | POST | 停止元素选取 | | `/api/record/pick/preview` | POST | 预览元素数据 | ### 用例管理接口 (`/api/cases`) | 接口 | 方法 | 说明 | |------|------|------| | `/api/cases` | GET | 用例列表(分页、搜索) | | `/api/cases` | POST | 创建用例 | | `/api/cases/{id}` | GET | 用例详情 | | `/api/cases/{id}` | PUT | 更新用例 | | `/api/cases/{id}` | DELETE | 删除用例 | | `/api/cases/{id}/steps` | POST | 保存步骤 | | `/api/cases/{id}/steps/{stepId}` | PUT/DELETE | 更新/删除步骤 | | `/api/cases/{id}/export` | GET | 导出用例 | | `/api/cases/import` | POST | 导入用例 | | `/api/cases/{id}/duplicate` | POST | 复制用例 | | `/api/cases/batch-delete` | POST | 批量删除 | ### 回放接口 (`/api/play`) | 接口 | 方法 | 说明 | |------|------|------| | `/api/play/execute` | POST | 执行用例 | | `/api/play/execute-steps` | POST | 直接执行步骤 | | `/api/play/status/{taskId}` | GET | 获取执行状态 | | `/api/play/pause/{taskId}` | POST | 暂停执行 | | `/api/play/resume/{taskId}` | POST | 继续执行 | | `/api/play/stop/{taskId}` | POST | 停止执行 | | `/api/play/close-browser/{taskId}` | POST | 关闭浏览器 | | `/api/play/result/{taskId}` | GET | 获取执行结果 | | `/api/play/batch` | POST | 批量执行 | ### 报告接口 (`/api/reports`) | 接口 | 方法 | 说明 | |------|------|------| | `/api/reports` | GET | 报告列表(分页、搜索) | | `/api/reports/{id}` | GET | 报告详情 | | `/api/reports/{id}/html` | GET | HTML报告内容 | | `/api/reports/{id}/generate` | POST | 重新生成报告 | | `/api/reports/{id}/delete` | DELETE | 删除报告 | | `/api/reports/statistics/summary` | GET | 统计摘要 | | `/api/reports/statistics/recent` | GET | 最近执行记录 | | `/api/reports/case/{caseId}/history` | GET | 用例执行历史 | ### LLM接口 | 接口 | 方法 | 说明 | |------|------|------| | `/api/config/llm` | GET/POST | 获取/更新LLM配置 | | `/api/config/llm/full` | POST | 完整更新LLM配置 | | `/api/config/llm/test` | POST | 测试LLM连接 | | `/api/llm-logs` | GET | LLM日志列表 | | `/api/llm-logs/{id}` | GET/DELETE | 日志详情/删除 | | `/api/llm-logs/statistics/summary` | GET | 日志统计 | | `/api/llm-logs/clear` | POST | 清理日志 | ### 插件接口 (`/api/plugins`) | 接口 | 方法 | 说明 | |------|------|------| | `/api/plugins` | GET | 插件列表(分页、搜索、类型过滤) | | `/api/plugins/all` | GET | 所有活跃插件(流程编辑器用) | | `/api/plugins` | POST | 创建插件 | | `/api/plugins/{id}` | GET/PUT/DELETE | 插件详情/更新/删除 | | `/api/plugins/{id}/upload` | POST | 上传插件文件 | | `/api/plugins/execute` | POST | 测试执行插件 | ### WebSocket | 接口 | 说明 | |------|------| | `/ws/record/{sessionId}` | 录制会话实时通信 | | `/ws/play/{taskId}` | 回放任务实时通信 | --- ## 许可证 MIT License