资讯动态

AionUi Aionrs Chat E2E 实现映射:15 个测试用例从需求定义到落地验证的完整工程实践

发布时间:2026/9/11 7:58:49 来源:尧图企业网站定制
AionUi Aionrs Chat E2E 实现映射15 个测试用例从需求定义到落地验证的完整工程实践【免费下载链接】AionUiOpen-source 24/7 Cowork app for OpenClaw, Hermes, Claude Code, Codex, OpenCode and 20 more CLI Agent | Customize your assistants | Team them upStar if you like it!项目地址: https://gitcode.com/GitHub_Trending/ai/AionUi本文以tests/e2e/docs/chat-aionrs/文档体系为核心完整解析 AionUi 桌面端 Aion CLIaionrs聊天功能端到端测试的工程化落地从test-cases.zh.md定义的 15 个用例TC-A-01 ~ TC-A-15到tests/e2e/features/conversations/aionrs/下 6 个实现文件的映射关系、P0/P1/P2 分级策略、DB 断言与清理机制以及运行时模型/权限切换导致的静默挂起已知问题。读完你将掌握一套可复用的用例定义 → 实现映射 → 偏差治理 → 质量度量E2E 工程方法论并理解 AionUi 中 aionrs 对话从 guid 页创建、bridge 建会话、发送消息到数据库断言的全链路验证方式。一、背景aionrs 对话与 E2E 文档体系AionUi 是一款面向 CLI Agent如 OpenClaw、Claude Code、Codex 等的桌面协作应用其内置的 aionrs 后端对应 Aion CLI 二进制负责执行真实的模型对话、工具调用与文件读写。由于 aionrs 走独立二进制进程而非 ACP bridge它的 E2E 测试与 Gemini/ACP 通道有显著差异因此仓库在tests/e2e/docs/chat-aionrs/下沉淀了一套完整的文档体系文档定位requirements.zh.md需求来源与 Gate 阶段定义test-cases.zh.md15 个测试用例的权威定义维度组合、操作步骤、DB 断言 SQLimplementation-mapping.zh.md用例定义 ↔ 实际实现文件的映射、偏差清单与重写计划discussion-log.zh.md设计讨论与议题决策记录其中implementation-mapping.zh.md是连接定义与实现的桥梁它记录每个用例 ID 对应的实现文件、行号、测试函数名、截图数量与当前状态并明确标注定义与实现偏差的处理结论。本文即围绕这份映射文档展开。二、用例体系P0/P1/P2 三级编号与测试维度2.1 编号规则依据 test-cases.zh.md15 个用例按优先级分三档P0必测TC-A-01 ~ TC-A-05基线路径验证最小可用功能P1常规TC-A-06 ~ TC-A-12维度组合与常用场景P2边界TC-A-13 ~ TC-A-15异常处理与边界验证。2.2 五个测试维度每个用例都围绕以下维度组合设计所有取值均有源码依据维度可选值说明关联文件夹无 / 单 / 多atPath数组源码AionrsSendBox.tsx上传文件无 / 单 / 多uploadFile数组源码useSendBoxFiles.ts模型默认 / 自选从用户配置的 provider 列表选择过滤 Google AuthipcBridge.mode.getModelConfig权限default/auto_edit/yolo来自 aionrs runtime capabilities对话中操作切换模型 / 切换权限 / 无对话页AionrsModelSelector/AgentModeSelector2.3 统计概览文档 v4 运行结果类别文档定义实际实现状态P0 核心流程55✅ 100%P1 功能验证77✅ 100%P2 边界用例33⚠️ 100%需重写总计1515⚠️ 15/15其中 3 个偏差运行状态为✅ Passed 11/15TC-A-01/02/03/05/06/10/11/12/13/14/15⏭️ Skipped 4/15TC-A-04/07/08/09aionrs binary 运行时切换挂起❌ Failed 0/15。三、全局前置条件binary 检查与 provider 过滤所有 aionrs 测试用例共享三条前置条件见 test-cases.zh.mdaionrs binary 可用否则 skip 全部测试至少 1 个可用 provider过滤掉platform包含gemini-with-google-auth的 Google Auth provider且必须包含 apiKey 与可用 model临时工作目录/tmp/e2e-chat-aionrs-scenario-timestamp/。这三条前置条件在 chatAionrs.ts 中落地为可复用的 helper// tests/e2e/helpers/chatAionrs.ts export function resolveAionrsBinary(): string | null { try { const result execSync(which aionrs, { encoding: utf-8, timeout: 5000 }).trim(); if (result fs.existsSync(result)) return result; } catch { // Binary not found in PATH } return null; }resolveAionrsBinary()通过which aionrs探测 PATH 中的二进制并校验文件真实存在随后resolveAionrsPreconditions(page)将 binary 探测与模型获取合并返回{ binary, models }每个测试文件在beforeAll中统一调用test.beforeAll(async ({ page }) { preconditions await resolveAionrsPreconditions(page); if (!preconditions.binary || !preconditions.models) { test.skip(true, No aionrs-compatible provider found, skipping E2E tests); } });3.1 provider 兼容性过滤与优先级模型选择并非随便取一个 provider而是有严格的兼容性判断逻辑chatAionrs.ts硬性排除gemini-with-google-authGoogle Auth 流程不适合 E2EgeminiOpenAI 兼容通道/v1beta/openai在 preview 模型上存在已知的首次发送静默挂起 bug为保证 E2E 确定性而排除兼容白名单anthropic、bedrock、gemini-vertex-ai、new-apicustom平台要求 baseUrl 以/v1或/v1/结尾因为 aionrs 会自行拼接/v1/chat/completions平台优先级排序custom用户自配 OpenAI 兼容端点优先其次anthropicnew-api因常用中继网关轮换 token 而靠后gemini-vertex-ai最后。模型对modelA/modelB的选取规则modelA取候选列表首个 provider 的第一个模型若该 provider 有第二个模型则作为modelB否则取第二个候选 provider 的第一个模型不足则modelB null对应用例会 skip。四、P0 核心流程5/5最小可行路径的实现细节4.1 TC-A-01 最小可行路径对应实现basic-flow.e2e.ts。维度组合为无附件 默认模型 default 权限验证最基础的对话闭环。其关键路径是完全通过 IPC bridge 驱动而非 UI 点击// 通过 bridge 创建 aionrs 类型对话 const conversationId await createAionrsConversationViaBridge(page, { name: conversationName, workspace: tempWorkspace.path, provider: preconditions.models!.modelA, sessionMode: default, }); // 通过 bridge 发送消息 await sendAionrsMessage(page, conversationId, Say hi in one word.); // 轮询等待 AI 回复完成 await waitForAionrsReply(page, conversationId);其中createAionrsConversationViaBridge内部调用invokeBridge(page, create-conversation, { type: aionrs, model: provider, extra: { workspace, sessionMode } }, 15_000)将sessionMode持久化到conversations.extra字段sendAionrsMessage调用chat.send.message并附带msg_id、files: []。DB 断言要点四个方向// 1. conversation 类型与模式 expect(conversation.type).toBe(aionrs); // extra 可能是 string 或 object需兼容处理 const extra typeof conversation.extra string ? JSON.parse(conversation.extra || {}) : conversation.extra || {}; expect([default, auto_edit, yolo]).toContain(extra.sessionMode); // 放宽断言兼容用户默认设置 // 2. 用户消息positionright expect(userMsg.content.content).toContain(Say hi in one word.); // 3. AI 回复positionleft 且 typetext至少 1 条 expect(aiMessages.length).toBeGreaterThanOrEqual(1); // 4. 消息总数 ≥ 2用户 AI expect(messages.length).toBeGreaterThanOrEqual(2);4.2 TC-A-02 关联单个文件夹对应实现basic-flow.e2e.ts。测试在临时工作区下创建test-folder/sample.txt将 workspace 指向该文件夹并验证用户消息的content.attachedDirs字段包含{ name: test-folder, isFile: false }条目if (userContent.attachedDirs) { expect(Array.isArray(userContent.attachedDirs)).toBe(true); expect(userContent.attachedDirs.some((dir: any) dir.name test-folder !dir.isFile)).toBe(true); }4.3 TC-A-03 上传单个文件对应实现basic-flow.e2e.ts。在 workspace 中创建e2e-test-file.txt后发送消息询问文件内容验证 aionrs 具备 workspace 内文件读取能力且用户消息内容包含文件名。4.4 TC-A-04 非默认模型Skip对应实现model-selection.e2e.ts。设计意图是验证在 guid 页选择modelB后 DB 记录正确模型 ID断言extra.model.useModel modelB.useModel。当前因运行时切换挂起问题被test.skip()。4.5 TC-A-05 yolo 权限对应实现permission-modes.e2e.ts。这是少数走完整 UI 路径的 P0 用例selectAionrsAgent(page)选中 aionrs agent → 点击[data-testidagent-mode-selector-aionrs]→ 选择[data-testidaionrs-mode-option-yolo]→ 通过guid-input输入消息并点击guid-send-btn→ 等待 URL 跳转至/conversation/[a-f0-9-]后轮询 AI 回复最终断言extra.sessionMode yolo。五、P1 功能验证7/7组合场景与动态切换5.1 TC-A-06 对话中切换权限default → yolo对应实现permission-modes.e2e.ts。通过 bridge 以default模式创建对话并完成首轮对话然后导航到对话页打开agent-mode-selector-aionrs切换为 yolo再发送第二轮消息。DB 断言验证extra.sessionMode已持久化为yolo且消息总数 ≥ 4、AI 回复 ≥ 2——证明权限切换不仅更新了 UI 状态还真实写入了数据库。5.2 TC-A-07 对话中切换模型Skip对应实现model-selection.e2e.ts。设计上通过[data-testidaionrs-model-option-${modelB.useModel}]精确选择模型断言 DB 中extra.model.useModel更新为modelB.useModel且消息数 ≥ 4。与 TC-A-04 同因运行时切换挂起被 skip。5.3 TC-A-08 / TC-A-09 连续切换与切换后多轮Skip对应实现mid-conversation-switch.e2e.ts 与 (tests/e2e/features/conversations/aionrs/mid-conversation-switch.e2e.ts#L179-L283)。TC-A-08 覆盖modelA → modelB → yolo → modelA三次连续切换后发消息TC-A-09 覆盖切换后进行 3~4 轮多轮对话验证配置持久化。两者均因 aionrs binary 运行时状态机不支持切换而 skip详见第八节已知问题。5.4 TC-A-10 / TC-A-11 / TC-A-12 组合场景对应实现combo-scenarios.e2e.ts。这三个用例是多维度正交组合的典型代表用例实际组合关键断言TC-A-10folder second model yoloextra.workspace含test-folderextra.sessionMode yoloTC-A-11file non-default model default modeextra.workspace tempWorkspace.pathextra.sessionMode defaultTC-A-12folder file second model yolo 全组合workspace 含combo-folderyolo 模式左右消息均 ≥ 1组合用例在对话页通过aionrs-model-selector下拉选择第二个模型若选项数 2 则test.skip随后经 bridge 发送消息并等待回复。它们的共同点是验证conversations.extra中 workspace 与 sessionMode 的持久化而 aionrs 文本消息不设置statusfinish只能依赖conv.status判断完成状态。六、P2 边界用例定义 vs 实现的偏差治理P2 三个用例在文档定义与实际实现之间出现了严重偏差implementation-mapping.zh.md用例 ID文档定义当前实现偏差说明判断TC-A-13Binary 不可达时跳过empty workspace folder without crashing前者测环境检测 skip 逻辑后者测空工作区容错❌ 需重写TC-A-14超大文件上传限制100MBvery long message2000 字符前者测文件大小限制后者测消息长度❌ 需重写TC-A-15关联不存在的文件夹rapid consecutive messages并发竞态前者测错误处理路径不存在后者测并发场景❌ 需重写值得注意的是当前 edge-cases.e2e.ts 的实际实现已按照原定义部分重写TC-A-13 变为验证 binary 可达时能通过beforeAll前置检查断言preconditions.binary非空TC-A-14 在临时工作区构造精确 100MB 文件并记录 bridge 是否抛出错误TC-A-15 创建文件夹后立即rmdir删除再尝试以该路径创建对话验证错误处理行为。文档同时给出了完整的重写计划TC-A-13 通过 mockresolveAionrsBinary()返回 null 验证test.skip(true, aionrs binary not found)触发TC-A-14 创建 100MB 临时文件经sendAionrsMessage上传并验证 UI/bridge 错误提示TC-A-15 删除临时文件夹后经 bridge 创建对话并验证异常抛出。七、数据库验证策略与清理机制7.1 conversations / messages 双表断言所有测试通过 IPC bridge 直接读库断言// conversations 表 const conv await getAionrsConversationDB(page, conversationId); expect(conv.type).toBe(aionrs); // extra 字段需处理 string/object 两种形态 const extra typeof conv.extra string ? JSON.parse(conv.extra) : conv.extra; expect([default, auto_edit, yolo]).toContain(extra.sessionMode); expect(extra.workspace).toBe(workspacePath); // 或 undefined无文件夹 // messages 表通过 waitForAionrsReply 轮询7.2 waitForAionrsReply 轮询语义核心等待逻辑在 chatAionrs.ts以conv.status finished AI 文本内容稳定 2 秒作为完成信号每 500ms 轮询一次默认超时 150 秒比 Gemini API 快但需预留模型切换时间。关键字段约定字段名为createdAt驼峰而非created_ataionrs 文本消息不设置statusfinish只依赖conv.status超时后会 dump 最终 DB 状态conv.status、消息数量与每条消息的 pos/type/status/preview帮助定位原因。7.3 清理机制afterEach 四步曲每个测试文件在afterEach中按固定顺序清理test-cases.zh.mdUI 状态清理连续按 ESC × 5 次关闭可能弹出的对话框数据库清理cleanupE2EAionrsConversations(page)通过database.get-user-conversations拉取全部对话筛选name以E2E-aionrs-开头的记录逐条调用remove-conversationbridge 删除依赖 FK CASCADE 自动级联删除 messagessessionStorage 清理遍历删除aionrs_initial_message_*与aionrs_initial_processed_*前缀的 key临时文件清理各测试在finally块调用tempWorkspace.cleanup()fs.rmSync(dirPath, { recursive: true, force: true })。清理失败策略严格执行需求约定清理失败必须 throwcleanupE2EAionrsConversations在获取对话列表失败时直接抛错不允许静默失败污染后续用例。八、已知问题运行时切换后消息静默挂起文档记录了一个影响 4 个用例TC-A-04/07/08/09的关键缺陷implementation-mapping.zh.md在对话中切换 model 或 permission 后后续消息发送时 aionrs binary 静默挂起AI 回复永不到达。8.1 症状与复现路径以 TC-A-08 为例创建 modelA default 对话 → 首条消息正常回复 → UI 切换 modelA→modelB → default→yolo → modelB→modelA → 发送第二条消息 →conv.status卡在running或pending2.7 分钟后超时。8.2 数据库现场证据超时 dump 显示消息停留在 3 条用户消息 2 条 AI 回复 1 条第二条 AI 回复缺失[waitForAionrsReply TIMEOUT] conv.statuspending, msg count3 [waitForAionrsReply TIMEOUT] - posright typetext statusnull previewHello, initial message. [waitForAionrsReply TIMEOUT] - posleft typetext statusnull previewHello! How can I help today? [waitForAionrsReply TIMEOUT] - posright typetext statusnull previewAfter all switches.8.3 已排除项与待排查项已通过测试脚本、bridge 通信、非切换场景三条路径确认问题不在测试侧第二条消息已成功入库、bridge → main process 路径正常、TC-A-01/02/03 无切换场景均正常完成。待排查方向aionrs binary 运行时状态机是否支持 model/permission 切换、切换后 binary 进程是否正确重启/重新初始化、运行时变更后的环境变量/配置文件是否生效。当前处理策略是将四个用例标记为test.skip()并在注释中记录原因等待产品侧诊断 binary 运行时切换逻辑重开条件为产品团队确认 binary 支持运行时切换或提供 workaround。该问题同时揭示了实际用户场景风险对话中切换 model 或 permission 后后续消息可能无响应——这正是 E2E 提前暴露生产隐患的价值所在。九、截图策略与测试质量指标9.1 截图规范每个用例最少 3 张截图test-cases.zh.mdguid 页选择 agent 后 → 对话页首条消息发送后 → 对话完成后。实际实现中takeScreenshot调用总计 60 次文档统计为 61 次含一次差异核对平均 4.0 张/测试截图目录按chat-aionrs/tc-a-XX/NN-阶段.png组织便于回归比对。9.2 质量指标汇总截图覆盖率15/15100%测试均含截图全部满足至少 3 张规则用例完整性P0 5/5、P1 7/7、P2 3/3但需重写分布均衡性6 个文件承载 15 个测试平均每文件 2.5 个最大文件mid-conversation-switch.e2e.ts占 13.3%文件/测试数比 0.4略分散于 Gemini 的 0.33属合理范围按优先级分组P0 19 张均 3.8、P1 32 张均 4.6、P2 9 张均 3.0。十、维护流程如何让映射文档保持新鲜文档维护遵循明确的触发条件与更新流程implementation-mapping.zh.md。触发条件包括新增用例、修改用例 ID/标题、调整优先级、重构测试文件结构、完成 TC-A-13/14/15 重写。更新流程的第一步是用命令行重新统计各文件的截图数for file in tests/e2e/features/conversations/aionrs/*.e2e.ts; do echo $(basename $file): $(grep -c takeScreenshot $file); done随后依次更新统计概览数字、对应映射表行、校验分组小计等于总数最后提交变更并注明修改原因。这套映射文档 统计脚本 偏差清单的组合让测试资产的定义与实现始终保持可追溯、可审计的状态。十一、工程启示与可复用要点定义与实现分离治理test-cases.zh.md管该测什么implementation-mapping.zh.md管实际测了什么偏差显式记录并区分合理演化保留实现、更新定义与严重偏差按原定义重写避免文档漂移bridge 优先 UI 补充的双通道策略P0 主干用例直接经 IPC bridge 驱动create-conversation、chat.send.message以提升确定性而权限/模型选择等 UI 交互用例则走真实点击路径兼顾稳定性与覆盖度DB 层断言是最终真相UI 断言可能随重构变化但conversations.extra.sessionMode、extra.workspace、消息 position/type/createdAt 的持久化结果不会撒谎前置条件不可达时优雅降级binary 缺失、provider 不足、模型数不足时统一test.skip并附原因保证 CI 报告是skipped 而非 failed避免环境噪音淹没真实回归信号。对希望在本仓库继续深入的同学建议按此顺序阅读先看 test-cases.zh.md 理解用例意图再对照 implementation-mapping.zh.md 的映射表逐个打开tests/e2e/features/conversations/aionrs/下的 6 个实现文件最后以 chatAionrs.ts 为辅助层索引通读全部 helper 语义即可完整掌握 AionUi aionrs 通道的 E2E 验证全貌。【免费下载链接】AionUiOpen-source 24/7 Cowork app for OpenClaw, Hermes, Claude Code, Codex, OpenCode and 20 more CLI Agent | Customize your assistants | Team them upStar if you like it!项目地址: https://gitcode.com/GitHub_Trending/ai/AionUi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价