For the complete documentation index, see llms.txt. This page is also available as Markdown.

端到端测试

使用 WDIO + Appium 的端到端测试。CI 和本地设置。

概览

桌面端 E2E 测试使用 WebDriverIO(WDIO) 通过 Appium 驱动 Tauri 应用:

平台
驱动
端口
应用格式
选择器

Linux / Appium Chromium

Appium Chromium

4723

调试二进制

CSS / DOM

macOS / Appium Chromium

Appium Chromium

4723

.app

CSS / DOM

OpenHuman 的桌面应用目前使用 CEF 运行时(tauri-runtime-cef)。CI 使用 Appium 的 Chromium 驱动来驱动 Linux 调试二进制;手动的 macOS 和 Windows E2E 使用相同的 Chromium 驱动后端。


快速开始

Linux / Appium Chromium

# 安装 Appium 和 Chromium 驱动(一次性)
npm install -g appium@3
appium driver install --source=npm appium-chromium-driver

# 构建 E2E 应用
pnpm --filter openhuman-app test:e2e:build

# 运行所有流程
pnpm --filter openhuman-app test:e2e:all:flows

# 运行单个 spec
bash app/scripts/e2e-run-spec.sh test/e2e/specs/smoke.spec.ts smoke

在无头 Linux 上,测试框架会在 Xvfb 下运行,以提供虚拟显示器。

macOS / Appium Chromium

macOS 上的 Docker(本地 Linux 测试框架)

通过 Docker 在 macOS 上运行相同的基于 Linux 的测试框架。

需要 Docker Desktop 或 Colima。仓库会通过绑定挂载,因此构建结果会在多次运行之间保留。


架构

平台检测

app/test/e2e/helpers/platform.ts 导出:

  • isTauriDriver(),旧的兼容封装,现在始终返回 true ,用于支持 DOM 的 Chromium 会话

  • isMac2(),旧的兼容封装,现在始终返回 false

  • supportsExecuteScript(), true 因为 Chromium 驱动支持 browser.execute() 在所有平台上

元素辅助函数

app/test/e2e/helpers/element-helpers.ts 提供统一 API:

辅助函数
Appium Chromium

waitForText(text)

基于 DOM 文本内容的 XPath

waitForButton(text)

按钮 / [role="button"] XPath

clickText(text)

标准 el.click()

clickNativeButton(text)

标准 el.click() 在按钮上

clickToggle()

[role="switch"] / input[type="checkbox"]

waitForWindowVisible()

窗口句柄检查

waitForWebView()

document.readyState 检查

hasAppChrome()

窗口句柄检查

dumpAccessibilityTree()

HTML 页面源代码

稳定的测试 ID

优先使用稳定的 data-testid 用于 E2E spec 点击或轮询的 UI 交互钩子。使用以下命名法 <surface>-<element>-<id?>,例如:

  • cron-jobs-panel, cron-refresh

  • cron-job-row-<jobId>, cron-job-toggle-<jobId>, cron-job-run-<jobId>, cron-job-view-runs-<jobId>, cron-job-remove-<jobId>

  • settings-nav-<routeId>

  • skill-row-<skillId>, skill-install-<skillId>, skill-uninstall-<skillId>

  • thread-row-<threadId>, new-thread-button, send-message-button

  • onboarding-next-button

使用 waitForTestId(testId)clickTestId(testId) 来自 element-helpers.ts ,当 spec 目标是这些钩子之一时使用。保留文本选择器用于用户可见文案的断言,而不是行/操作发现。

深度链接辅助函数

app/test/e2e/helpers/deep-link-helpers.ts 处理认证深度链接:

  • Appium Chromium: browser.execute(window.__simulateDeepLink(url)) 在所有平台上

  • macOS 备用方案: macos: deepLink 扩展命令,然后 open -a ...

对于发布候选版本,在触及 CEF 预检、单实例或深度链接启动代码时,还要在 Linux 或 macOS 上手动运行一次二次实例冒烟测试:

  1. 正常启动 OpenHuman 并保持其运行。

  2. 触发 openhuman://auth?token=e2e-token&key=auth ,通过操作系统打开器。

  3. 确认已经运行的窗口收到了回调,并且没有启动第二个完整的 CEF 实例。

  4. 确认辅助进程能干净退出,没有 CEF 缓存锁错误。

这可以捕获一类回归:辅助进程在 CEF 缓存预检期间退出,而此时 Tauri 的深度链接转发路径尚未安装。

