9.1 KiB
测试与验收
本地门禁
改功能先跑 npm run test:patrol 和相关单测,再按范围执行验收:
npm run acceptance:quick
依次检查界面类型、测试 API 契约、全部 Vitest 测试、Rust 格式和 Rust 编译。
提交或发包前执行:
npm run acceptance:full
完整门禁额外执行 ESLint、Clippy 零警告、Rust 测试、前端生产构建和发布脚本测试。任何步骤失败都会立即返回非零状态。
覆盖重点
- 应用壳在原生 API 可用和不可用时都能稳定渲染
- 会话新建、密码/私钥认证、代理和跳板配置
- SSH Config 解析和会话导出真实写盘
- 批量打开终端、SFTP 和批量命令
- Tauri 事件监听注册/销毁竞态
- SSH 连接关闭后的状态回收
- HTTP CONNECT、SOCKS5 和断点复制
- 转发规则不持久化运行状态,复制产生新 ID;原生隧道可启动、查询、停止;按断开原因验证保留或清理
- 状态栏「转发」抽屉启停动态
127.0.0.1:1080,右键复制 SOCKS 地址;每台 SSH 主机仅一条动态规则 - i18n:全部 APP_LANGUAGES(zh-CN / zh-TW / en / ja / ko / vi / ru)的 namespace key 对齐(
test/i18n/localeKeys.test.ts) - RDP / VNC 仅原生可用;非 Tauri 环境不得显示为可连接;桌面会话不参与批量命令
- SFTP 本地/远程路径参数方向、原生路径上传、选中文件下载、双栏双向拖拽、目录落点、远程文本读写和错误反馈
- 终端分屏、剪贴板、快捷键、分片 UTF-8 解码、高输出背压和异步输入错误
ssh://安全解析、冷启动队列、IPv6 格式和快速连接预填充- AI Provider 的 OpenAI Chat、Responses、Anthropic 响应解析和 HTTP Endpoint 限制
- models.dev 多种 JSON 形态归一化、目录源部分失败降级和 new-api
/models列表 - API Key 只进入 Rust secrets,不出现在
ai-providers-v1、日志或 WebView 返回值中 - Agent CLI 单任务入口、回车发送、选区上下文、本地脱敏、单行命令协议和最终结论
- 新 Provider 测试前不落盘,真实测试成功后才启用保存;任一连接字段变化会使验证快照失效
- Agent 固定当前 SSH connection;达到当前安全模式确认阈值时,确认前不得调用
ssh_exec;退出码与真实输出反馈下一轮且不进入历史 - Agent 五级命令风险、critical 硬拒绝、连续失败换路、相同命令循环拦截和长输出
analyze_output - 远程 Shell EOF/TMOUT 事件不得误判为整个 SSH 连接断开;只为对应分屏提供一键重开
- macOS 原生“编辑”菜单以及所有输入框的复制、剪切、粘贴、全选、撤销;应用快捷键不得覆盖这些系统操作
- 普通界面右键不出现 WebView 的 Reload/Inspect Element;输入框仍保留系统编辑菜单,自定义右键不受影响
测试替身必须完整实现 DesktopApiContract。新增或删除桌面接口后,typecheck:test 必须能发现未同步的契约。
分层与设置回归
npx vitest run test/platform/invoke.test.ts test/stores/settingsPersistence.test.ts test/stores/settingsMigration.test.ts test/hooks/useTheme.test.ts
cargo test --manifest-path src-tauri/Cargo.toml --lib files
覆盖 IPC 拒绝错误码与原始原因、业务失败信封保持、设置串行保存与失败回退、加载期间修改设置、无效主题归一化、系统主题切换,以及本地文件二进制往返和无效 Base64 不覆盖原文件。
文案变更另跑 npx vitest run test/i18n/localeKeys.test.ts。巡检通过不代表全量验收通过;既有失败应明确报告,不能以针对性测试替代全量结果。仅文档变更检查路径、链接和说明与实现一致,不必运行功能测试。
AI 助手验收
自动验收不得使用真实个人 API Key。可以用本机 mock OpenAI Compatible 服务验证以下边界:
- Provider 没有 Key 时返回明确错误;保存 Key 后普通设置 JSON 中搜索不到明文。
- HTTPS 为默认要求,任意公网 HTTP Endpoint 被拒绝;只有显式允许后才能访问可信本机 HTTP 服务。
- OpenAI Chat、OpenAI Responses 和 Anthropic 三种响应都能提取文本,错误响应显示 HTTP 状态和供应商消息。
Authorization: Bearer、密码字段、AWS Key 和私钥在请求发出前被替换,并显示脱敏计数。- 有选区时只发送选区;无选区时不抓取当前整屏。
- 面板不再出现“解释 / 生成命令 / 排障 / 执行任务”切换;回车触发执行,
Shift+回车不触发。 - 关闭再打开 AI 面板,之前的提示词和回答不存在。
- models.dev 三个源全部失败时不影响已保存 Provider;部分成功时仍能生成可导入目录。
- 新增 Provider 后测试前“保存”禁用;测试实际发送“你是什么模型?请简短回答。”,期间 settings 与 secrets 均无写入;只有非空成功回答显示 HTTP 200,随后保存才写入加密 Key。
- 切换 Endpoint、模型、协议或 API Key 后“保存”立即重新禁用。
- 每一轮只接受唯一单行命令;默认宽松模式下 safe/low/medium 自动执行、high 先确认;严格模式从 medium 起确认;critical 前后端均硬拒绝。需要确认时,对话框打开前和用户取消后
ssh_exec调用次数必须为 0。Agent 发起的ssh_exec必须带fromAgent。 - 确认后只向当前 connectionId 执行;真实输出和 exit code 必须交给下一轮,直到 FINAL 或 12 步上限。
rm -rf /、mkfs、对磁盘覆盖的dd等 critical 命令必须在确认对话框前硬拒绝。- 相同命令第 3 次必须在执行前拦截;连续失败的下一轮 Prompt 必须要求更换路径。
- 超长工具输出必须限长,
analyze_output保留总行数、错误行和首尾;关闭面板后命令与输出消失。
真实 SSH/SFTP 探针
真实探针默认标记为 ignored,必须显式提供测试服务器:
OPSX_TEST_SSH_HOST=example.com \
OPSX_TEST_SSH_PORT=22 \
OPSX_TEST_SSH_USER=root \
cargo test --manifest-path src-tauri/Cargo.toml \
real_ssh_exec_and_sftp_probe -- --ignored --nocapture
该探针会执行 SSH 命令、创建 SFTP 通道,并在远端 /tmp 完成一个临时文件的上传、下载、逐字节比对和清理。只有列目录成功不算 SFTP 基础传输验收通过。
ProxyJump 探针额外设置 OPSX_TEST_SSH_JUMP_HOST、OPSX_TEST_SSH_JUMP_PORT;使用 OPSX_TEST_SSH_JUMP_COUNT=2 可验证两级链。
动态 SOCKS5 真实探针使用同一组 SSH 环境变量:
OPSX_TEST_SSH_HOST=example.com \
OPSX_TEST_SSH_PORT=22 \
OPSX_TEST_SSH_USER=root \
cargo test --manifest-path src-tauri/Cargo.toml \
real_dynamic_forward_probe -- --ignored --nocapture
它会创建随机本地 SOCKS5 监听,通过 SSH direct-tcpip 再连回测试主机,读取 SSH- 协议头,最后停止监听并确认运行状态已清理。
端口转发验收
Rust 单元测试会用随机本地端口验证动态监听器的唯一 ID、运行查询、重复启动拒绝和真实停止。实机验收还必须包含:
- 在状态栏打开「转发」抽屉,启动
127.0.0.1:1080,用curl --proxy socks5h://127.0.0.1:1080 https://example.com验证(出口 IP 应为当前 SSH 服务器)。 - 右键状态栏「转发」复制
socks5://127.0.0.1:1080,确认剪贴板正确。 - 确认连接数和流量会变化(若界面展示统计)。
- 停止后确认端口无法再连接,不能只检查 UI 颜色。
- 重启应用后规则仍在,但状态必须为未运行。
- 分别验证意外断开/空闲挂起与用户停止/关闭标签:前者按保留策略维持转发并支持同窗重连接管,后者必须关闭真实 Listener;不能把所有 SSH 断开一概视为清理转发。
- 复制规则后确认新规则 ID 独立且状态为未运行;编辑运行中的规则必须先停止原 Listener。
- 同一 SSH 主机不得出现第二条动态规则。
远程桌面验收
- 非 Tauri / 浏览器预览中,RDP / VNC 不得表现为可连接。
- 原生应用中分别建立 RDP、VNC 会话,确认画面、键盘鼠标与断开清理。
- RDP:验证剪贴板同步与共享盘放入/打开本机下载目录。
- 批量命令入口不得包含桌面会话。
ssh:// 验收
macOS 安装版先检查 Info.plist 包含 ssh URL scheme,然后分别验证冷启动和运行中唤起:
plutil -p OpsXShell.app/Contents/Info.plist | grep -A8 CFBundleURLTypes
open -a OpsXShell 'ssh://root@opsbase.cn:55555'
必须确认只存在一个 OpsXShell 进程、原窗口被聚焦、快速连接目标为 root@opsbase.cn:55555。ssh://root:password@host 和包含远程路径的链接必须被拒绝。Windows 需要在安装后的注册表和浏览器唤起场景重复验证,macOS 结果不能代替 Windows 验收。
发版验收
候选发布必须在目标系统完成:安装、首次启动、窗口操作、SSH、SFTP、代理、跳板、端口转发、RDP/VNC、串口枚举、休眠恢复、卸载及重新安装。CI 构建成功不能替代 Windows 或 macOS 实机验收。