ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AionUi 助手设置页 E2E 测试开发实录:源码反推需求与多角色评审驱动的测试工程方法论

2026/9/10 15:05:06 拓冰建站 浏览量
AionUi 助手设置页 E2E 测试开发实录:源码反推需求与多角色评审驱动的测试工程方法论 AionUi 助手设置页 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导读本文基于 AionUi 仓库中tests/e2e/docs/assistants/discussion-log.zh.md这份完整的多角色协作讨论日志还原Assistant 设置页从需求反推门 1、测试用例设计门 2到 E2E 落地迭代门 3的完整流程。读者将看到如何以源码为唯一事实来源反推 62 条功能需求、如何通过 Analyst / Engineer / Designer 三角色交叉评审识别 3 个源码级争议、如何把 38 条补充测试细化为带 Playwright 代码的可执行用例以及在实施中如何通过三轮修订修正根本性设计错误。这套方法论对任何希望为复杂 UI 页面构建高可信 E2E 测试的团队都具直接参考价值。1. 背景一个以源码为唯一事实来源的 E2E 测试工程AionUi 是一个开源的 24/7 Cowork 桌面应用集成了 OpenClaw、Hermes、Claude Code 等多款 CLI Agent并提供助手Assistant管理、技能Skills库、团队协作等能力。其中Assistant 设置页承担了所有 AI 助手的创建、编辑、启用/禁用、复制、删除等核心管理功能是用户高频使用的复杂表单页面。为了给该页面补齐 E2E 测试仓库中的tests/e2e/docs/assistants/目录沉淀了一套完整的文档链requirements.zh.md需求文档 v1.1门 1 定稿基于源码反推明确不以现有 specs 测试行为作为需求来源test-cases.zh.md测试用例文档 v1.338 个可执行 Playwright 用例discussion-log.zh.md多角色协作讨论日志本文主角完整记录 12 轮工作记录implementation-mapping.zh.md实施映射测试与源码的对应关系。这套流程围绕一个核心原则展开——源码是唯一事实来源需求逐条标注源码文件与行号评审逐条回源码验证测试断言以源码实际行为为准而非文档设想。下面按门gate推进顺序还原整个过程。2. 门 1从源码反推 61 条功能需求2.1 Analyst 起草与逐条对照验证第 1 轮由assistant-analyst-2负责起草需求初稿其做了什么包括四项关键动作通读已由主 agent 越权撰写的requirements.zh.md草稿约 24.7K确认结构合理源码验证逐条对照 4 个关键源码文件index.tsx、AssistantListPanel.tsx、AssistantEditDrawer.tsx、assistantUtils.ts验证 61 条功能需求的文件路径/行号准确性测试场景映射确认 33 个已覆盖测试用例crud 15 条 permissions 8 条 skills 10 条与需求 ID 的映射正确补充测试范围分级为 32 条未被覆盖的需求分配 P0核心交互 5 条/ P1重要 UI 状态 25 条/ P2边界 2 条优先级。验证结论为全绿所有行号引用抽查正确btn-create-assistant、assistant-edit-drawer等 testid 标识符与实际 DOM 一致33 个测试用例全部映射到需求 ID。从配套需求文档可以看到这批需求的具体形态例如列表展示 F-L-01 ~ F-L-10 中的典型条目requirements.zh.md 第 2 章#需求源码追溯F-L-04Extension 助手的启用开关始终为 on 且 disabledAssistantListPanel.tsx:159-161F-L-05列表按 Enabled / Disabled 分为两个区段各带标题与数量AssistantListPanel.tsx:180-192, 279-283F-L-08过滤为空时显示 No assistants match the current filters.AssistantListPanel.tsx:284-290在当前仓库中AssistantListPanel.tsx 依然可验证这些行为卡片使用dnd-kit实现拖拽排序canDelete assistant.source user、canDuplicate assistant.source ! user的权限分支与需求文档 F-D-01 的行级操作逻辑一一对应。2.2 三个争议点的源码证据链Analyst 在验证过程中发现 3 个待讨论事项这是整份日志中最有价值的冲突样本争议 1Extension Name 输入权限矛盾后确认是源码 bug设计意图index.tsxL9 权限表Extension Name 应为 read-only源码实际AssistantEditDrawer.tsxL280disabled{activeAssistant?.isBuiltin}而 Extension 的isBuiltinfalse导致 Name 输入框未被禁用。争议 2Extension showSkills 行为后确认为预期行为源码AssistantEditDrawer.tsxL131-134showSkills isCreating || ... || (!activeAssistant.isBuiltin)Extension 满足第三个条件因此Skills 区会显示但因isExtensionAssistant判断字段只读测试specs/skills S-09extension assistant drawer opens without error通过。争议 3Edit 模式 Save 是否自动关闭 Drawer需实际验证specs 注释crud L249Edit save does not auto-close the drawer但文档与实现存在待确认空间。这三个争议点展示了设计文档 vs 实现的典型张力后续 Engineer 与 Designer 的评审正是围绕它们展开的。为便于 Reviewer 核对Analyst 在日志中附上了审阅检查清单第 2 章 61 条需求是否遗漏、第 3 章 4 条关键路径描述、第 5 章 13 条边界场景、第 7 章 33 个测试映射、第 8 章 P0/P1/P2 分级、第 9 章 3 个争议点是否需升级。3. 双 Review工程师的可测试性审查与设计师的 UX 补漏3.1 Engineer Review以可测试性/可观测性为标尺assistant-engineer-2从四个维度独立审查需求文档源码追溯准确性、testid 标识符完整性、P0 核心交互技术可行性、争议点技术判断。源码追溯抽查全部通过包括Extension Name 权限矛盾L280确认disabled{activeAssistant?.isBuiltin}showSkills 逻辑L131-134确认 Extension 满足!activeAssistant.isBuiltin分支highlightId 滚动逻辑AssistantListPanel L66-81确认 2 秒高亮 onHighlightConsumed回调intent 自动打开index.tsx L105-137确认 sessionStorage route state 两条路径搜索图标切换AssistantListPanel L236-240确认isSearchVisible ? CloseSmall : Search。data-testid 契约审计是本次评审的重点产出。通过Grep>// P0-1: 搜索栏展开/折叠 const searchToggle page.locator([data-testidbtn-search-toggle]); const searchInput page.locator([data-testidinput-search-assistant]); // 验证初始状态 await expect(searchInput).toBeHidden(); // 点击展开 await searchToggle.click(); await expect(searchInput).toBeVisible(); await expect(searchInput).toBeFocused(); // 验证 autoFocus文档同时给出了 10 类无 testid 元素的组合 selector 方案例如// AddSkillsModal 外部源 pill modal.locator(button).filter({ has: page.locator(span[class*px-6px]) }); // Drawer Close 图标 drawer.locator(.arco-drawer-header).locator(svg[class*close]).first(); // Rules Expand 按钮 drawer.locator(button).filter({ hasText: Expand });4.2 Analyst 覆盖度 Review38 个用例 1:1 完整映射Analyst 对 test-cases v1.0 做了逐条映射验证结论是38 个用例与需求清单 1:1 完整映射P06/6、P127/27、P25/5100% 覆盖并发现一个有意思的细节需求文档第 8 章标题写的是37 条实际条目数是38 条P06 / P127 / P25建议在文档开头补充总览。抽查的关键用例需求 ID 映射全部准确P0-1 → F-S-01/02/03/08P0-6 → 2.5.3P1-18 → F-SK-10P2-1 → B-14。步骤合理性检查也通过P0-4 的等待时间200ms略大于需求150ms但作为测试 buffer 合理P1-22 的宽度断言与公式完全一致480px → 480、1024px → 512、2048px → 1024。同时提出两个问题6 个依赖外部数据的用例P1-14/15/16/17/21、P2-3标注为 skip长期 skip 会导致回归无法检测建议门 3 优先 mockP0-2 清理操作未明确断言 Switch 恢复到初始状态建议补充const isCheckedRestored await switchElement.isChecked(); expect(isCheckedRestored).toBe(isCheckedBefore);4.3 Engineer 可执行性 Review31 可直接实施Engineer 从能否执行 前置条件能否构造 每一步是否可观测三个角度审查产出关键统计可直接实施 31 个用例81.6%P0 全部 6 个、P1 中 18 个、P2 中 3 个需 skip 或前置准备 7 个18.4%依赖 Extension 助手P0-6、P1-6、Pending/Custom 技能P1-14~17、Auto-injected 技能P1-18、外部技能源P1-20/21、P2-35 处建议补充 testidP1 优先级非阻塞。对 10 类无 testid 元素的组合 selector 做了稳定性评级Arco 标准类名.arco-drawer-header .arco-icon-close、.arco-tabs-header-title、.arco-btn-status-danger为高依赖文本/i18n 的pill、Add 按钮、Cancel、Expand、删除按钮为中等建议补充 5 个 testiddata-source、btn-add-skill、btn-cancel、btn-expand-rules、btn-delete-skill。断言准确性评估提出了三个关键改进P0-1 图标切换不要只断言 SVG 存在改用行为验证点击后输入框可见 初始是 Search 图标更鲁棒P1-13 状态点颜色getComputedStyle(el).background返回完整 CSS 值需解析改用 class 判断如toContain(bg-green)P1-22 Drawer 宽度浏览器渲染可能有 1-2px 误差断言改为expect(Math.abs(actualWidth - expectedWidth)).toBeLessThanOrEqual(2)。Mock 方案方面P1-23sessionStorage intentPlaywright 原生支持直接page.evaluate写入即可P2-5dialog.showOpen直接覆盖window.electron.dialog可能与 preload 的 IPC 不一致更可靠的是通过electronApp.evaluate()在 main process mockawait electronApp.evaluate(async ({ dialog }) { dialog.showOpenDialog () Promise.resolve({ canceled: false, filePaths: [/mock/selected/path] }); });清理策略上推荐统一afterEachhook清空搜索 → 关闭 Drawer → 恢复 viewport → 按名称前缀E2E Test删除测试创建的助手而非 38 个用例各自内联清理。5. 门 3E2E 落地与三轮迭代修正5.1 配置变更与首批成果实施前需修改 playwright.config.tstestDir从./tests/e2e/specs改为./tests/e2e使测试扫描范围覆盖specs/与features/两个目录保持testMatch: **/*.e2e.ts与workers: 1不变——由于测试共享单例 Electron 应用实例worker 数必须为 1。首批实现产出两个测试文件tests/e2e/features/assistants/core-interactions.e2e.ts6 个 P0 测试全部通过与tests/e2e/features/assistants/ui-states.e2e.ts13 个 P1 测试通过、1 个 P1-9 因缺 testid 跳过每个测试保留 3~5 张截图到tests/e2e/screenshots/assistants/。运行结果E2E_DEV1 bun run test:e2e tests/e2e/features/assistants/ Running 20 tests using 1 worker ✓ 1-6 core-interactions.e2e.ts P0-1 ~ P0-6 (26.0s) ✓ 7-14 ui-states.e2e.ts P1-1 ~ P1-8 (11.8s) - 15 ui-states.e2e.ts P1-9 (skipped) ✓ 16-20 ui-states.e2e.ts P1-10 ~ P1-13, P1-25 (12.3s) 1 skipped / 19 passed (50.1s)5.2 实施中的五项技术决策这些踩坑决策对 Electron Playwright 测试极具参考价值① 避免page.goto()Electron E2E 中page.goto(/#/...)与 HashRouter 不兼容改用window.location.hashawait page.evaluate((id) { window.location.hash /settings/assistants?highlight${id}; }, targetId);② i18n 文本用正则匹配UI 有中英双语hardcode 英文会致中文环境失败await expect(modal.locator(.arco-modal-title)).toContainText(/Delete|删除/i);③ Drawer 关闭用 helperpage.keyboard.press(Escape)有时不可靠封装closeDrawer()可见则按 Escape waitFor({ state: hidden })在清理操作中统一复用。④ 隐藏元素只断言可见性await expect(searchInput).toBeHidden()即可不要对隐藏元素断言toHaveValue()。⑤ Hover 验证显式移开鼠标移到 (0,0) 不可靠改为 hover 到页面其他元素触发 unhover再等待 200ms 断言。5.3 第一轮修正可测性调整空态验证方案Engineer 实现 P1-14 ~ P1-18 时发现这 5 个用例依赖无法通过 invokeBridge 构造的数据Pending Skills 是 AddSkillsModal 中的临时 React state未持久化Custom Skills 需预置外部文件系统路径含 SKILL.mdAuto-injected Skills 依赖 Builtin 助手特定配置。同时 team-lead 有禁止 test.skip 的硬性要求。Designer 提出两方案方案 A采用——改为空态验证方案 B未采用——降级 P2 并标注需真实环境。空态验证同样有价值验证无此类数据 → 不显示对应 UI的逻辑且不依赖外部环境、立即可测。P1-14/15/16/17/18 分别改为无 Pending 时不显示 PENDING 标签无 Custom 时不显示 CUSTOM 标签删除 Builtin 技能触发通用弹窗取消操作已合并到 P1-16无 Auto-injected 时不显示该分组。用例数量38、P0/P1/P2 分级、覆盖需求均不变。5.4 第二轮修订三个实施失败后的根因修正Engineer 实现后报告 3 个失败Designer 逐一做根因分析P1-15 失败前一用例 P1-14 结尾未执行清理drawer 未关闭导致btn-create被遮挡——修订为所有清理操作提供可执行代码EscapetoBeHidden({ timeout: 3000 })P1-16 失败[class*skill-card]定位器错误——实际 DOM 是通用 flex 容器div.flex.items-start.gap-8px.p-8px且删除按钮opacity-0需先 hover 再点击P1-18 失败设计时假设大部分 Builtin 助手没有 Auto-injected 配置但实际 assistantPresets 中几乎所有 Builtin 助手都有defaultEnabledSkillsword-creator、ppt-creator、excel-creator、cowork 等只有 code-interpreter、claude-code 等极少数没有——P1-18 从空态验证反转为正向验证有 Auto-injected 时显示该分组 N/M 计数。5.5 第三轮修订P1-16 的根本性设计错误Engineer 按新定位器实现 P1-16 时delete button 定位 30s 超时——即使已 hover按钮也未出现。Designer 查看源码后发现这是一个设计层面的根本性错误Builtin Skills 卡片根本没有删除按钮只有 Checkbox取消勾选 取消激活不是删除只有 Pending/Custom Skills 才有删除按钮opacity-0 group-hover:opacity-100点击后调用setDeletePendingSkillName/setDeleteCustomSkillName新创建的 Custom assistantbuiltinSkillItems从availableSkills过滤初始为空F-SC-01/F-SC-02删除弹窗需求只对 Pending/Custom 适用而这两类技能需外部依赖构造。最终采用方案 AP1-16 完全重写为Builtin Skills 通过 Checkbox 取消勾选不触发删除弹窗8 步打开 Drawer → 展开 Builtin 分组 → 验证有可用技能 → 取消勾选 → 断言无弹窗modal.toHaveCount(0)→ 断言已取消勾选 → 恢复原状态覆盖需求从 F-SC-01/02 改为 F-SK-08P1-17 标记为不可测已废弃。这轮修订揭示了一个重要教训在设计测试用例前必须精读目标组件的 DOM 结构与交互能力矩阵否则看似合理的场景可能是完全不可测的。同时它也是文档化决策的典范——废弃原因、源码证据L487-497、L527-537、L570-599全部留痕。6. 方法论沉淀从这份讨论日志可以学到什么6.1 源码是唯一事实来源文档只是提案整份日志贯彻一个原则需求、测试断言、权限表都以源码实际行为为准设计意图与实现冲突时如争议 1 的 Extension Name先记录差异、再判定是 bug 还是预期、最后给出双向修复路径。反推需求时逐条标注文件:行号让评审可以在 5 分钟内复核任意一条需求。6.2 contenteditable="false">【免费下载链接】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),仅供参考