mcpField
B
bun-test

bun-test

github.com/daleseo测试与质量4227 次安装40 周前更新
代码仓库

关于 bun-test

bun-test 是用于配置和使用 Bun 内置测试运行器的技能,面向开发者。内容涵盖测试组织、Jest 迁移、模拟、覆盖率配置和常见测试模式。

主要功能

  1. 01配置 Bun 测试运行器
  2. 02组织单元与集成测试
  3. 03使用兼容 Jest 的测试 API
  4. 04设置模拟函数与间谍
  5. 05配置覆盖率与监视模式

适用场景

  1. 01为 Bun 项目配置测试
  2. 02将测试从 Jest 迁移
  3. 03测试 API、异步代码或数据库交互
  4. 04生成覆盖率报告

安装

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

$npx skills add https://github.com/daleseo/bun-skills --skill bun-test

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

包含的文件

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

references/
examples.md
jest-migration.md
mocking.md

详细介绍

Bun 测试配置

配置 Bun 内置测试运行器,使用兼容 Jest 的 API,并显著提升执行速度(比 Jest 快 3–10 倍)。

快速参考

如需了解详细模式,请参阅:

  • Jest 迁移:jest-migration.md - 完整的 Jest 到 Bun 迁移指南
  • 模拟:mocking.md - 模拟函数、间谍和模块
  • 示例:examples.md - API、数据库和异步代码的测试模式

核心工作流

1. 检查先决条件
# Verify Bun installation
bun --version

# Check if project exists
ls -la package.json
2. 确定测试需求

询问用户需要哪种类型的测试:

  • 单元测试:测试单个函数和模块
  • 集成测试:测试组件交互
  • API 测试:测试 HTTP 端点
  • 快照测试:测试输出一致性
3. 创建测试目录结构
# Create test directories
mkdir -p tests/{unit,integration,fixtures}

推荐结构:

project/
├── src/
│   ├── utils.ts
│   └── components/
├── tests/
│   ├── unit/              # Unit tests
│   ├── integration/       # Integration tests
│   ├── fixtures/          # Test data
│   └── setup.ts          # Global setup
├── package.json
└── bunfig.toml           # Test configuration
4. 配置 Bun 测试

在项目根目录中创建 bunfig.toml:

[test]
# Preload files before running tests
preload = ["./tests/setup.ts"]

# Code coverage
coverage = true
coverageDir = "coverage"
coverageThreshold = 80

# Timeouts (in milliseconds)
timeout = 5000

# Bail after first failure
bail = false
5. 创建测试设置文件

创建 tests/setup.ts:

import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";

// Global test setup
beforeAll(() => {
  console.log("🧪 Starting test suite");
  process.env.NODE_ENV = "test";
});

afterAll(() => {
  console.log("✅ Test suite complete");
});

// Reset mocks before each test
beforeEach(() => {
  // Clear mock state
});

afterEach(() => {
  // Cleanup after each test
});

// Global test utilities
globalThis.testHelpers = {
  wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
};
6. 编写第一个测试

创建 tests/unit/example.test.ts:

import { describe, it, expect, test } from "bun:test";

// Simple test
test("addition works", () => {
  expect(1 + 1).toBe(2);
});

// Describe blocks for organization
describe("Array utilities", () => {
  it("should filter even numbers", () => {
    const numbers = [1, 2, 3, 4, 5, 6];
    const evens = numbers.filter(n => n % 2 === 0);

    expect(evens).toEqual([2, 4, 6]);
    expect(evens).toHaveLength(3);
  });
});

// Async tests
describe("Async operations", () => {
  it("should handle promises", async () => {
    const result = await Promise.resolve(42);
    expect(result).toBe(42);
  });
});

如需查看更多测试示例(API 测试、数据库测试等),请参阅 examples.md。

7. 添加模拟(如有需要)
import { describe, it, expect, mock, spyOn } from "bun:test";

describe("Mock functions", () => {
  it("should create mock functions", () => {
    const mockFn = mock((x: number) => x * 2);

    const result = mockFn(5);

    expect(result).toBe(10);
    expect(mockFn).toHaveBeenCalledTimes(1);
    expect(mockFn).toHaveBeenCalledWith(5);
  });

  it("should spy on methods", () => {
    const obj = {
      method: (x: number) => x * 2,
    };

    const spy = spyOn(obj, "method");

    obj.method(5);

    expect(spy).toHaveBeenCalledWith(5);
    expect(spy).toHaveReturnedWith(10);
  });
});

如需了解高级模拟模式,请参阅 mocking.md。

8. 更新 package.json

添加测试脚本:

