Guides Test Runner
Selectively run tests concurrently with glob patterns
Set a glob pattern to decide which tests from which files run in parallel
The concurrentTestGlob option in bunfig.toml runs tests concurrently in files whose names match a glob pattern.
Project Structure
my-project/
├── bunfig.toml
├── tests/
│ ├── unit/
│ │ ├── math.test.ts # Sequential
│ │ └── utils.test.ts # Sequential
│ └── integration/
│ ├── concurrent-api.test.ts # Concurrent
│ └── concurrent-database.test.ts # ConcurrentConfiguration
Configure your bunfig.toml to run test files with the "concurrent-" prefix concurrently:
[test]
# Run all test files with "concurrent-" prefix concurrently
concurrentTestGlob = "**/concurrent-*.test.ts"Test Files
Unit Test (Sequential)
Tests that share state or depend on ordering should stay sequential:
import { test, expect } from "bun:test";
// These tests run sequentially by default
let sharedState = 0;
test("addition", () => {
sharedState = 5 + 3;
expect(sharedState).toBe(8);
});
test("uses previous state", () => {
// This test depends on the previous test's state
expect(sharedState).toBe(8);
});Integration Test (Concurrent)
Tests in files matching the glob pattern automatically run concurrently:
import { test, expect } from "bun:test";
// These tests automatically run concurrently due to filename matching the glob pattern.
// Using test() is equivalent to test.concurrent() when the file matches concurrentTestGlob.
// Each test is independent and can run in parallel.
test("fetch user data", async () => {
const response = await fetch("/api/user/1");
expect(response.ok).toBe(true);
});
// can also use test.concurrent() for explicitly marking it as concurrent
test.concurrent("fetch posts", async () => {
const response = await fetch("/api/posts");
expect(response.ok).toBe(true);
});
// can also use test.serial() for explicitly marking it as sequential
test.serial("fetch comments", async () => {
const response = await fetch("/api/comments");
expect(response.ok).toBe(true);
});Running Tests
# Run all tests - concurrent-*.test.ts files will run concurrently
$ bun test
# Override: Force ALL tests to run concurrently
# Note: This overrides bunfig.toml and runs all tests concurrently, regardless of glob
$ bun test --concurrent
# Run only unit tests (sequential)
$ bun test tests/unit
# Run only integration tests (concurrent due to glob pattern)
$ bun test tests/integrationBenefits
- Gradual migration: rename files one at a time to move them to concurrent execution
- Clear organization: the filename tells you how a file's tests run
- Performance: independent integration tests finish faster in parallel
- Safety: unit tests stay sequential where they need to
Migration Strategy
To migrate existing tests to concurrent execution:
- Start with independent integration tests - these typically don't share state
- Rename files to match the glob pattern:
mv api.test.ts concurrent-api.test.ts - Run
bun test- check for race conditions and flaky or unexpected failures - Continue migrating stable tests file by file
Tips
- Use descriptive prefixes:
concurrent-,parallel-,async- - Keep related sequential tests together in the same directory
- Document why certain tests must remain sequential with comments
- Use
test.concurrent()for fine-grained control in sequential files (in files matched byconcurrentTestGlob, plaintest()already runs concurrently)
Multiple Patterns
concurrentTestGlob also accepts multiple patterns:
[test]
concurrentTestGlob = [
"**/integration/*.test.ts",
"**/e2e/*.test.ts",
"**/concurrent-*.test.ts"
]Tests in files matching any of these patterns run concurrently:
- All tests in
integration/directories - All tests in
e2e/directories - All tests with
concurrent-prefix anywhere in the project