mcpField
T
testing-unit

testing-unit

github.com/yonatangross测试与质量299109 次安装今天更新
代码仓库

关于 testing-unit

testing-unit 提供编写隔离且快速的单元测试指南,面向使用 TypeScript 或 Python 的开发者,涵盖测试结构、HTTP 拦截、夹具和测试数据生成。

主要功能

  1. 01Arrange-Act-Assert 测试结构
  2. 02参数化测试以避免重复
  3. 03夹具作用域与隔离指南
  4. 04网络层 HTTP 拦截
  5. 05工厂与夹具数据管理
  6. 06测试脚手架脚本

适用场景

  1. 01组织隔离的单元测试
  2. 02不访问真实 API 测试 HTTP 相关代码
  3. 03创建可复用测试数据与夹具
  4. 04生成测试文件和 MSW 处理器

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatangross/orchestkit --skill testing-unit

安装后在 Claude Code 中输入/testing-unit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

test-cases.json
checklists/
msw-setup-checklist.md
test-data-checklist.md
vcr-checklist.md
examples/
handler-patterns.md
references/
aaa-pattern.md
factory-patterns.md
msw-2x-api.md
stateful-testing.md
rules/
_sections.md
data-factories.md
data-fixtures.md
data-seeding-cleanup.md
mocking-msw.md
mocking-vcr.md
unit-aaa-pattern.md
unit-fixture-scoping.md
unit-parametrized.md
scripts/
create-msw-handler.md
create-test-case.md
create-test-fixture.md

详细介绍

单元测试模式

专注于编写隔离、高速且易于维护的单元测试模式。涵盖测试结构(AAA)、参数化、fixture 管理、HTTP 模拟(MSW/VCR)以及使用工厂生成测试数据。

每个类别都有独立的规则文件,按需从 rules/ 加载;此外还提供参考资料、检查清单和脚手架脚本。

核心原则(始终遵循)

  1. AAA 结构:每个测试都必须遵循 Arrange-Act-Assert。使用 // Arrange、// Act、// Assert 注释,提高清晰度。
  2. 使用参数化,不要重复编写:测试多个输入时,使用 test.each(TypeScript)或 @pytest.mark.parametrize(Python)。切勿复制粘贴测试主体,只更改不同的值。
  3. Fixture 作用域很重要:对于可变数据,使用 scope="function"(默认值)。只有对于开销较大的只读资源(DB 引擎、ML 模型),才使用 scope="module" 或 scope="session"。共享作用域中的可变数据会导致测试不稳定。
  4. 速度目标:每个单元测试都应在 100ms 内运行完毕。如果更慢,你很可能触发了 I/O 操作——请模拟它。
  5. 在网络层模拟:使用 MSW(TypeScript)或 VCR.py(Python)在网络层拦截 HTTP。切勿直接模拟 fetch/axios/requests。

快速参考

类别规则影响适用场景
单元测试结构3严重编写任何单元测试时
HTTP 模拟2高在前端/后端测试中模拟 API 调用时
测试数据管理3中设置测试数据、工厂和 fixture 时

总计:3 个类别中的 8 条规则、4 份参考资料、3 份检查清单、1 组示例、3 个脚本

单元测试结构

用于构建隔离单元测试的核心模式,包含清晰的阶段并可高效执行。

规则文件关键模式
AAA 模式rules/unit-aaa-pattern.md通过隔离实现 Arrange-Act-Assert
Fixture 作用域rules/unit-fixture-scoping.md选择 function/module/session 作用域
参数化测试rules/unit-parametrized.mdtest.each / @pytest.mark.parametrize

参考资料: references/aaa-pattern.md — 详细介绍 AAA 实现并附带检查清单

HTTP 模拟

在网络层拦截请求,以运行确定性测试,而无需访问真实 API。

规则文件关键模式
MSW 2.xrules/mocking-msw.md面向前端的网络层模拟(TypeScript)
VCR.pyrules/mocking-vcr.md录制/回放 HTTP 磁带(Python)

参考资料:

  • references/msw-2x-api.md — 完整的 MSW 2.x API(处理器、GraphQL、WebSocket、直通)
  • references/stateful-testing.md — 用于有状态测试的 Hypothesis RuleBasedStateMachine

检查清单:

  • checklists/msw-setup-checklist.md — MSW 安装、处理器设置、测试编写
  • checklists/vcr-checklist.md — VCR 配置、敏感数据过滤、CI 设置

示例: examples/handler-patterns.md — CRUD、错误模拟、身份验证流程、文件上传处理器

测试数据管理

用于生成隔离且真实的测试数据的工厂、fixture 和数据填充模式。

规则文件关键模式
数据工厂rules/data-factories.mdFactoryBoy / @faker-js 构造器
数据 Fixturerules/data-fixtures.md通过组合使用 JSON fixture
数据填充与清理rules/data-seeding-cleanup.md自动化数据库数据填充和拆除

参考资料: references/factory-patterns.md — 高级工厂模式(Sequence、SubFactory、Traits)

