Test runner
Write bun:test suites, isolate dependencies, and run stable CI tests
Last updated on
Minimal test
import { describe, expect, test } from 'bun:test';
describe('sum', () => {
test('adds values', () => {
expect(2 + 3).toBe(5);
});
});bun test
bun test sum
bun test --watch
bun test --coverageBun discovers conventional *.test.*, *_test.*, *.spec.*, and *_spec.* files.
Lifecycle and async tests
import { afterEach, beforeEach, expect, test } from 'bun:test';
let controller: AbortController;
beforeEach(() => {
controller = new AbortController();
});
afterEach(() => {
controller.abort();
});
test('loads data', async () => {
const response = await fetch('https://example.com', {
signal: controller.signal,
});
expect(response.ok).toBe(true);
});Real tests should replace external network calls so they remain repeatable and cannot mutate production data.
Mocking order of preference
- Test pure functions directly.
- Inject network, clock, random, filesystem, and database boundaries.
- Use module mocks only when the boundary cannot reasonably be refactored.
- Restore state after every test; avoid order dependence.
Isolation, parallelism, and CI shards
Bun 1.3.13 added file-level isolation and worker parallelism for larger suites:
# Detect state leaking between files locally
bun test --isolate
# Parallel CI workers; --parallel implies --isolate
bun test --parallel --coverage
# Three independent CI jobs
bun test --shard=1/3
bun test --shard=2/3
bun test --shard=3/3Database integration tests, fixed ports, and shared temporary directories may not be parallel-safe. Allocate a database or schema, port, and temporary directory per worker, or keep that group in a serial job.
Coverage and flaky tests
[test]
coverage = true
coverageReporter = ["text", "lcov"]
coverageDir = "./coverage"
coverageSkipTestFiles = true
coverageThreshold = 0.8The test process exits non-zero below the threshold. Coverage proves execution, not meaningful assertions; keep explicit scenarios for security, authorization, and migration paths.
bun test --randomize
bun test --seed 12345
bun test --retry 2
bun test --rerun-each 20Do not hide deterministic bugs behind unbounded retries. Record the failing seed, shard, and Bun version in CI.
Compact output for coding agents
AGENT=1 bun testBun suppresses per-test passing noise while retaining failures and the summary. Quiet output does not change the exit status and does not replace complete CI logs.
Migrating from Jest
Bun targets Jest compatibility, but verify custom environments, DOM setup, complex fake timers, Jest-only transformers, native extensions, and snapshot workflows. Start with isolated unit tests, not the most customized suite.
Official references: Test runner, test configuration, and Bun 1.3.13.