Bun provides a built-in Jest-compatible test runner that executes tests without requiring external dependencies. This framework includes test discovery, execution lifecycle management, an extensive expect API with matchers, snapshot testing, mocking capabilities, and multiple reporting formats. The test runner is implemented primarily in Rust, with C++ bindings exposed through the bun:test module.
For information about the CLI interface to the test runner, see Test Command.
Before test execution begins, the test runner discovers test files using glob patterns. By default, files matching these patterns are discovered:
**/*.test.{js,jsx,ts,tsx,cjs,mjs}**/*_test.{js,jsx,ts,tsx,cjs,mjs}**/test-*.{js,jsx,ts,tsx,cjs,mjs}Files can be filtered using:
The test runner handles various module formats including ESM import, CommonJS require, and dynamic import() test/cli/test/bun-test.test.ts142-197
Sources: test/cli/test/bun-test.test.ts7-197
The test runner orchestration involves managing test registration via test() and describe() blocks, and coordinating lifecycle hooks. It supports concurrent and serial execution modes.
The core components are:
| Component | Source | Role |
|---|---|---|
TestCommand | src/runtime/cli/test_command.rs | CLI entry point, code coverage, reporter setup |
Scanner | src/runtime/cli/test/Scanner.rs | File discovery using glob patterns |
Coordinator | src/runtime/cli/test/parallel/runner.rs | Spawns and manages worker processes |
Worker | src/runtime/cli/test/parallel/runner.rs | Runs test files in isolated processes |
IsolatedModuleCache | src/jsc/bindings/IsolatedModuleCache.h | Per-VM module cache for --isolate mode |
CommandLineReporter | src/runtime/cli/test_command.rs | Formats test output to stderr |
The Coordinator spawns Worker subprocesses (one per test file or batch), communicates via Channel using framed messages (Frame), and merges result fragments. The Worker reads commands from stdin, executes each test file under a fresh module scope, and streams results back on fd 3 src/runtime/cli/test/parallel/runner.rs1-45
The Scanner struct walks the filesystem using a VecDeque-backed FIFO (Fifo), filtering by exclusion_names, filter_names, and path_ignore_patterns. It populates test_files as a Vec<Interned> src/runtime/cli/test/Scanner.rs19-48
For details, see Test Runner Architecture.
Title: Test Framework Component Mapping (code entities)
Sources: src/runtime/cli/test_command.rs1-30 src/runtime/cli/test/Scanner.rs19-48 src/runtime/cli/test/parallel/runner.rs1-45 src/jsc/bindings/IsolatedModuleCache.h1-30 packages/bun-types/test.d.ts16-227
The Expect assertion system is the primary way to validate test results. It handles complex types like Set, Map, and circular objects.
For details, see Expect API and Matchers.
Title: Expect API type hierarchy
toBe() uses strict reference equality (SameValueZero); for objects and arrays use toEqual() (deep) or toStrictEqual() (deep + class + undefined properties) packages/bun-types/test.d.ts960-1056.resolves and .rejects chains assert on Promise outcomes packages/bun-types/test.d.ts920-929 test/js/bun/test/expect.test.js88-142expect.any(Ctor), expect.anything(), expect.arrayContaining(), expect.objectContaining(), expect.stringContaining(), expect.stringMatching(), expect.closeTo() packages/bun-types/test.d.ts770-833jest-extended style matchers including toBeEmpty(), toBeOneOf(), toSatisfy(), toBeOdd(), toBeEven(), toContainKey(), toContainAllKeys(), and others test/js/bun/test/jest-extended.test.js17-191expectTypeOf utility provides compile-time type assertions packages/bun-types/test.d.ts241-244expect.extend() registers new matcher implementations packages/bun-types/test.d.ts658-684expect.assertions(n) and expect.hasAssertions() validate that a specific number of assertions ran packages/bun-types/test.d.ts710-715Sources: packages/bun-types/test.d.ts617-716 packages/bun-types/test.d.ts770-898 test/js/bun/test/expect.test.js46-203 test/js/bun/test/jest-extended.test.js17-191
Snapshot testing allows developers to assert against a "known good" serialized state via toMatchSnapshot() and toMatchInlineSnapshot(). Bun generates snapshots in a __snapshots__ directory with a .snap extension.
Snapshot files use one of two header formats:
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots — for files created by Bun// Jest Snapshot v1, ... — for backwards compatibility with Jest-generated filesEach snapshot is keyed by exports[\{testName} {index}`]` test/regression/issue/__snapshots__/03830.test.ts.snap1-8
Running bun test -u (or --update-snapshots) regenerates stored snapshots. New snapshots cannot be committed in CI when the CI environment variable is true unless -u is provided test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts205-221
For details, see Snapshot Testing.
Sources: test/js/bun/test/snapshot-tests/snapshots/__snapshots__/snapshot.test.ts.snap1-10 test/regression/issue/__snapshots__/03830.test.ts.snap1-8 test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts8-165
Bun includes a mocking system compatible with jest.fn() and Vitest's vi.fn().
For details, see Mock System.
mock(fn?) and jest.fn(fn?) create trackable mock functions of type Mock<T> packages/bun-types/test.d.ts17-20spyOn(obj, method) wraps existing object methods to track calls without replacing the implementation packages/bun-types/test.d.ts107-110mock.module(id, factory) replaces an entire module's exports for the duration of the test suite packages/bun-types/test.d.ts38-49mock.restore() restores all previously mocked modules; mock.clearAllMocks() resets call state without restoring implementations packages/bun-types/test.d.ts51-58jest.useFakeTimers(options?) / jest.useRealTimers(), jest.advanceTimersByTime(ms), jest.runAllTimers(), and jest.runOnlyPendingTimers() manipulate fake timer state packages/bun-types/test.d.ts98-106setSystemTime(date?) and jest.setSystemTime(date?) freeze or reset Date.now() and new Date() packages/bun-types/test.d.ts61-89vi namespace: The vi export is an alias for the jest namespace, providing Vitest API compatibility packages/bun-types/test.d.ts170-201Sources: packages/bun-types/test.d.ts17-201 test/regression/issue/18820.test.ts1-10
Bun provides built-in reporters for both human consumption and machine processing.
For details, see Test Reporting.
The runner tracks passes, failures, skips, and todos. It handles unhandled errors occurring in various lifecycle stages:
beforeAll, beforeEach, afterEach, or afterAll are caught and reported as test failures or runner errors test/js/bun/test/test-test.test.ts12-53describe block or test file do not block the execution of others test/js/bun/test/test-test.test.ts188-229Sources: test/js/bun/test/test-test.test.ts12-229 test/js/bun/test/jest-hooks.test.ts3-250