检查清单: checklists/test-data-checklist.md — 数据生成、清理、隔离验证

快速开始

TypeScript(Vitest + MSW)
import { describe, test, expect, beforeAll, afterEach, afterAll } from 'vitest';
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
import { calculateDiscount } from './pricing';

// 1. Pure unit test with AAA pattern
describe('calculateDiscount', () => {
  test.each([
    [100, 0],
    [150, 15],
    [200, 20],
  ])('for order $%i returns $%i discount', (total, expected) => {
    // Arrange
    const order = { total };

    // Act
    const discount = calculateDiscount(order);

    // Assert
    expect(discount).toBe(expected);
  });
});

// 2. MSW mocked API test
const server = setupServer(
  http.get('/api/users/:id', ({ params }) => {
    return HttpResponse.json({ id: params.id, name: 'Test User' });
  })
);

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

test('fetches user from API', async () => {
  // Arrange — MSW handler set up above

  // Act
  const response = await fetch('/api/users/123');
  const data = await response.json();

  // Assert
  expect(data.name).toBe('Test User');
});
Python(pytest + FactoryBoy)
import pytest
from factory import Factory, Faker, SubFactory

class UserFactory(Factory):
    class Meta:
        model = dict
    email = Faker('email')
    name = Faker('name')

class TestUserService:
    @pytest.mark.parametrize("role,can_edit", [
        ("admin", True),
        ("viewer", False),
    ])
    def test_edit_permission(self, role, can_edit):
        # Arrange
        user = UserFactory(role=role)

        # Act
        result = user_can_edit(user)

        # Assert
        assert result == can_edit

Vitest 4.1 特性

aroundEach / aroundAll(推荐用于数据库事务)

通过设置/拆卸包装每个测试——用于事务时,比单独使用 beforeEach/afterEach 更简洁:

test.aroundEach(async (runTest, { db }) => {
  await db.transaction(runTest)  // auto-rollback on test end
})

test('insert user', async ({ db }) => {
  await db.insert({ name: 'Alice' })
  // transaction auto-rolls back — no cleanup needed
})

aroundAll 以相同方式包装整个测试套件。

mockThrow / mockThrowOnce

替代冗长的 mockImplementation(() => { throw err }) 模式:

const fn = vi.fn()
fn.mockThrow(new Error('connection lost'))  // always throws
fn.mockThrowOnce(new Error('timeout'))      // throws once, then normal
vi.defineHelper(简洁的堆栈跟踪)

自定义断言辅助函数,可将错误指向调用位置,而不是辅助函数内部:

const assertPair = vi.defineHelper((a, b) => {
  expect(a).toEqual(b)  // error points to where assertPair() was CALLED
})
测试标签

在命令行中按标签筛选测试——适用于 CI 快速路径:

// vitest.config.ts
test: {
  tags: {
    unit: { timeout: 5000 },
    flaky: { retry: 3 },
  }
}
vitest --tags-filter="unit and !flaky"
vitest --tags-filter="(unit or integration) and !slow"
Agent 报告器

最简输出(仅显示失败项)——适用于 AI Agent / CI 场景:

AI_AGENT=copilot vitest    # auto-detect agent mode

关键决策

决策建议
测试框架(TS)Vitest 4.1+(现代、快速,支持 aroundEach、测试标签)或 Jest(生态成熟)
测试框架(Python)搭配插件使用 pytest(parametrize、asyncio、cov)
HTTP 模拟(TS)在网络层使用 MSW 2.x,切勿直接模拟 fetch/axios
HTTP 模拟(Python)使用 VCR.py 和录制文件,并过滤敏感数据
测试数据优先使用工厂(FactoryBoy/faker-js),而非硬编码的测试固件
测试固件作用域可变测试固件使用 scope="function"(默认值)。仅对开销大的不可变资源使用 module/session
执行时间每个单元测试不超过 100ms——如果更慢,请模拟外部调用
覆盖率目标业务逻辑达到 90%+,关键路径达到 100%

常见错误

  1. 测试实现细节而非公开行为(测试脆弱)
  2. 直接模拟 fetch/axios,而不是在网络层使用 MSW(覆盖不完整)
  3. 通过模块级测试固件在测试之间共享可变状态(测试不稳定)
  4. 使用包含重复 ID 的硬编码测试数据(并行运行时发生测试冲突)
  5. 数据库填充后未清理(测试之间状态泄漏)
  6. 过度模拟——测试模拟对象而不是代码(产生虚假的信心)
  7. 冗长的抛错模拟——使用 mockImplementation(() => { throw err }) 而非 mockThrow(err)(Vitest 4.1+)

脚本

脚本文件用途
创建测试用例scripts/create-test-case.md根据自动检测到的框架搭建测试文件
创建测试固件scripts/create-test-fixture.md根据上下文检测搭建 pytest 测试固件
创建 MSW 处理器scripts/create-msw-handler.md为 API 端点搭建 MSW 处理器

评论

支持 Markdown