Claude-skill-registry bun-test
Configure Bun's built-in test runner with Jest-compatible APIs. Use when setting up testing infrastructure, writing unit/integration/snapshot tests, migrating from Jest, or configuring test coverage. 3-10x faster than Jest.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/bun-test" ~/.claude/skills/majiayu000-claude-skill-registry-bun-test && rm -rf "$T"
skills/data/bun-test/SKILL.mdBun Test Configuration
Set up Bun's built-in test runner with Jest-compatible APIs and significantly faster execution (3-10x faster than Jest).
Quick Reference
For detailed patterns, see:
- Jest Migration: jest-migration.md - Complete Jest to Bun migration guide
- Mocking: mocking.md - Mock functions, spies, module mocking
- Examples: examples.md - Test patterns for APIs, databases, async code
Core Workflow
1. Check Prerequisites
# Verify Bun installation bun --version # Check if project exists ls -la package.json
2. Determine Testing Needs
Ask the user what type of testing they need:
- Unit Testing: Test individual functions and modules
- Integration Testing: Test component interactions
- API Testing: Test HTTP endpoints
- Snapshot Testing: Test output consistency
3. Create Test Directory Structure
# Create test directories mkdir -p tests/{unit,integration,fixtures}
Recommended structure:
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. Configure Bun Test
Create
bunfig.toml in project root:
[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. Create Test Setup File
Create
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. Write First Test
Create
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); }); });
For more test examples (API testing, database testing, etc.), see examples.md.
7. Add Mocking (If Needed)
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); }); });
For advanced mocking patterns, see mocking.md.
8. Update package.json
Add test scripts:
{ "scripts": { "test": "bun test", "test:watch": "bun test --watch", "test:coverage": "bun test --coverage", "test:ui": "bun test --coverage --reporter=html" } }
9. Run Tests
# 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 Migration
If migrating from Jest, see jest-migration.md for:
- Import updates (
→@jest/globals
)bun:test - Mock syntax changes (
→jest.fn()
)mock() - Configuration migration
- Compatibility notes
Key changes:
// 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();
Common Test Patterns
Testing Functions
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); });
Testing Errors
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"); });
Snapshot Testing
test("should match snapshot", () => { const data = { id: 1, name: "Test User", email: "test@example.com", }; expect(data).toMatchSnapshot(); }); test("should match inline snapshot", () => { const config = { theme: "dark", language: "en" }; expect(config).toMatchInlineSnapshot(` { "theme": "dark", "language": "en" } `); });
Matchers Reference
Common matchers available:
// 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);
Test Organization
Setup and Teardown
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(); }); });
Coverage Configuration
View coverage report:
# Generate coverage bun test --coverage # View HTML report bun test --coverage --reporter=html open coverage/index.html
Set coverage thresholds in
bunfig.toml:
[test] coverage = true coverageThreshold = 80 # Fail if coverage < 80%
Debugging Tests
# Run with debugger bun test --inspect # Verbose output bun test --verbose # Show all test results bun test --reporter=tap
Performance
Bun test is significantly faster than Jest:
- Jest: ~15 seconds for 100 tests
- Bun: ~2 seconds for 100 tests
3-10x faster execution!
Completion Checklist
- ✅ Test directory structure created
- ✅ bunfig.toml configured
- ✅ Test setup file created
- ✅ Example tests written
- ✅ Package.json scripts updated
- ✅ Tests run successfully
- ✅ Coverage configured (if needed)
Next Steps
After basic setup:
- Write tests: Add tests for critical business logic
- CI/CD: Configure tests to run in your pipeline
- Coverage: Set up coverage reporting
- Pre-commit: Add pre-commit hooks to run tests
- Documentation: Document testing patterns for the team
For detailed implementations, see the reference files linked above.