测试与可观测:Vitest / RTL / Playwright / MSW / Sentry / Web Vitals / a11y
0. 元信息
- 主题路径:
docs/topics/react-app/subtopics/testing-and-observability/README.md - 父主题:
react-app - 主分类:前端与客户端
- 辅助分类:安全与可靠性
- 适合对象:想把应用送上生产、需要监控与质量保障的开发者
- 建议周期:1.5~2 周
- 前置知识:
components-and-jsx、hooks-and-state-management、routing-and-data-fetching - 最终目标:能搭出端到端测试金字塔 + 监控 + a11y 报告,把应用送到生产
1. 学习路线
单元 / 组件测试(Vitest + RTL)→ API mock(MSW)→ 端到端(Playwright)
→ 性能(Web Vitals + Profiler)→ 错误与链路(Sentry / OpenTelemetry)
→ 可访问性(axe / 键盘 / 焦点)→ CI / CD 集成
2. 阶段周数分配
精简子主题不固定周数。按 §3 顺序完成,每段都有可量化交付。
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 学会标准 |
|---|---|---|---|
| 1 | Vitest 配置、jsdom、happy-dom、ESM | 单元测试起步 | vitest run 跑通 |
| 2 | RTL:render / screen / fireEvent / userEvent | 组件测试套件 | 不查 state,只查可见行为 |
| 3 | MSW:request handlers、reset、Node + browser | API mock | 测试不依赖真后端 |
| 4 | Playwright:fixtures、trace viewer、sharding | e2e 套件 | 跨浏览器跑通 |
| 5 | Web Vitals:LCP / INP / CLS / TTFB / FCP | 真实用户指标上报 | 能在 dashboard 看到 P75 |
| 6 | Sentry:source map、release、Replay、Performance | 错误监控 | 能定位到 commit |
| 7 | OpenTelemetry JS:trace / span / exporter | 链路追踪 | trace 串联前后端 |
| 8 | a11y:ARIA、键盘、焦点、axe-core、eslint-plugin-jsx-a11y | a11y 报告 | WCAG 2.2 AA 通过 |
| 9 | CI:GitHub Actions / GitLab CI 跑 lint / typecheck / test / build / e2e | 完整流水线 | PR 状态全绿 |
4. 第一周任务
精简版省略固定日程。优先完成“Vitest + RTL 起步 + MSW mock 一个 endpoint + Playwright 跑一个 happy path”。
5. 阶段通用验收
精简版省略;要求测试金字塔三层都跑通且 CI 全绿。
6. 最终验收
精简版省略;以 §3 第 9 阶段和 §9.4 案例口述检查为准。
7. 综合项目
精简版省略;成果并入父主题电商 SPA 的“测试金字塔 + 监控 + a11y 报告 + CI”。
本主题贡献
- 职责 1(测试金字塔三层 + RTL 行为断言):父主题“商品列表 + 详情 + 购物车 + 结账”建立单元 / 组件 / e2e 三层套件——Vitest 跑纯函数与 hook,React Testing Library +
userEvent跑组件(只查文本 / role / aria-label,不查 state / className,呼应 §9.4 #2),Playwright 跑 1~3 个 happy path e2e;MSW handler 在 dev / unit / e2e 三处共用一份(§3 阶段 3、§9.4 #3)。 - 职责 2(可观测三件套:Sentry + Web Vitals + OTel trace):Sentry 在 CI 上传 source map(
SENTRY_AUTH_TOKEN+sentry-cli releases new)让堆栈定位到 commit;onLCP/onINP/onCLS/onTTFB/onFCP全量上报到 RUM 仪表盘,按 P75 报警;SSR 入口注入 W3Ctraceparent,RQ 把traceparent加到 fetch header,前后端 trace 串联(§3 阶段 5~7、§9.4 #4 / #10)。 - 职责 3(a11y + CI 全绿):组件库默认键盘可达,Modal 关闭焦点归还触发元素(§9.4 #9);CI 跑
eslint-plugin-jsx-a11y+jest-axe+ Playwright@axe-core/playwright,目标 WCAG 2.2 AA 零违规。 - 交付物 1:
tests/unit/≥40 个用例覆盖 utils + hooks;tests/component/≥30 个组件用例使用 RTL;tests/e2e/Playwright 跑“浏览 → 加入购物车 → 结账”一条 happy path;coverage 报告在 Vitest 内置v8上产出。 - 交付物 2:
mocks/handlers.ts单一来源——同一份 MSW handler 同时被 Vitest(setupServer)、Playwright(setupWorker)、pnpm dev(浏览器 SW)消费;改一处三处生效,杜绝 §9.4 #3 “测试过、生产坏”。 - 交付物 3:
.github/workflows/ci.yml跑 lint / typecheck / unit / e2e / build / a11y / lighthouse-ci 七步;Sentry release 与 GitHub release 绑定。 - 交付物 4:Playwright trace viewer 在 CI 失败时自动上传工件;Sentry 在 PR 上挂“预览环境”问题流,方便 reviewer 看复现。
- 指标 1:单元 + 组件测试覆盖率 ≥80%(line + branch),CI 跌破阈值则构建失败。
- 指标 2:线上 P75 LCP ≤2.5s、INP ≤200ms、CLS ≤0.1(Web Vitals “Good” 阈值,§9.6.1 / §3 阶段 5);任一指标连续 3 天越线自动开 Issue。
- 指标 3:Playwright e2e 整套 ≤60s(用 sharding + 浏览器缓存);axe-core 在
pnpm test:a11y中违规数 0;e2e 失败后 trace viewer 工件可在 GitHub PR 评论直接下载。
8. 推荐资料
精简版省略;使用 §9.3 和 §9.6 Source。
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
应用上线后最大的问题不是“功能对不对”,而是“线上到底发生了什么”。测试金字塔保证“已知问题不回归”;监控把“未知问题”变成可定位的事件;可访问性保证“最弱用户也能用”。三者缺一不可:只测不监 → 线上盲飞;只监不测 → 监控告警多到没人看;只测不 a11y → 触达用户少。
9.2 概念地图
flowchart LR
Test[测试] --> Unit[Vitest 单元]
Test --> Comp[RTL 组件]
Test --> API[MSW API mock]
Test --> E2E[Playwright e2e]
Test --> Visual[Visual regression: Chromatic / Percy]
Observe[可观测] --> Sentry[错误 / Replay / Performance]
Observe --> Vitals[Web Vitals]
Observe --> OTel[OpenTelemetry trace]
Observe --> Logs[结构化日志]
A11y[可访问性] --> ARIA
A11y --> Keyboard[键盘 / 焦点]
A11y --> Axe[axe-core / Pa11y]
A11y --> ESLint[eslint-plugin-jsx-a11y]
CI[CI / CD] --> Lint
CI --> Typecheck
CI --> Unit
CI --> E2E
CI --> Build
CI --> Deploy
9.3 基础知识讲解
9.3.1 论文 / 规范
- W3C ARIA Authoring Practices Guide (APG)。
- WAI-ARIA 1.2 / 2.0。
- WCAG 2.2。
- Google Web Vitals 文档(LCP / INP / CLS 阈值)。
- W3C Trace Context(OpenTelemetry 兼容)。
- testing-library guiding principles:测试可见行为,不查实现。
9.3.2 书
- Testing JavaScript(Kent C. Dodds)。
- Effective Software Testing(Mauricio Aniche)。
- Web Accessibility: Web Standards and Regulatory Compliance。
- Observability Engineering(Majors / Fong-Jones / Miranda)。
9.3.3 博客 / 文档
- testing-library.com。
- Playwright 文档。
- MSW 文档。
- Sentry React 文档。
- Web Vitals 文档。
- OpenTelemetry JS。
- axe-core 文档。
- Kent C. Dodds:testing implementation details。
- TkDodo:测试与 RQ。
9.3.4 人物
- Kent C. Dodds:Testing Library 作者。
- Andrey Okonetchnikov:Vitest 维护者之一。
- Tim Dohman:Playwright 团队。
- OpenTelemetry SIG:跨语言追踪规范。
- Sentry team:前端监控文档。
- Web Vitals 团队:Google Chrome。
9.3.5 方法
- Test the contract, not the implementation:RTL 查文本 / role,不查 state。
- MSW once, run anywhere:同一份 handler 在单元 / e2e / dev 都用。
- E2E happy paths only:1~3 个核心流,其余放单元。
- Real user monitoring(RUM):Web Vitals 上报真实用户。
- Source maps for prod:Sentry 上传 source map,按 release / commit 定位。
- Trace context:服务端用 W3C traceparent 贯穿 SSR + RSC + RQ。
- a11y as requirement:组件库默认键盘可达;CI 跑 axe。
9.4 经典问题与经典案例
| # | 问题 | 为什么重要 | 最简答案或证据 |
|---|---|---|---|
| 1 | e2e 跑得太慢 | 跑全套冒烟 | 拆分 smoke / regression;用 Playwright sharding |
| 2 | 单元测试查 state | 一改实现全坏 | 改查文本 / role / aria-label |
| 3 | MSW handler 与 dev 不同步 | 测试过、生产坏 | 复用同一份 handler |
| 4 | Sentry 堆栈是压缩代码 | 看不懂 | 上传 source map;CI 设 SENTRY_AUTH_TOKEN |
| 5 | LCP 一直高 | 首屏 SSR 慢 / 大图 | <Image priority> / preload / 减小 JS |
| 6 | INP 差 | 长任务 | 拆 effect;用 useTransition;web worker |
| 7 | CLS 差 | 图片 / 字体 / 动态插入 | 设宽高;font-display: swap + size-adjust |
| 8 | a11y 报“button missing label” | <button> 没文字 | 加 aria-label;或塞 <span> |
| 9 | 焦点在 Modal 关闭后跑走 | a11y 灾难 | 关闭时把焦点归还触发元素 |
| 10 | trace 串不起前后端 | 没传 trace context | SSR 用 OpenTelemetry.propagation.inject;RQ 把 traceparent 加 header |
9.5 学习难点
- 概念难点:测试金字塔层之间的边界。e2e 慢且脆,单元测不到交互集成。
- 思维难点:把“监控告警”当产品需求设计——SLO、SLA、错误预算。
- 工程难点:e2e 稳定性、source map 管线、a11y 在 CI 跑通不假阳性。
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 版本 | 组织 | 状态 |
|---|---|---|---|
| Vitest | 1+ | Vitest team | 活跃 |
| React Testing Library | 16+ | Testing Library | 活跃 |
| Playwright | 1.4+ | Microsoft | 活跃 |
| MSW | 2+ | MSW team | 活跃 |
| Sentry | 24+ | Functional Software | 活跃 |
| Web Vitals | 4+ | Google Chrome | 活跃 |
| OpenTelemetry JS | 1+ | CNCF | 活跃 |
| axe-core | 4+ | Deque | 活跃 |
| jest-axe | 9+ | 社区 | 活跃 |
| Pa11y | 6+ | 社区 | 维护 |
| eslint-plugin-jsx-a11y | 6+ | jsx-eslint | 活跃 |
9.6.2 Scope
- RTL 不替代单元测试库(Vitest 负责运行);RTL 提供 DOM 查询语义。
- Playwright 不替代 Vitest;它管 e2e 与浏览器自动化。
- Sentry / OTel 不替代日志;日志是 trace 的旁路。
- a11y 工具不替代人工测试;视觉障碍用户的真实体验仍需评估。
9.6.3 Structure
- 必会 Vitest:
describe/it/expect/vi.mock/vi.spyOn/beforeEach。 - 必会 RTL:
render/screen/within/userEvent/waitFor。 - 必会 Playwright:
test/expect/page/locator/trace。 - 必会 MSW:
http.get/HttpResponse.json/setupServer/setupWorker。 - 必会 Sentry:
Sentry.init/captureException/withScope/setUser/setTag。 - 必会 Web Vitals:
onLCP/onINP/onCLS/onTTFB/onFCP。 - 必会 OTel:
trace.getTracer/startActiveSpan/propagation.inject。 - 必会 a11y:
axe.run/toHaveNoViolations/aria-*/ role。
9.6.4 Ecosystem
- Visual regression:Chromatic、Percy、Loki。
- 错误监控:Sentry、Bugsnag、Rollbar、Datadog RUM、LogRocket。
- 性能监控:Lighthouse CI、PageSpeed Insights、WebPageTest、SpeedCurve。
- a11y 工具:axe DevTools、ANDI、WAVE、Pa11y CI。
- CI:GitHub Actions、GitLab CI、CircleCI、Buildkite。
9.6.5 Depth Tiers
| 层级 | 可观察能力 |
|---|---|
| L0 | 知道测试 / 监控存在 |
| L1 | 看得懂基本测试与监控 |
| L2 | 能写组件 / API / e2e 测试 |
| L3 | 能搭测试金字塔、接 Sentry、看 Web Vitals 排问题 |
| L4 | 能设计 SLO / 错误预算 / trace 架构 |
本计划目标:L3。
9.6.6 Source
- testing-library.com。
- playwright.dev。
- docs.sentry.io。
- web.dev/vitals。
- opentelemetry.io。
- 引用快照:2026-07-30。
10. 常见误区
- 用 e2e 测一切
- 单元测试查 state
- MSW 在测试与 dev 用不同文件
- Sentry 不上传 source map
- LCP 用合成数据而非 RUM
- a11y 只跑一次就完事
- Modal 关闭不归还焦点
- 没把 trace context 串起来
- CI 跑 e2e 不缓存浏览器
- 错误预算不与团队对齐。
11. 所有知识点分类
- 编程语言 2. 数据结构与算法 3. 计算机基础 4. 工程技术 5. Web 与后端 6. 前端与客户端 7. 数据与人工智能 8. 项目与职业能力 9. 安全与可靠性
本计划归属:前端与客户端 主 + 安全与可靠性 辅。