跳到主要内容

测试策略

OpenHuman 如何测试其产品。"我的测试放在哪里?"的最终来源。配套 TEST-COVERAGE-MATRIX.md

测试层次

层次位置测试内容驱动
Rust 单元同源 *.rs 文件内的 #[cfg(test)] mod tests,或同级 tests.rs,或域下的 tests/ 子目录纯域逻辑、schema、RPC 处理程序形状、内存状态机cargo test
Rust 集成仓库根的 tests/*.rs带真实 Tokio 运行时的完整域连接、模拟外部服务、JSON-RPC 端到端pnpm test:rust
Vitest 单元源码同源的 *.test.ts(x)app/src/**/__tests__/React 组件、hooks、store slices、纯工具、服务层适配器pnpm test:unit
WDIO E2Eapp/test/e2e/specs/*.spec.ts完整桌面流:UI → Tauri → 核心 sidecar → JSON-RPC;用户可见行为Linux CI:tauri-driver (端口 4444)。macOS 本地:Appium Mac2 (端口 4723)
手动冒烟docs/RELEASE-MANUAL-SMOKE.md驱动程序无法断言的 OS 级表面:TCC 权限提示、Gatekeeper、代码签名、DMG 安装、OS 原生 toasts发布时人工确认

测试放置决策树

变更是否在 JSON-RPC 边界后面(在 `src/` 中)?
├─ 是 - 是否跨域或与外部服务对话?
│ ├─ 是 → Rust 集成(tests/*.rs)
│ └─ 否 → Rust 单元(源码旁边)
└─ 否 - 变更在 `app/`
├─ 是纯函数、hook、slice 还是孤立组件?
│ └─ 是 → Vitest 单元(*.test.tsx 同源)
└─ 是用户可见的且跨 UI ⇄ Tauri ⇄ sidecar ⇄ JSON-RPC?
├─ 是 → WDIO E2E(app/test/e2e/specs/*.spec.ts)
└─ 是 OS 级(TCC、Gatekeeper、安装、OS toasts)?
└─ 是 → 手动冒烟检查清单

如果变更触及以上多个层次,在您触及的每个层次编写测试。不要用一个层次替代另一个。

失败路径要求

覆盖矩阵中的每个特征叶必须至少有一个失败/边缘断言以及快乐路径。示例:

  • 文件写入工具:快乐路径 = 写入字节;失败路径 = 路径限制拒绝
  • OAuth 流:快乐路径 = 发放 token;边缘 = 过期 refresh token 恢复
  • 记忆存储:快乐路径 = 存储 + 回忆;边缘 = 遗忘然后回忆返回空

Mock 策略

  • 单元/集成/E2E 中无真实网络。 使用共享 mock 后端
  • 外部服务(Telegram、Slack、Gmail、Notion、Ollama、OpenAI 等)在 mock 后端级别 stub
  • 唯一可接受的例外是文档化的发布截止手动冒烟步骤

确定性规则

  • 不使用壁钟等待,使用 waitForAppwaitForAppReadywaitForWebView helpers 或明确的元素就绪谓词
  • 不使用共享文件系统状态,每个 E2E spec 在隔离的 OPENHUMAN_WORKSPACE 中运行
  • 不依赖顺序相关的 spec,每个 spec 单独运行时必须通过
  • 不依赖绝对坐标或动画时间

预合并检查

# Rust 核心
cargo fmt --check
cargo check --manifest-path Cargo.toml
cargo clippy --manifest-path Cargo.toml -- -D warnings
cargo test --manifest-path Cargo.toml

# Tauri shell
cargo check --manifest-path app/src-tauri/Cargo.toml

# 前端
pnpm typecheck
pnpm lint
pnpm format:check
pnpm test:unit

# Rust 集成
pnpm test:rust

# E2E(慢——仅在行为用户可见地改变时运行)
pnpm test:e2e:build

驱动程序无法自动化的内容

某些表面无法通过 WDIO / Appium 驱动,因为它们跨越 OS 级信任边界或硬件路径:

  • macOS TCC 权限提示(Accessibility、Input Monitoring、Screen Recording、Microphone)
  • Gatekeeper 签名验证
  • 代码签名完整性
  • DMG 安装/拖动到 Applications 流程
  • 自动更新下载 + 重新启动
  • Linux 上的 OS 原生通知 toasts

覆盖矩阵作为契约

覆盖矩阵中的每个特征叶映射到:

  1. 测试路径,
  2. 有正当理由的 🚫 和手动冒烟条目

当您添加/删除/重命名特征时,在同一 PR 中更新矩阵行

下一步