writing-tests
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWriting Tests
编写测试
Use this skill when the user asks to add tests to existing code, improve test coverage, or write tests for a specific file or module.
当用户要求为现有代码添加测试、提升测试覆盖率或为特定文件/模块编写测试时,使用此技能。
Steps
步骤
-
Detect the test setup — check what's already configured:bash
# Check package.json for test runner cat package.json | grep -E "jest|vitest|mocha|playwright|cypress"Look for config files:,vitest.config.ts,jest.config.ts,playwright.config.ts. Check for existing test files to understand the project's test patterns and conventions..mocharc.* -
If no test runner exists — set one up:bash
npm install -D vitest @testing-library/react @testing-library/jest-domAdd ascript totest:package.jsonjson{ "test": "vitest run", "test:watch": "vitest" } -
Analyze the target code — read the file(s) to test and identify:
- Public API: exported functions, classes, components, hooks
- Code paths: conditionals, error handling, edge cases
- Dependencies: external services, databases, APIs that need mocking
- Side effects: file I/O, network calls, DOM mutations
-
Create the test file — place it next to the source file or in adirectory, matching the project's convention:
__tests__/- →
src/utils/format.tssrc/utils/format.test.ts - →
src/components/Button.tsxsrc/components/Button.test.tsx
-
Write tests following this structure:ts
import { describe, it, expect, vi } from "vitest"; describe("functionName", () => { // Happy path it("returns formatted output for valid input", () => { ... }); // Edge cases it("handles empty string", () => { ... }); it("handles null/undefined input", () => { ... }); // Error cases it("throws on invalid argument", () => { ... }); // Boundary conditions it("handles maximum length input", () => { ... }); }); -
Mock external dependencies — don't make real API calls or database queries in unit tests:ts
vi.mock("@/lib/db", () => ({ query: vi.fn().mockResolvedValue([{ id: 1, name: "test" }]), }));For React components, mock hooks that fetch data:tsvi.mock("@/hooks/useUser", () => ({ useUser: () => ({ user: { name: "Test" }, isLoading: false }), })); -
Test React components with Testing Library:tsx
import { render, screen, fireEvent } from "@testing-library/react"; it("renders the button and handles click", () => { const onClick = vi.fn(); render(<Button onClick={onClick}>Click me</Button>); fireEvent.click(screen.getByRole("button", { name: "Click me" })); expect(onClick).toHaveBeenCalledOnce(); }); -
Run the tests and verify they pass:bash
npm testIf any fail, fix the test or the code (depending on whether the test expectation or the implementation is wrong).
-
检测测试配置 — 检查已有的配置:bash
# Check package.json for test runner cat package.json | grep -E "jest|vitest|mocha|playwright|cypress"查找配置文件:、vitest.config.ts、jest.config.ts、playwright.config.ts。查看现有测试文件以了解项目的测试模式和约定。.mocharc.* -
如果没有测试运行器 — 配置一个:bash
npm install -D vitest @testing-library/react @testing-library/jest-dom在中添加package.json脚本:testjson{ "test": "vitest run", "test:watch": "vitest" } -
分析目标代码 — 读取要测试的文件并识别:
- 公共API:导出的函数、类、组件、hooks
- 代码路径:条件分支、错误处理、边界情况
- 依赖项:需要模拟的外部服务、数据库、API
- 副作用:文件I/O、网络请求、DOM变更
-
创建测试文件 — 遵循项目约定,将其放在源文件旁边或目录中:
__tests__/- →
src/utils/format.tssrc/utils/format.test.ts - →
src/components/Button.tsxsrc/components/Button.test.tsx
-
按照以下结构编写测试:ts
import { describe, it, expect, vi } from "vitest"; describe("functionName", () => { // Happy path it("returns formatted output for valid input", () => { ... }); // Edge cases it("handles empty string", () => { ... }); it("handles null/undefined input", () => { ... }); // Error cases it("throws on invalid argument", () => { ... }); // Boundary conditions it("handles maximum length input", () => { ... }); }); -
模拟外部依赖项 — 单元测试中不要发起真实的API请求或数据库查询:ts
vi.mock("@/lib/db", () => ({ query: vi.fn().mockResolvedValue([{ id: 1, name: "test" }]), }));对于React组件,模拟获取数据的hooks:tsvi.mock("@/hooks/useUser", () => ({ useUser: () => ({ user: { name: "Test" }, isLoading: false }), })); -
使用Testing Library测试React组件:tsx
import { render, screen, fireEvent } from "@testing-library/react"; it("renders the button and handles click", () => { const onClick = vi.fn(); render(<Button onClick={onClick}>Click me</Button>); fireEvent.click(screen.getByRole("button", { name: "Click me" })); expect(onClick).toHaveBeenCalledOnce(); }); -
运行测试并验证是否通过:bash
npm test如果有测试失败,修复测试或代码(取决于测试预期还是实现存在问题)。
What to Test
测试内容
- Always test: public API, error handling, edge cases (empty, null, zero, negative), state transitions, async behavior
- Skip testing: private implementation details, third-party library internals, simple getters/setters, type-only code
- 必须测试:公共API、错误处理、边界情况(空值、null、零、负数)、状态转换、异步行为
- 无需测试:私有实现细节、第三方库内部逻辑、简单的getter/setter、仅类型代码
Notes
注意事项
- Match the project's existing test style — if they use instead of
test(), follow that.it() - Don't test implementation details — test behavior and outputs, not internal method calls.
- Use descriptive test names that explain the scenario: "returns 0 when cart is empty" not "test1".
- One assertion concept per test — multiple calls are fine if they verify the same behavior.
expect - For async code, always the result or use
await/resolvesmatchers.rejects
- 匹配项目现有的测试风格 — 如果项目使用而非
test(),遵循该风格。it() - 不要测试实现细节 — 测试行为和输出,而非内部方法调用。
- 使用描述性的测试名称来解释场景:比如“购物车为空时返回0”而非“test1”。
- 每个测试对应一个断言概念 — 如果是验证同一行为,多个调用是可行的。
expect - 对于异步代码,务必结果或使用
await/resolves匹配器。rejects