关于 ts-testing
ts-testing 是指导 TypeScript 开发者编写可维护测试的技能,侧重行为覆盖、沿用项目现有工具,并提供快速且确定的反馈。
主要功能
- 01遵循仓库现有测试技术栈
- 02按项目类型选择测试方案
- 03优先验证行为而非实现细节
- 04保持测试快速且确定
- 05为已报告缺陷添加回归测试
适用场景
- 01添加单元、集成或端到端测试
- 02为缺陷编写回归测试
- 03在重构期间检查行为
- 04改进现有 TypeScript 测试套件
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ johnlindquist/ claude --skill ts-testing安装后在 Claude Code 中输入/ts-testing确认已加载。
详细介绍
本技能指导你为 TypeScript 代码构建务实、可维护的测试套件。重点关注行为覆盖、快速反馈,以及与项目现有工具链保持一致。
用户是专注于 TypeScript 的开发者。他们很可能关心正确性、重构安全性,以及不陷入脆弱或不稳定的测试之中。
何时使用本技能
在以下情况下使用本技能:
- 用户正在添加或更新单元、集成或端到端测试
- 用户报告了 bug,并希望添加回归测试
- 用户正在重构,并希望确信没有破坏行为
- 仓库已配置测试工具链(或明显需要配置),并且你被要求“添加测试”或“改进测试”
如果仓库已经有测试栈,不要凭空发明一套新的。先检测并遵循现有设置。
库偏好
始终优先与仓库保持一致(检查 package.json、devDependencies、配置文件):
- 如果仓库已经使用某个框架(Jest、Vitest、Playwright、Cypress 等),坚持使用它。
- 只有在目前还没有明确测试栈时,才建议新的库。
当你必须选择时,优先使用:
- 单元 / 集成测试
- Node / 后端 / 共享库:
- 优先使用 Vitest(
vitest)或 Jest(jest) - 如果存在
vitest,就使用它。否则如果存在jest,就使用它。
- 优先使用 Vitest(
- Node / 后端 / 共享库:
- React / UI 组件测试
- 将 Testing Library 与现有测试运行器一起使用:
@testing-library/react配合 Vitest 或 Jest
- 将 Testing Library 与现有测试运行器一起使用:
- 端到端浏览器测试
- 如果已安装 Playwright,或从零开始时,优先使用 Playwright
- 如果仓库已经使用 Cypress,或用户明确要求,则使用它
如果仓库使用较少见的测试栈(Mocha、Ava、Node 内置测试运行器),请尊重该选择并适配。
核心测试理念
遵循这些原则:
- 测试行为,而不是实现细节
- 对于 React/UI:测试用户看到和做的事情(DOM、事件、ARIA),而不是内部状态或私有方法
- 对于服务:测试公共 API,而不是私有辅助函数
- 保持测试快速且聚焦
- 优先使用运行迅速的小型、确定性测试
- 除非你明确在编写集成测试,否则避免不必要的网络、文件系统或数据库调用
- 让失败显而易见
- 使用清晰的命名和断言来说明为什么测试失败
- 在有帮助时,使用描述性的测试名称并遵循 “given/when/then” 风格
- 尽量减少 mock,但在合理之处使用它
- mock 外部服务、网络调用和缓慢依赖
- 避免 mock 你自己的业务逻辑,除非有充分理由
标准工作流
当被要求添加或改进测试时,请遵循以下工作流:
-
检测现有技术栈
- 检查
package.json中的jest、vitest、@playwright/test、cypress、@testing-library/* - 查找配置文件:
jest.config.*、vitest.config.*、playwright.config.*、cypress.config.* - 检查
package.json中的test、unit或e2e脚本
- 检查
-
找到测试的正确位置
- 沿用现有模式:
- 如果测试位于
__tests__目录中,请遵循该方式 - 如果它们使用
*.test.ts或*.spec.ts,也照此处理
- 如果测试位于
- 对于 UI:如果这是现有惯例,请将测试放在组件附近(例如
Component.test.tsx)
- 沿用现有模式:
-
以对 TS 友好的方式编写测试
- 按照仓库惯例使用
.test.ts/.test.tsx(或.spec) - 在测试中尽可能避免使用
any;使用真实类型或最小接口以保持测试稳健 - 对于异步代码:在异步测试函数中使用
await,避免悬空 Promise
- 按照仓库惯例使用
-
遵循特定库的最佳实践
Vitest / Jest
- 使用
describe/it或test,并使用清晰的名称 - 对于 spy 和 mock,优先使用
vi.fn()/jest.fn() - 对于模块:使用
vi.mock()/jest.mock(),并将 mock 放在文件顶部 - 对于定时器:仅在必要时使用 fake timers(
vi.useFakeTimers()/jest.useFakeTimers())
React Testing Library
- 使用
render、screen以及用户交互(userEvent) - 像用户那样按 role、label、text 进行查询(优先使用
getByRole、getByLabelText) - 避免按 test ID 查询,除非没有更好的语义化替代方案
Playwright / Cypress
- 使用现有的 fixture 和 helper(例如已认证会话、base URL),而不是重新发明它们
- 保持测试相互独立;不要依赖执行顺序
- 一致地使用
data-testid或语义化定位器
- 使用
-
为已报告的 bug 添加回归测试
- 先在一个失败的测试中复现该 bug
- 然后再更改实现以使测试通过
- 为回归测试清晰命名(例如
it("does not crash when X is null (regression #123)"))
-
运行测试
- 使用现有脚本,例如
npm test、pnpm test、npx vitest、npx jest、npx playwright test - 如果添加新的测试命令,请按照现有风格将其接入
package.jsonscripts
- 使用现有脚本,例如
优先采用的模式
- 每个测试只验证一种行为:除非它们属于同一场景,否则不要将多个不相关的断言塞进单个测试中。
- 辅助工厂函数:使用小型工厂函数构建测试数据(
makeUser、makeOrder),而不是重复设置。 - 显式处理异步:始终
awaitPromise;避免将异步回调传给不期望异步回调的 API。
应避免的反模式
- 对复杂对象或 DOM 过度使用 snapshot —— 改用有针对性的断言
- 直接测试私有方法
- 过度 mock,使测试只是镜像实现接线
- 依赖真实时间、网络或不受控全局状态的脆弱测试
TypeScript 专项指导
- 尽可能为测试使用项目的
tsconfig(如果存在tsconfig.test.json则使用它) - 不要只是为了“让测试能编译”而压制类型错误
- 在 stub 数据时,创建最小化的类型化 helper,而不是使用
as any
如果用户要求你生成测试,优先选择更少但高价值、贴近真实使用方式的测试,而不是庞大、机械的测试套件。
评论
支持 Markdown