SuperAPI AI 工具集

frontend-typescript-testing

测试与质量

查看项目

更新于 10-16 05:40

技能介绍

该技能用于在前端 TypeScript 项目中设计测试,基于仓库已经配置好的 React 测试与浏览器工具链来落地,包括 React Testing Library(RTL)、MSW(Mock Service Worker)、Vitest 和 Playwright(当存在时)。

一、前置探测 在选择框架或命令之前,先检查 package.json、锁文件、测试配置和已有测试的导入。只有当依赖或配置确实存在时,才应用 Vitest、React Testing Library、MSW 或 Playwright 的规则。如果仓库使用了不同但等价的配置,就沿用仓库自身的方案。如果找不到可运行的测试环境,应报告已检查的路径以及缺失的框架或命令,而不是自行发明一个。

二、参考文档划分 该文档本身对应单元/集成测试,用于使用 RTL + Vitest + MSW 实现 React 组件测试。E2E 测试则参考 references/e2e.md,用于使用 Playwright 实现浏览器级端到端测试。

三、测试框架与导入 Vitest 在仓库配置或已有测试选择它时使用;React Testing Library 用于组件测试;MSW 用于 API 模拟。基础导入为:import { describe, it, expect, beforeEach, vi } from 'vitest'。组件测试导入为:import { render, screen } from '@testing-library/react'。用户交互为:import userEvent from '@testing-library/user-event'。Mock 创建使用 vi.mock()。

四、基本测试策略与质量要求 回归保护:针对关键路径和高复用组件,断言具名的验收结果、公共分支或失败状态。独立性:每个测试可独立运行,不依赖其他测试。可复现性:控制时间、随机性、环境值、网络响应和浏览器状态,使相同输入产生相同的可观察结果。可读性:每个测试命名一个用户可见行为,分隔准备、动作、断言三个阶段,fixture 只保留该行为用到的值。

测试严谨度应集中在跨功能复用的共享组件、自定义 hooks 和工具函数上,覆盖其公共分支、错误状态和边界契约,因为其回归影响范围更大。当行为依赖多个渲染单元时,通过集成或 E2E 测试验证页面级组合。

五、测试类型与范围 单元测试(RTL):验证单个组件或函数的行为,模拟所有外部依赖,数量最多、粒度最细,聚焦用户可观察行为。集成测试(RTL + MSW):验证多个组件之间的协作,用 MSW 模拟 API,不连接真实数据库(数据库由后端管理),验证实现主要验收标准或协调多个渲染组件的流程。E2E 中的跨功能验证:新增功能时必须验证对既有功能的影响;将每个集成点分级,High 表示失败会破坏主要用户旅程或契约,Medium 表示失败会降低次要可观察行为,需覆盖 High 与 Medium;验证模式为“既有功能操作 -> 启用新功能 -> 验证既有功能连续性”。成功标准是保留源验收标准中具名的展示内容和交互行为;只有在项目配置或需求定义了阈值及其测量方式时,才应用渲染时间阈值。整体设计面向 CI/CD 流水线自动执行。

六、实现约定 目录结构与命名:将组件测试与其组件放在同一目录,使实现与测试同步移动。测试文件命名为 {ComponentName}.test.tsx;集成测试文件命名为 {FeatureName}.integration.test.tsx。测试套件名称描述目标组件或功能;测试用例名称从用户视角描述预期行为。

测试代码质量规则:保持每个已提交的测试处于有效状态。保护当前行为的测试应修复;只有当行为不再被需要且源需求或实现契约确认移除时,才删除该测试。

Mock 类型安全:用 satisfies 将 MSW handler 的响应体约束到它所代表的领域类型,使偏离契约的 fixture 在编译期失败,而不是让测试对一个应用永远不会收到的结构通过。将组件或依赖 mock 类型约束到被测对象实际消费的接口面(如 Pick<Props, 'usedProp'>、Pick<Router, 'push'>),而不是完整接口,并用 satisfies 约束字面量,使多余或拼写错误的成员在编译期失败。

七、测试设计模式 测试用户可见的结果,而不是实现细节。按用户感知的角色和可访问名称查询(getByRole/getByLabelText/getByText),而不是 getByTestId 或 container.querySelector。通过 userEvent 并在每个测试中使用 userEvent.setup() 驱动交互,而不是触发原始事件,以便测试复现浏览器的事件序列。对每个交互和异步断言都使用 await——未 await 的交互会针对更新前的渲染做断言,因此异步 UI 应使用 findBy*。

覆盖空、错误、加载/异步状态,而不只是 happy path。错误状态应通过为单个测试覆盖 MSW handler 来产生,而不是修改共享的 handler 集合。

当所需的 UI 状态、可访问名称或外部契约未知时,停止对该断言的测试设计,并指出所需的 UI Spec、验收标准、实现契约或用户决策。继续执行那些预期行为可被观察的独立断言。