docs/guides/hub-testing.md
| 层级 | 名称 | 测什么 | 关注点 | 运行环境 |
|---|---|---|---|---|
| L1 | Integration Test | 主进程安装链路 | 数据流转正确性 | 本地 + CI |
| L2 | E2E Test | UI 交互流程 | 用户体验正确性 | 本地(需 Electron) |
| L3 | Smoke Test | 真实 Backend 连通性 | ACP 协议可用性 | 仅本地 |
文件: tests/integration/hub-install-flow.test.ts
测试的完整链路:
HubIndexManager 加载 index
→ HubInstaller.install() 下载解压
→ lifecycle onInstall 执行(安装 CLI)
→ ExtensionRegistry.hotReload()
→ AcpDetector.refreshAll() 检测新 Backend
→ AcpConnection.connect() 完成 handshake
→ sendPrompt() 收到 response
关注点:
使用的 fixture:
tests/fixtures/fake-acp-cli/ — 最小 ACP JSON-RPC CLI,支持 initialize / session/new / session/prompttests/fixtures/fake-extension/ — 测试用 extension,声明 acpAdapters,onInstall 钩子将 fake CLI 放到 PATH运行:
bun run test:integration
# 或单独运行
bunx vitest run tests/integration/hub-install-flow.test.ts
文件: tests/e2e/specs/hub-backend-install.e2e.ts
测试的 UI 流程:
设置页 → Agent 页 → 本地 Agent Tab
→ 点击"从市场安装"
→ Hub 弹窗打开,列表加载
→ 验证 card 状态(Install / Installed / Retry)
→ 点击 Install,状态流转(Installing → Installed)
→ 关闭弹窗,验证新 Backend 出现在列表
→ 选择新 Backend,验证可发起会话
关注点:
运行:
# 需要 Electron 环境
bun run test:e2e
# 或单独运行
bunx playwright test tests/e2e/specs/hub-backend-install.e2e.ts --config playwright.config.ts
注意: L2 需要 Electron 二进制。如果 Electron 未安装,先运行
node node_modules/electron/install.js。
文件: tests/integration/acp-smoke.test.ts
测试流程:
检查 CLI 是否在 PATH 上
→ 不存在则 skip(不 fail)
→ 存在则 spawn CLI + ACP handshake
→ initialize → session/new → session/prompt
→ 验证收到 response chunk
→ disconnect,验证进程正常退出
关注点:
覆盖的 Backend:
| Backend | 命令 | ACP 参数 | 备注 |
|---|---|---|---|
| fake-acp-cli | node index.js | — | 始终运行 |
| claude | claude | --acp | 需 ACP_SMOKE_REAL=1 |
| codex | codex | --acp | 需 ACP_SMOKE_REAL=1 |
| goose | goose | acp | 需 ACP_SMOKE_REAL=1 |
运行:
# 默认只跑 fake CLI(无需真实 Backend)
bunx vitest run tests/integration/acp-smoke.test.ts
# 启用真实 Backend 冒烟(需要本地已安装对应 CLI + API key)
ACP_SMOKE_REAL=1 bunx vitest run tests/integration/acp-smoke.test.ts
注意: L3 仅在本地运行,不上 CI。真实 Backend 测试需要本地安装 CLI 并配置好 API key。
当 Hub 新增一个 Backend extension 时,按以下步骤验证:
无需修改测试代码。L1 使用 fixture extension 验证通用安装链路,与具体 Backend 无关。
在 tests/integration/acp-smoke.test.ts 的 realBackends 数组中添加新 Backend:
const realBackends = [
{ name: 'claude', cmd: 'claude', args: ['--acp'] },
{ name: 'codex', cmd: 'codex', args: ['--acp'] },
{ name: 'goose', cmd: 'goose', args: ['acp'] },
// 新增:
{ name: 'new-backend', cmd: 'new-backend', args: ['--acp'] },
];
然后本地运行:
ACP_SMOKE_REAL=1 bunx vitest run tests/integration/acp-smoke.test.ts
启动 dev 环境,手动走一遍 UI 流程确认无误后,运行 E2E 测试:
bun run test:e2e
位置: tests/fixtures/fake-acp-cli/
最小 ACP JSON-RPC 2.0 CLI 实现,通过 stdin/stdout 通信:
initialize → 返回 capabilities + modelssession/new → 返回 sessionIdsession/prompt → 返回流式 text chunks + end_turnsession/cancel → 取消当前 prompt用于 L1 和 L3(fake CLI 部分),避免依赖真实 Backend。
位置: tests/fixtures/fake-extension/
测试用 extension:
aion-extension.json — 声明 contributes.acpAdapters,声明 lifecycle.onInstallscripts/install.js — onInstall 钩子,将 fake-acp-cli 放到临时 PATH(Unix: symlink, Windows: .cmd wrapper)所有测试已处理跨平台差异:
| 差异点 | 处理方式 |
|---|---|
| symlink 权限 (Windows) | Windows 用 .cmd wrapper 替代 |
| shebang (Windows) | 统一用 spawn('node', [path]) |
| 进程信号 (Windows) | child.kill() 跨平台,SIGKILL 仅 Unix |
| CLI 检测 | where (Windows) / which (Unix) |
| 路径分隔符 | 统一用 path.join() + os.tmpdir() |