bun test: The Built-in Test Runner
bun test discovers and runs *.test.ts and *.spec.ts files with a built-in, Jest-compatible runner, no extra dependency required.
bun test ships with Bun, so there is nothing to install for unit tests. It speaks a Jest-like API (describe, test, expect), runs TypeScript natively, and is fast enough to leave watch mode running locally.
What it does
bun test finds test files matching *.test.{js,ts,tsx} and *.spec.{js,ts,tsx}, runs them with the built-in runner, and reports pass/fail. It supports a Jest-compatible expect, lifecycle hooks, mocks, snapshots, and built-in coverage via --coverage.
Common usage
bun test
bun test --coverage # collect coverage
bun test ./src/auth # only tests under a path
bun test -t "login" # only tests whose name matches
bun test --timeout 10000 # per-test timeout in msOptions
| Flag | What it does |
|---|---|
| --coverage | Collect and print code coverage |
| -t / --test-name-pattern <re> | Run only tests whose name matches |
| --timeout <ms> | Per-test timeout (default 5000 ms) |
| --bail [n] | Stop after n failures (default 1) |
| --watch | Re-run on changes (local, not CI) |
| --rerun-each <n> | Run each test n times to catch flakes |
In CI
bun test exits non-zero on any failure, so it gates a pipeline cleanly. Use --bail to fail fast and --coverage with a threshold in bunfig.toml to enforce coverage. Note bun test is the runner; it does not read vitest or jest config files, so a project on Vitest will not run as-is under bun test.
Common errors in CI
"error: Cannot find module" inside a test usually means a path alias bun test does not resolve; configure paths via tsconfig or bunfig. "Test timed out after 5000ms" means an async test never resolved; raise --timeout or fix the hanging promise. "0 tests found" means the file naming does not match *.test.* / *.spec.*, or you pointed at the wrong directory.