Skip to main content
Bun automatically discovers test files based on naming conventions and directory structure.

Default discovery patterns

Bun recognizes test files with these patterns:

File extensions

  • *.test.ts
  • *.test.tsx
  • *.test.js
  • *.test.jsx
  • *.test.mjs
  • *.test.cjs
And with underscore:
  • *_test.ts
  • *_test.tsx
  • *_test.js
  • *_test.jsx
  • *_test.mjs
  • *_test.cjs

Test directories

Files in __tests__ directories:
project/
├── src/
│   ├── utils.ts
│   └── __tests__/
│       └── utils.ts          <- Discovered as test
└── components/
    ├── Button.tsx
    └── __tests__/
        └── Button.test.tsx    <- Discovered as test

Running all tests

Run all discovered tests:
$ bun test
Bun searches the current directory and subdirectories for test files.

Running specific tests

Specific file

$ bun test path/to/file.test.ts

Multiple files

$ bun test file1.test.ts file2.test.ts

Directory

$ bun test src/components/

Pattern matching

# Run all test files containing "auth"
$ bun test auth

# Fuzzy match
$ bun test compo/butt
# Matches: components/Button.test.tsx

Test file structure

Colocate tests with source code:
project/
├── src/
│   ├── math.ts
│   ├── math.test.ts
│   ├── utils.ts
│   └── utils.test.ts
└── package.json
Or separate test directory:
project/
├── src/
│   ├── math.ts
│   └── utils.ts
├── test/
│   ├── math.test.ts
│   └── utils.test.ts
└── package.json

Configuration

Configure test discovery in bunfig.toml:

Root directory

Set the root directory for test discovery:
[test]
root = "./src"
Bun will only search for tests in ./src and its subdirectories.

Custom patterns

Configure custom test file patterns:
[test]
patterns = [
  "**/*.test.ts",
  "**/*.spec.ts",
  "**/__tests__/**/*.ts"
]

Exclude patterns

Exclude directories from test discovery:
[test]
exclude = [
  "**/node_modules/**",
  "**/dist/**",
  "**/*.d.ts"
]

Import resolution

Bun resolves imports in test files using the same rules as regular code:

Relative imports

import { add } from "./math";
import { expect, test } from "bun:test";

test("add", () => {
  expect(add(1, 2)).toBe(3);
});

Package imports

import { test, expect } from "bun:test";
import { format } from "date-fns";

test("date formatting", () => {
  expect(format(new Date("2024-01-01"), "yyyy-MM-dd")).toBe("2024-01-01");
});

Path mapping

Use tsconfig.json path mapping:
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
import { add } from "@/math";
import { test, expect } from "bun:test";

test("add", () => {
  expect(add(1, 2)).toBe(3);
});

Preloading modules

Load modules before running tests:
[test]
preload = [
  "./test/setup.ts",
  "./test/global-mocks.ts"
]
Preloaded files run before any test files are loaded. Use this for:
  • Setting up global test utilities
  • Mocking built-in modules
  • Configuring test environment
#test/setup.ts
import { beforeAll } from "bun:test";

beforeAll(() => {
  // Global setup
  process.env.NODE_ENV = "test";
});

Test execution order

Bun runs tests in this order:
  1. Load preload modules (from bunfig.toml)
  2. Discover test files
  3. Load each test file
  4. Execute tests in each file:
    • beforeAll hooks
    • For each test:
      • beforeEach hooks
      • Test function
      • afterEach hooks
    • afterAll hooks

Parallel execution

Bun can run test files in parallel:
$ bun test --concurrent
Or configure in bunfig.toml:
[test]
concurrent = true
Tests within the same file always run sequentially. Only different test files run in parallel.

Filtering tests

By name pattern

$ bun test --test-name-pattern "user authentication"
Only tests whose names match the pattern will run.

By file pattern

$ bun test "src/**/*.integration.test.ts"

By label

Coming soon: Filter tests by custom labels.

Debugging test discovery

See which tests Bun discovers:
$ bun test --dry-run
This lists all test files without running them.

Performance tips

Reduce test discovery time

Limit search scope:
[test]
root = "./src"
exclude = ["**/node_modules/**", "**/dist/**"]

Optimize test file size

Split large test files:
❌ utils.test.ts (1000 tests)

✅ utils/
   ├── string.test.ts (200 tests)
   ├── array.test.ts (200 tests)
   ├── object.test.ts (200 tests)
   ├── number.test.ts (200 tests)
   └── date.test.ts (200 tests)

Use concurrent tests

Mark tests as concurrent when possible:
import { test } from "bun:test";

test.concurrent("test 1", async () => {
  // ...
});

test.concurrent("test 2", async () => {
  // ...
});

Build docs developers (and LLMs) love