主题
测试与质量保证
本文引用的源码文件
本文引用的文件
- package.json
- vitest.config.js
- playwright.config.js
- eslint.config.js
- vite.config.js
- .github/workflows/release.yml
- .github/workflows/test-install.yml
- test/setup/chrome-mock.js
- test/setup/jsdom-globals.js
- test/e2e/content-tools.e2e.spec.js
- test/e2e/helpers/load-module.js
- test/unit/activity-store-write-coalescing.unit.test.js
目录
引言
本文件面向 AI Helper(Chrome 扩展 + 本地 Agent)项目的测试与质量保证体系,覆盖单元测试、端到端测试、代码质量工具、持续集成与发布门禁,以及测试编写与维护最佳实践。项目采用双进程架构:扩展端基于 Manifest V3,Agent 端为独立 Node.js 服务;两端版本保持同步(当前以 2.3.1 为准)。测试体系分为两套且不可混跑:扩展端使用 Vitest 进行单元测试与部分 E2E 辅助能力,Playwright 负责真实浏览器自动化;Agent 端使用 Node.js 内置测试运行器,并限定在 agent/test/unit 目录执行。
项目结构
仓库的测试相关根配置与脚本集中在以下位置:
- 测试入口与命令:package.json
- 单元测试框架:vitest.config.js
- 端到端测试框架:playwright.config.js
- 静态检查:eslint.config.js
- 构建产物与源码映射控制:vite.config.js
- 持续集成与发布:.github/workflows/release.yml、.github/workflows/test-install.yml
- 测试环境桩与补丁:test/setup/*
- 示例 E2E 用例:test/e2e/*.spec.js
- 示例单元测试:test/unit/*.unit.test.js
graph TB A["package.json<br/>测试脚本入口"] --> B["vitest.config.js<br/>单元测试配置"] A --> C["playwright.config.js<br/>端到端测试配置"] A --> D["eslint.config.js<br/>代码风格与静态检查"] A --> E[".github/workflows/*.yml<br/>CI/CD 流程"] F["vite.config.js<br/>构建与 sourcemap 策略"] --> E G["test/setup/*<br/>测试环境桩与补丁"] --> B H["test/e2e/*<br/>浏览器自动化用例"] --> C I["test/unit/*<br/>单元与行为回归用例"] --> B
图示来源
- package.json#L6-L23
- vitest.config.js#L1-L12
- playwright.config.js#L1-L19
- eslint.config.js#L1-L15
- vite.config.js#L27-L41
- .github/workflows/release.yml#L49-L67
- .github/workflows/test-install.yml#L26-L79
章节来源
- package.json#L6-L23
- vitest.config.js#L1-L12
- playwright.config.js#L1-L19
- eslint.config.js#L1-L15
- vite.config.js#L27-L41
核心组件
本节聚焦测试与质量保障的核心配置与职责边界。
测试脚本与命令
- npm run test:unit 调用 Vitest 执行 test/unit 下的单测。
- npm run test:e2e 调用 Playwright 执行 test/e2e 下的浏览器自动化用例。
- npm run lint 对 src/ 与 agent/ 执行 ESLint。
- npm run build:silent 用于统一验证构建产物。
单元测试(Vitest)
- 默认运行环境为 node,全局 API 可用。
- 通过 setupFiles 注入 chrome API 最小桩与 jsdom 缺失 API 补丁。
- 测试文件匹配规则为 test/unit/**/*.test.js。
- 针对需要 DOM 的用例,可在文件头使用注释切换为 jsdom 环境。
端到端测试(Playwright)
- 测试目录为 test/e2e。
- 启用并行执行,CI 下允许一次重试。
- 使用 headless Chromium,动作超时 10 秒。
- 通过 helpers 将 content script 模块打包为 IIFE 注入页面,并在 page 上下文调用工具函数。
代码质量(ESLint)
- 显式纳入 agent 子包检查,仅排除 dist、libs、scripts 与 agent/node_modules、agent/dist。
- 开启若干基础错误规则,避免常见语法与语义问题。
构建与源码映射
- Vite 关闭 sourcemap,防止调试信息随扩展包公开。
- 构建输出到 dist,包含 background、content、side_panel、options 四个入口。
章节来源
- package.json#L6-L23
- vitest.config.js#L1-L12
- playwright.config.js#L1-L19
- eslint.config.js#L1-L15
- vite.config.js#L27-L41
架构总览
测试与质量保障的整体流程如下:开发者提交代码后,CI 触发构建与发布流程;本地开发时可通过脚本分别运行单元测试与 E2E 测试;ESLint 贯穿开发与 CI,确保代码风格与基本安全规则。
flowchart TD Dev["开发者修改代码"] --> Lint["ESLint 静态检查"] Dev --> Unit["Vitest 单元测试"] Dev --> E2E["Playwright 端到端测试"] Unit --> Build["Vite 构建扩展"] E2E --> Build Build --> Release["GitHub Actions 构建与发布"] Release --> Artifacts["生成 zip 并发布到 GitHub/Gitee"]
图示来源
详细组件分析
单元测试框架:Vitest 配置与使用
运行环境与初始化
- 默认 node 环境,globals 开启,setupFiles 加载 chrome-mock 与 jsdom-globals。
- chrome-mock 提供最小 chrome.* stub,避免 import 链意外访问 chrome 导致 ReferenceError。
- jsdom-globals 补齐 Element.scrollIntoView、scrollTo 与 NodeList.prototype.some/map/filter,使 DOM 逻辑可运行。
测试组织与断言
- 测试文件位于 test/unit,命名以 .unit.test.js 结尾。
- 使用 Vitest 提供的 describe/it/expect/vi 等 API。
- 典型模式包括:
- 用 vi.resetModules 与替换 globalThis.chrome.storage 实现模块级状态重置与存储桩。
- 用 vi.useFakeTimers 与 advanceTimersByTimeAsync 控制时间,验证防抖与即时落盘行为。
- 用 readFileSync 读取源码文本,断言热路径零逐次 IPC 与接线正确性。
Mock 策略
- 存储层:构造 makeFakeStorage,模拟 structuredClone 序列化语义,支持注入 set 失败场景,验证脏标与重试。
- Chrome API:chrome-mock 提供空操作对象,避免污染被测纯函数。
- 计时器:vi.useFakeTimers 精确控制异步合并与即时刷新的时序。
覆盖率报告
- 当前 vitest.config.js 未显式开启覆盖率插件或 reporter;如需覆盖率,可在 test 字段中添加 coverage 配置项。
flowchart TD Start(["进入测试"]) --> Setup["加载 setupFiles<br/>chrome-mock / jsdom-globals"] Setup --> TestRun["执行 test/unit 用例"] TestRun --> MockStorage["makeFakeStorage 模拟存储"] TestRun --> FakeTimers["vi.useFakeTimers 控制时间"] TestRun --> Assertions["断言形状/上限/合并/失败重试/即时刷"] Assertions --> End(["测试完成"])
图示来源
- vitest.config.js#L1-L12
- test/setup/chrome-mock.js#L1-L32
- test/setup/jsdom-globals.js#L1-L24
- test/unit/activity-store-write-coalescing.unit.test.js#L23-L60
章节来源
- vitest.config.js#L1-L12
- test/setup/chrome-mock.js#L1-L32
- test/setup/jsdom-globals.js#L1-L24
- test/unit/activity-store-write-coalescing.unit.test.js#L1-L224
端到端测试框架:Playwright 设置与用例
配置要点
- testDir 指向 test/e2e。
- fullyParallel 启用并行执行。
- CI 下 forbidOnly 生效,retries=1。
- use.headless=true,actionTimeout=10000。
- projects 定义 chromium 桌面设备。
测试环境搭建
- 通过 helpers/load-module.js 使用 esbuild 将 content script 模块打包为 IIFE,注入到页面 window.__tools。
- 每个用例 beforeAll/beforeEach 中注入 bundle,保证测试隔离。
- fixtures 提供 form-page.html、iframe-page.html、shadow-dom-page.html 等静态页面,用于表单、iframe、Shadow DOM 等场景。
浏览器自动化与交互
- 通过 callTool(page, fnName, ...args) 在 page.evaluate 中调用 window.__tools 暴露的工具函数。
- 用例覆盖查询元素、点击、输入、下拉选择、滚动收集、链接提取、表格转 JSON、正则搜索、iframe 内容获取、分页 ref 稳定性、叠加层提升等。
视觉回归测试
- 当前仓库未引入截图比对或视觉回归库;如需添加,可在用例中使用 page.screenshot() 并结合基线对比工具。
测试数据管理
- 使用 fixtures 目录中的 HTML 页面作为稳定数据源。
- 对于复杂交互,优先使用确定性选择器与可观测状态断言。
sequenceDiagram participant PW as "Playwright" participant Page as "浏览器页面" participant Helper as "helpers/load-module.js" participant Tools as "window.__tools" PW->>Helper : getContentBundle() Helper-->>PW : IIFE 字符串 PW->>Page : addInitScript(IIFE) Page->>Tools : 挂载工具函数 PW->>Page : goto(fixtureUrl) PW->>Page : evaluate(callTool(fn,args)) Page->>Tools : 执行工具函数 Tools-->>Page : 返回结果 Page-->>PW : 断言成功/失败
图示来源
- playwright.config.js#L1-L19
- test/e2e/helpers/load-module.js#L1-L46
- test/e2e/content-tools.e2e.spec.js#L1-L251
章节来源
- playwright.config.js#L1-L19
- test/e2e/helpers/load-module.js#L1-L46
- test/e2e/content-tools.e2e.spec.js#L1-L251
代码质量工具:ESLint 配置与静态分析
范围与排除
- 显式纳入 agent 子包,避免历史 ignores 导致的“无检查”盲区。
- 排除 dist、libs、scripts、agent/node_modules、agent/dist,避免扫描第三方与产物。
规则
- 开启 no-debugger、no-dupe-args、no-func-assign、no-obj-calls 等基础错误规则。
- 建议后续结合 @antfu/eslint-config 提供更完整的风格与安全规则集。
运行方式
- npm run lint 对 src/ 与 agent/ 执行检查。
- 建议在 CI 中将 lint 作为门禁步骤。
章节来源
持续集成与发布门禁
安装器生命周期验证(test-install.yml)
- Windows Runner 上执行 install.ps1 全流程:安装 → 工件校验 → aha status + API 连通性 → 更新检查 → 卸载 → 残留检查。
- Unix 管道安装复现 curl|bash 等价语义,校验安装版本与服务在线。
- Windows iex 探针验证 param/env 回退与 irm|iex 全流程。
发布流程(release.yml)
- 触发条件:推送 v* 标签或手动触发。
- 构建扩展、校验 dist/manifest.json、打包 zip(不含 .map)、上传构件、创建 GitHub Release。
- 同步 tag 到 Gitee,创建或更新发行版说明,附件上传带重试与旧附件清理。
flowchart TD Trigger["推送 v* 或手动触发"] --> Checkout["检出代码"] Checkout --> SetupNode["安装 Node 22 与依赖"] SetupNode --> Build["npm run build"] Build --> Verify["校验 dist/manifest.json"] Verify --> Package["打包 ai-helper-*.zip不含 .map"] Package --> GHRelease["创建 GitHub Release"] GHRelease --> SyncGitee["同步 tag 到 Gitee"] SyncGitee --> PublishGitee["创建/更新 Gitee 发行版说明"] PublishGitee --> AttachZip["上传 zip 附件含重试与清理"]
图示来源
- .github/workflows/release.yml#L49-L67
- .github/workflows/release.yml#L86-L127
- .github/workflows/release.yml#L141-L340
章节来源
- .github/workflows/test-install.yml#L26-L79
- .github/workflows/test-install.yml#L86-L111
- .github/workflows/test-install.yml#L113-L155
- .github/workflows/release.yml#L49-L67
- .github/workflows/release.yml#L86-L127
- .github/workflows/release.yml#L141-L340
测试编写指南与最佳实践
命名规范
- 单元测试:文件名以 .unit.test.js 结尾,描述被测功能或修复编号(如 activity-store-write-coalescing.unit.test.js)。
- 端到端测试:文件名以 .e2e.spec.js 结尾,描述用户流程或页面区域(如 content-tools.e2e.spec.js)。
断言策略
- 优先断言可观测状态(DOM 文本、属性、输入值),而非内部实现细节。
- 对并发与竞态场景,使用夹具复现旧实现丢更新的行为,同时断言新实现一条不丢。
异步测试处理
- 使用 vi.useFakeTimers 与 advanceTimersByTimeAsync 控制时间,验证防抖与即时落盘。
- 在 E2E 中利用 page.waitForFunction 等待特定 UI 状态(如 :popover-open)。
错误模拟
- 存储层注入 failNextSet,验证脏标保留与下一次落盘合并失败批。
- 关键审计类别走即时落盘,普通命令走防抖合并。
模块化与隔离
- 使用 vi.resetModules 与替换 globalThis.chrome.storage 重置模块单例状态。
- E2E 用例通过 beforeAll/beforeEach 注入 bundle,保证页面上下文隔离。
章节来源
- test/unit/activity-store-write-coalescing.unit.test.js#L76-L170
- test/e2e/content-tools.e2e.spec.js#L104-L122
测试维护策略与性能测试方法
维护策略
- 新增功能应配套单元测试与 E2E 用例,确保行为不变量与接线守卫不被破坏。
- 对性能敏感路径(如活动日志与工具统计写放大)增加并发对照用例,防止回归。
性能测试方法
- 使用 fake storage 模拟高并发写入,验证内存权威态与防抖合并的正确性。
- 通过断言 setCalls 次数与数据长度,确认热路径零逐次 IPC。
质量门禁
- 在 CI 中运行 npm run lint、npm run test:unit、npm run test:e2e。
- 发布流程强制校验 dist/manifest.json 与 zip 不包含 .map。
章节来源
- test/unit/activity-store-write-coalescing.unit.test.js#L172-L224
- .github/workflows/release.yml#L58-L67
- .github/workflows/release.yml#L93-L100
依赖关系分析
测试与质量工具的依赖关系如下:
graph LR Pkg["package.json"] --> Vitest["vitest.config.js"] Pkg --> Playwright["playwright.config.js"] Pkg --> ESLint["eslint.config.js"] Pkg --> Vite["vite.config.js"] Vitest --> SetupChrome["test/setup/chrome-mock.js"] Vitest --> SetupJSDOM["test/setup/jsdom-globals.js"] Playwright --> E2EHelpers["test/e2e/helpers/load-module.js"] Playwright --> E2ETests["test/e2e/*.spec.js"] Vitest --> UnitTests["test/unit/*.unit.test.js"]
图示来源
- package.json#L6-L23
- vitest.config.js#L1-L12
- playwright.config.js#L1-L19
- eslint.config.js#L1-L15
- vite.config.js#L27-L41
- test/setup/chrome-mock.js#L1-L32
- test/setup/jsdom-globals.js#L1-L24
- test/e2e/helpers/load-module.js#L1-L46
章节来源
- package.json#L6-L23
- vitest.config.js#L1-L12
- playwright.config.js#L1-L19
- eslint.config.js#L1-L15
- vite.config.js#L27-L41
性能考虑
单元测试性能
- 使用 fake storage 与 vi.useFakeTimers 避免真实 I/O 与时间不确定性,提高测试稳定性与速度。
- 通过断言 setCalls 次数验证防抖合并,减少不必要的持久化开销。
E2E 性能
- Playwright 启用并行执行,缩短整体测试时长。
- 使用 fixture 页面与确定性断言,降低不稳定因素。
构建与发布
- 关闭 sourcemap,减小发布包体积,避免泄露源码。
- CI 中校验 zip 不包含 .map,防止调试信息外泄。
[本节为通用指导,无需具体文件引用]
故障排查指南
单元测试无法访问 chrome.*
- 确认 vitest.config.js 已加载 test/setup/chrome-mock.js。
- 若用例需要 DOM,确保文件头使用注释切换到 jsdom 环境,并加载 test/setup/jsdom-globals.js。
E2E 用例找不到工具函数
- 检查 helpers/load-module.js 是否正确打包并注入 window.__tools。
- 确认 beforeAll/beforeEach 中调用了 addInitScript 注入 bundle。
CI 安装器测试失败
- 查看 test-install.yml 各步骤日志,确认 install.ps1/install.sh 参数与环境变量。
- 校验 API 连通性与嵌入 Node 版本是否符合预期。
发布流程失败
- 检查 GITEE_TOKEN 是否配置,权限是否勾选 projects。
- 确认 dist/manifest.json 存在且 zip 不包含 .map。
章节来源
- vitest.config.js#L1-L12
- test/setup/chrome-mock.js#L1-L32
- test/setup/jsdom-globals.js#L1-L24
- test/e2e/helpers/load-module.js#L1-L46
- .github/workflows/test-install.yml#L26-L79
- .github/workflows/release.yml#L58-L67
- .github/workflows/release.yml#L93-L100
结论
本项目测试与质量保证体系围绕 Vitest 与 Playwright 展开,辅以 ESLint 静态检查与完善的 CI/CD 流程。单元测试强调行为不变量、并发对照与接线守卫;端到端测试聚焦真实浏览器交互与工具链路;发布流程严格校验构建产物与附件完整性。遵循本文档的编写与维护策略,可有效提升代码质量、降低回归风险,并确保扩展与 Agent 端的稳定交付。
[本节为总结性内容,无需具体文件引用]
附录
常用命令
- npm run test:unit:运行单元测试。
- npm run test:e2e:运行端到端测试。
- npm run lint:执行 ESLint。
- npm run build:silent:统一验证构建。
参考用例路径
- 单元测试示例:test/unit/activity-store-write-coalescing.unit.test.js
- 端到端示例:test/e2e/content-tools.e2e.spec.js
- E2E 辅助模块:test/e2e/helpers/load-module.js
章节来源