Skip to content

TESTING —— agentaily monorepo(测试真相源)

这个仓怎么测:分层、框架选型、在哪道闸拦回归。是测试策略的单一出处 —— 改选型 / 护栏 / 分层,同一次改动更新本文件(文档与代码同步)。

  • 真相源同侪:SPEC.md(规格)· ARCHITECTURE.md(架构)· ROADMAP.md(能力进度)· 本文件(测试)。
  • 一句话:vitest 4 一把梭,靠根 vitest.config.tsprojects 把不同环境的包编排到一起跑(纯逻辑包跑 Node,带 React/DOM 的包跑各自的 jsdom 配置)。
  • 双循环方法论配套:本仓用「BDD 外环 + TDD 内环 + sub-agent 分工」组织开发 —— 角色边界 / 交接协议 / 五条铁律 / 编排策略见 .claude/agents/README.md。下面这套分层正是 implementer(内环,红→绿→重构)/ outer-tester(外环,验收)把 spec-architect 写的 features/ 行为契约 realize 出来、并在护栏上拦回归的方式。

测试分层(多而快在下,少而真在上)

海拔 / 环谁写框架 / 环境测什么位置跑在哪
unit 纯逻辑单测内环(TDD,最多最快)implementervitest · node 环境aml / 数据引擎 / 迁移 / agent loop / 市场数据层 / VFS 组装等纯函数(behavior-styled AAA,不为每断言写 Gherkin)llm presets eval backend db aml agent apps/web apps/publish 下的 *.test.tspnpm test + CI
组件单测内环implementervitest · jsdom + React(@testing-library)design-system 组件渲染 / 交互design-system/**(自带 design-system/vitest.config.js)pnpm test + CI
BDD 行为契约横切真相源spec-architect 写 / 两环对着它Gherkin .feature系统该做什么(business-readable,唯一真相源)它所描述的包根 features/(如 apps/web/features/apps/website/features/)(契约本身;被外环测试 realize)
integration 集成外环(BDD 验收)outer-testervitest · jsdom + React + @amiceli/vitest-cucumber组件 / 跨模块协作,realize features/ 场景相关 DOM 包 tests/integration/*(范式:apps/website/tests/integration/)pnpm test + CI
e2e外环(最高最真)outer-tester(当前 —— 未引入 Playwright/Cypress)用户真实走一遍

编排机制(头号坑): 一把 vitest run 默认会把 design-system 的 jsdom 测试也扫进 Node 环境而炸。所以根 vitest.config.tstest.projects:① 一个内联 node project 圈定纯逻辑包;② 把 design-systemapps/website 各自的 config 文件作为独立 project 引入(它们各带 jsdom + react)。新增一个需要 DOM 的包 → 给它写自己的 vitest.config.js 并在根 projects 里引一行;新增一个纯逻辑包 → 把它的 glob 加进根 node project 的 include 漏了这步,它的测试根本不会被跑(静默漏测)。


框架选型(为什么这么选)

  • 单测 / 集成 → vitest 4:与 Vite 同源、ESM/TS 原生、projects 能在一次进程里编排多环境(Node + 多个 jsdom),正好贴合本仓「纯逻辑包 + React 包」混合的形态。turbo 负责 build/typecheck 的跨包编排,测试则统一交给根 vitest 一次跑完。
  • 组件 / 官网 → jsdom + @testing-library/react:测「用户看到/能做什么」而非实现细节;DOM 在 jsdom 里够用、比真浏览器快得多。
  • BDD 契约 → Gherkin features/*.feature:business-readable、行为可执行,作为「系统该做什么」的契约真相源,由 spec-architect 写、内外环都对着它。放在它所描述的那个包根的 features/(apps/website/features/switch-locale.feature 是已 realize 的活例;apps/web/features/ 已种入 build-app / market-fork,待 outer-tester realize)。
  • e2e:暂未引入(没有 Playwright/Cypress)。等出现「跨页面真实链路」必须验时再加一层,别提前上重器。

护栏(质量门)

阶段拦什么
写时plan + 先写失败测试方向 / 实现错
提交 / 推送(当前未配 git hooks)—— 暂无本地预提交闸,质量全压在 CI
PR / push main.github/workflows/ci.yml:pnpm typecheckpnpm testpnpm build(Node 24 + pnpm 11.7,--frozen-lockfile)类型错 / 测试红 / 构建坏
合并后deploy.yml(agentaily)+ deploy-website.yml(官网)CD——

没有 lefthook/husky:push 前自己本地把下面那条 done 命令跑绿,别依赖 hook 兜底。CI 三步任一红都会拦住 PR / 阻断部署。


本地一条命令验完(done 的定义)

bash
pnpm typecheck && pnpm test && pnpm build

pnpm build = turbo run build(各包各自构建;app 前端是零构建 VFS,沙箱直跑,无 studio 汇入步)—— build 绿即代表各包都编译过、apps/web 制品已产出。


约定 / 坑(this repo)

  • 测试文件命名 *.test.ts(x):纯逻辑包用 *.test.ts(被根 node project 的 glob 捞);DOM 包按各自 config 的 include(如 apps/websitetests/**/*.{test,spec}.*)。
  • 新包接测试 = 改两处之一(见上「编排机制」坑):纯逻辑 → 根 node.include 加 glob;带 DOM → 写包内 vitest.config.js + 根 projects 引一行。
  • apps/web(主 SPA)的纯逻辑已纳入编排(apps/web/**/*.test.ts 在根 node project,如 VFS 内联预览组装器);但它还没有 DOM / 集成测试 —— core/*(apiClient / auth / marketStore / conversationStore)与 /build、市场 UI 的用户可见行为是已知缺口。补 DOM / 集成测时给 apps/webvitest.config.js(jsdom + react)并入根 projects,再用 @amiceli/vitest-cucumber realize apps/web/features/*.feature(本仓已种入 build-app / market-fork 两条行为契约,待 outer-tester realize)。
  • 推进模型:改 vitest.config.ts / pnpm-lock.yaml 等共享文件走 worktree + PR —— 在自己的 worktree 里改、窄暂存(别 git add -A)、开 PR 合并,见 CLAUDE.md 的「🌳 推进模型」。