{
  "scripts": {
    "test": "bun test",
    "test:watch": "bun test --watch",
    "test:coverage": "bun test --coverage",
    "test:ui": "bun test --coverage --reporter=html"
  }
}
9. 运行测试
# Run all tests
bun test

# Run specific file
bun test tests/unit/utils.test.ts

# Watch mode
bun test --watch

# With coverage
bun test --coverage

# Filter by name
bun test --test-name-pattern="should handle"

Jest 迁移

如果要从 Jest 迁移,请参阅 jest-migration.md,了解:

  • 导入更新(@jest/globals → bun:test)
  • 模拟语法变更(jest.fn() → mock())
  • 配置迁移
  • 兼容性说明

主要变更:

// Before (Jest)
import { describe, it, expect } from '@jest/globals';
const mockFn = jest.fn();

// After (Bun)
import { describe, it, expect, mock } from 'bun:test';
const mockFn = mock();

常见测试模式

测试函数
import { test, expect } from "bun:test";

function add(a: number, b: number): number {
  return a + b;
}

test("add function", () => {
  expect(add(2, 3)).toBe(5);
  expect(add(-1, 1)).toBe(0);
});
测试错误
test("should throw errors", () => {
  const throwError = () => {
    throw new Error("Something went wrong");
  };

  expect(throwError).toThrow("Something went wrong");
  expect(throwError).toThrow(Error);
});

test("should reject promises", async () => {
  const asyncReject = async () => {
    throw new Error("Async error");
  };

  await expect(asyncReject()).rejects.toThrow("Async error");
});
快照测试
test("should match snapshot", () => {
  const data = {
    id: 1,
    name: "Test User",
    email: "[email protected]",
  };

  expect(data).toMatchSnapshot();
});

test("should match inline snapshot", () => {
  const config = { theme: "dark", language: "en" };

  expect(config).toMatchInlineSnapshot(`
    {
      "theme": "dark",
      "language": "en"
    }
  `);
});

匹配器参考

常见的可用匹配器:

// Equality
expect(value).toBe(expected);           // ===
expect(value).toEqual(expected);        // Deep equality

// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeDefined();
expect(value).toBeUndefined();

// Numbers
expect(number).toBeGreaterThan(3);
expect(number).toBeLessThan(5);

// Strings
expect(string).toMatch(/pattern/);
expect(string).toContain("substring");

// Arrays
expect(array).toContain(item);
expect(array).toHaveLength(3);

// Objects
expect(object).toHaveProperty("key");
expect(object).toMatchObject({ subset });

// Promises
await expect(promise).resolves.toBe(value);
await expect(promise).rejects.toThrow();

// Mock functions
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(3);
expect(mockFn).toHaveBeenCalledWith(arg1, arg2);

测试组织

设置和清理
import { beforeAll, afterAll, beforeEach, afterEach, describe, it } from "bun:test";

describe("User service", () => {
  let db: Database;

  beforeAll(async () => {
    // Setup before all tests
    db = await connectToDatabase();
  });

  afterAll(async () => {
    // Cleanup after all tests
    await db.close();
  });

  beforeEach(async () => {
    // Reset before each test
    await db.clear();
  });

  it("should create user", async () => {
    const user = await db.users.create({ name: "Test" });
    expect(user.id).toBeDefined();
  });
});

覆盖率配置

查看覆盖率报告:

# Generate coverage
bun test --coverage

# View HTML report
bun test --coverage --reporter=html
open coverage/index.html

在 bunfig.toml 中设置覆盖率阈值:

[test]
coverage = true
coverageThreshold = 80  # Fail if coverage < 80%

调试测试

# Run with debugger
bun test --inspect

# Verbose output
bun test --verbose

# Show all test results
bun test --reporter=tap

性能

Bun 测试的速度显著快于 Jest:

  • Jest:100 个测试约需 15 秒
  • Bun:100 个测试约需 2 秒

执行速度快 3–10 倍!

完成检查清单

  • ✅ 已创建测试目录结构
  • ✅ 已配置 bunfig.toml
  • ✅ 已创建测试设置文件
  • ✅ 已编写示例测试
  • ✅ 已更新 package.json 脚本
  • ✅ 测试运行成功
  • ✅ 已配置覆盖率(如有需要)

后续步骤

完成基本设置后:

  1. 编写测试:为关键业务逻辑添加测试
  2. CI/CD:配置测试在流水线中运行
  3. 覆盖率:设置覆盖率报告
  4. 提交前检查:添加提交前钩子以运行测试
  5. 文档:为团队记录测试模式

如需了解详细实现,请参阅上方链接的参考文件。

评论

支持 Markdown