编写跨平台 spec

  1. 使用辅助函数 来自 element-helpers.ts,绝不要使用原始的 XCUIElementType* 选择器在 spec 中

  2. 使用 clickNativeButton(text) ,而不是使用内联的按钮点击代码

  3. 使用 hasAppChrome() ,而不是检查 XCUIElementTypeMenuBar

  4. 使用 waitForWebView() ,而不是检查 XCUIElementTypeWebView

  5. 对于仅限 macOS 的测试,请使用 process.platform 守卫或单独的 spec 文件

  6. 使用 navigateViaHash(route) 用于 hash 路由;它会等待 hash, document.readyState以及挂载好的 React 根节点,然后才返回。在完成 onboarding 之后, walkOnboarding() 还会等待 #/home 以及一个 Home 页面标记,然后 spec 才会跳转到别处。


环境变量

变量
默认值
描述

APPIUM_PORT

4723

Appium 服务端口

E2E_MOCK_PORT

18473

模拟后端服务端口

OPENHUMAN_WORKSPACE

(临时目录)

应用工作区目录

OPENHUMAN_SERVICE_MOCK

0

启用服务模拟模式

OPENHUMAN_E2E_MODE

未设置

启用破坏性的测试支持 RPC;E2E 运行器会将其设置为 1

OPENHUMAN_E2E_AUTH_BYPASS

未设置

启用 JWT 绕过认证

DEBUG_E2E_DEEPLINK

(详细)

设置为 0 以关闭深度链接日志

E2E_FORCE_CARGO_CLEAN

未设置

在 E2E 构建前强制执行 cargo clean


CI 工作流

Push / PR 检查

默认的拉取请求门禁是 .github/workflows/ci-lite.yml (快速通道:质量检查 + 仅针对变更文件范围的单元测试)。E2E 套件不会在发往 main 的 PR 上运行——完整的 E2E 矩阵(Rust mock 后端、Playwright Web、Linux/macOS/Windows 桌面端)会在 .github/workflows/ci-full.yml 运行于目标为 release 分支的 PR 上,以及每次推送到该分支时。

macOS 和 Windows 桌面端 E2E 不会在每个 PR 上运行。需要跨平台桌面信号时,请使用手动触发的 E2E 工作流(.github/workflows/e2e.yml)在晋级前运行。

macOS / Appium Chromium

macOS/Appium Chromium 可用于本地运行,也可通过手动触发的 E2E 工作流使用:

  1. 安装 Appium + Chromium 驱动

  2. 构建 .app

  3. 运行所有 E2E 流程


故障排查

Linux:“WebView 未就绪”超时

对于默认的 CEF 运行时,这通常意味着某个过时的本地运行器正试图通过 WebKitWebDriver 驱动一个基于 CEF 的 WebView。当前 CI 在 Linux 上使用 Appium Chromium 驱动;请使用 app/scripts/e2e-run-session.sh 或 PR CI 工作流来走受支持的 Linux 路径。

确保 DISPLAY 已设置且 Xvfb 正在运行:

还要确保 dbus 已启动(webkit2gtk 需要它):

Linux:未找到 Appium Chromium 驱动

macOS:深度链接在 tauri dev

深度链接需要一个 .app bundle。请改用 pnpm tauri build --debug --bundles app

Docker:首次运行构建很慢

第一次 Docker 构建会编译 Rust 并安装 E2E 测试框架依赖。后续运行会使用缓存层。Cargo 仓库和 git 源会通过 Docker 卷缓存。

Spec:通知

文件: app/test/e2e/specs/notifications.spec.ts

通过实时 core sidecar 和 Notifications UI 页面测试通知 RPC 方法:

  • notification_ingest,通过 core RPC 创建一条新通知

  • notification_list,验证返回了已摄取的通知

  • notification_mark_read,将通知标记为已读

  • notification_stats,检查聚合统计的形状

  • UI:Notifications 页面渲染集成通知部分([data-testid="integration-notifications-section"])

  • UI:Notifications 页面显示系统事件部分([data-testid="system-events-section"])

运行:

平台说明:RPC 测试(notification_ingest, notification_list, notification_mark_read, notification_stats)通过统一的 Appium Chromium 后端运行。UI 断言需要 browser.execute() 支持,而当前后端在所有平台上都提供该支持。


面向 Agent 可观测的产物流程

要进行一次可作为基准、可检查的运行,并将截图、页面源代码转储和模拟请求日志写入磁盘:

产物会落在 app/test/e2e/artifacts/<timestamp>-agent-review/。完整详情 + 辅助 API: AGENT-OBSERVABILITY.md。任何失败的测试都会触发 wdio.conf.tsafterTest 钩子,它会写入 failure-*.png + failure-*.source.xml 到同一个运行目录中。


Rust 推理提供方 E2E

这些测试(tests/inference_provider_e2e.rs)使用 wiremock 来模拟 HTTP 上游,不需要任何真实的 LLM API 调用。它们覆盖 OpenAI 兼容聊天、Anthropic 认证样式、按模型禁用 temperature、Ollama 本地提供方,以及 /v1 HTTP 端点认证层。

最后更新于