> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/oven-sh/bun/llms.txt
> Use this file to discover all available pages before exploring further.

# Test Runner

> Bun ships with a fast, built-in, Jest-compatible test runner with TypeScript support, lifecycle hooks, mocking, snapshot testing, and watch mode.

Bun ships with a fast, built-in, Jest-compatible test runner. Tests are executed with the Bun runtime and support the following features:

* TypeScript and JSX out of the box
* Lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`)
* Snapshot testing
* UI and DOM testing
* Watch mode with `--watch`
* Script preloading with `--preload`

<Note>
  Bun aims for compatibility with Jest, but not everything is implemented yet. To track progress, see the [Jest compatibility tracking issue](https://github.com/oven-sh/bun/issues/1825).
</Note>

## Running tests

```bash theme={null}
bun test
```

Tests are written in JavaScript or TypeScript with a Jest-like API imported from `bun:test`.

```typescript math.test.ts theme={null}
import { expect, test } from "bun:test";

test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});
```

## Test discovery

The runner recursively searches the working directory for files matching these patterns:

* `*.test.{js|jsx|ts|tsx}`
* `*_test.{js|jsx|ts|tsx}`
* `*.spec.{js|jsx|ts|tsx}`
* `*_spec.{js|jsx|ts|tsx}`

By default, `node_modules` and hidden directories (starting with `.`) are excluded.

### Run specific files

Pass a path starting with `./` or `/` to run a specific file:

```bash theme={null}
bun test ./test/auth.test.ts
```

Pass a substring filter to match files by path:

```bash theme={null}
bun test auth
```

This matches any file whose path contains `auth`, such as `src/auth/login.test.ts`.

### Filter by test name

Use `-t` / `--test-name-pattern` to filter by test name using a substring or regex pattern:

```bash theme={null}
bun test -t "should handle"
```

The pattern is matched against the full test title, including all parent `describe` block labels joined with spaces.

## Watch mode

Use `--watch` to re-run tests automatically when files change:

```bash theme={null}
bun test --watch
```

Only the affected test files are re-run when a source file changes.

## Timeouts

Use `--timeout` to set a per-test timeout in milliseconds. The default is `5000ms`.

```bash theme={null}
bun test --timeout 10000
```

You can also set a per-test timeout as the third argument to `test()`:

```typescript theme={null}
test("slow operation", async () => {
  const result = await heavyComputation();
  expect(result).toBeDefined();
}, 15000);
```

## Bail on failure

Use `--bail` to stop the test run after a given number of failures. This is useful in CI to avoid spending time on subsequent tests after early failures.

```bash theme={null}
# Stop after the first failure
bun test --bail

# Stop after 5 failures
bun test --bail=5
```

## Concurrent execution

By default, tests run sequentially within each file. Use `--concurrent` to run async tests in parallel:

```bash theme={null}
bun test --concurrent
```

Control the maximum concurrency with `--max-concurrency` (default: 20):

```bash theme={null}
bun test --concurrent --max-concurrency 4
```

You can also mark individual tests to run concurrently or serially:

```typescript theme={null}
import { test, expect } from "bun:test";

// Runs concurrently with other concurrent tests
test.concurrent("fetches user data", async () => {
  const res = await fetch("/api/user/1");
  expect(res.ok).toBe(true);
});

// Always runs sequentially, even with --concurrent
test.serial("updates shared state", () => {
  sharedCounter++;
  expect(sharedCounter).toBeGreaterThan(0);
});
```

## Retrying failed tests

Use `--retry` to automatically retry failed tests:

```bash theme={null}
bun test --retry 3
```

Override the retry count per test with the `{ retry: N }` option:

```typescript theme={null}
test("flaky network request", async () => {
  const res = await fetch("https://api.example.com");
  expect(res.ok).toBe(true);
}, { retry: 3 });
```

## Randomizing test order

Use `--randomize` to run tests in a random order, which helps detect hidden dependencies between tests:

```bash theme={null}
bun test --randomize
```

The seed used for randomization is printed in the summary. Use `--seed` to reproduce a specific order:

```bash theme={null}
bun test --seed 12345
```

## Reporters

Bun supports multiple output formats for test results.

<Tabs>
  <Tab title="Default">
    The default reporter prints human-readable results to the console with color support.

    ```bash theme={null}
    bun test
    ```
  </Tab>

  <Tab title="Dots">
    The dots reporter shows `.` for passing tests and `F` for failures — useful for large suites.

    ```bash theme={null}
    bun test --reporter=dots
    ```
  </Tab>

  <Tab title="JUnit XML">
    Generate a JUnit XML report for CI/CD systems like GitLab and Jenkins:

    ```bash theme={null}
    bun test --reporter=junit --reporter-outfile=./bun.xml
    ```

    Console output is preserved while the XML file is written at the end of the run.
  </Tab>
</Tabs>

## CI/CD integration

### GitHub Actions

Bun automatically detects GitHub Actions and emits annotations. No extra configuration is needed beyond installing Bun:

```yaml .github/workflows/test.yml theme={null}
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install
      - run: bun test
```

### AI agent integration

When running under an AI coding assistant, set one of these environment variables for quieter output that hides passing tests but preserves failures and the summary:

```bash theme={null}
# Claude Code
CLAUDECODE=1 bun test

# Generic agent flag
AGENT=1 bun test
```

## Lifecycle hooks

Bun supports `beforeAll`, `beforeEach`, `afterEach`, and `afterAll` hooks for setup and teardown. See [Test Lifecycle](/test/lifecycle) for full documentation.

## Mocks

Create mock functions with `mock()` from `bun:test`. See [Mocks & Spies](/test/mocks) for full documentation.

```typescript theme={null}
import { test, expect, mock } from "bun:test";

const random = mock(() => Math.random());

test("random", () => {
  const val = random();
  expect(val).toBeGreaterThan(0);
  expect(random).toHaveBeenCalledTimes(1);
});
```

## Snapshot testing

Use `.toMatchSnapshot()` to save and compare output across test runs. See [Snapshots](/test/snapshots) for full documentation.

```typescript theme={null}
import { test, expect } from "bun:test";

test("snapshot", () => {
  expect({ a: 1, b: "hello" }).toMatchSnapshot();
});
```

Update snapshots with:

```bash theme={null}
bun test --update-snapshots
```
