mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 19:08:50 +00:00
## Summary Adds a new `concurrentTestGlob` configuration option to bunfig.toml that allows test files matching a glob pattern to automatically run with concurrent test execution enabled. This provides granular control over which tests run concurrently without modifying test files or using the global `--concurrent` flag. ## Problem Currently, enabling concurrent test execution in Bun requires either: 1. Using the `--concurrent` flag (affects ALL tests) 2. Manually adding `test.concurrent()` to individual test functions (requires modifying test files) This creates challenges for: - Large codebases wanting to gradually migrate to concurrent testing - Projects with mixed test types (unit tests that need isolation vs integration tests that can run in parallel) - CI/CD pipelines that want to optimize test execution without code changes ## Solution This PR introduces a `concurrentTestGlob` option in bunfig.toml that automatically enables concurrent execution for test files matching a specified glob pattern: ```toml [test] concurrentTestGlob = "**/concurrent-*.test.ts" ``` ### Key Features - ✅ Non-breaking: Completely opt-in via configuration - ✅ Flexible: Use glob patterns to target specific test files or directories - ✅ Override-friendly: `--concurrent` flag still forces all tests to run concurrently - ✅ Zero code changes: No need to modify existing test files ## Implementation Details ### Code Changes 1. Added `concurrent_test_glob` field to `TestOptions` struct (`src/cli.zig`) 2. Added parsing for `concurrentTestGlob` from bunfig.toml (`src/bunfig.zig`) 3. Added `concurrent_test_glob` field to `TestRunner` (`src/bun.js/test/jest.zig`) 4. Implemented `shouldFileRunConcurrently()` method that checks file paths against the glob pattern 5. Updated test execution logic to apply concurrent mode based on glob matching (`src/bun.js/test/ScopeFunctions.zig`) ### How It Works - When a test file is loaded, its path is checked against the configured glob pattern - If it matches, all tests in that file run concurrently (as if `--concurrent` was passed) - Files not matching the pattern run sequentially as normal - The `--concurrent` CLI flag overrides this behavior when specified ## Usage Examples ### Basic Usage ```toml # bunfig.toml [test] concurrentTestGlob = "**/integration/*.test.ts" ``` ### Multiple Patterns ```toml [test] concurrentTestGlob = [ "**/integration/*.test.ts", "**/e2e/*.test.ts", "**/concurrent-*.test.ts" ] ``` ### Migration Strategy Teams can gradually migrate to concurrent testing: 1. Start with integration tests: `"**/integration/*.test.ts"` 2. Add stable unit tests: `"**/fast-*.test.ts"` 3. Eventually migrate most tests except those requiring isolation ## Testing Added comprehensive test coverage in `test/cli/test/concurrent-test-glob.test.ts`: - ✅ Tests matching glob patterns run concurrently (verified via execution order logging) - ✅ Tests not matching patterns run sequentially (verified via shared state and execution order) - ✅ `--concurrent` flag properly overrides the glob setting - Tests use file system logging to deterministically verify concurrent vs sequential execution ## Documentation Complete documentation added: - `docs/runtime/bunfig.md` - Configuration reference - `docs/test/configuration.md` - Test configuration details - `docs/test/examples/concurrent-test-glob.md` - Comprehensive example with migration guide ## Performance Considerations - Glob matching happens once per test file during loading - Uses Bun's existing `glob.match()` implementation - Minimal overhead: simple string pattern matching - Future optimization: Could cache match results per file path ## Breaking Changes None. This is a fully backward-compatible, opt-in feature. ## Checklist - [x] Implementation complete and building - [x] Tests passing - [x] Documentation updated - [x] No breaking changes - [x] Follows existing code patterns ## Related Issues This addresses common requests for more granular control over concurrent test execution, particularly for large codebases migrating from other test runners. 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
133 lines
3.5 KiB
Markdown
133 lines
3.5 KiB
Markdown
# Concurrent Test Glob Example
|
|
|
|
This example demonstrates how to use the `concurrentTestGlob` option to selectively run tests concurrently based on file naming patterns.
|
|
|
|
## Project Structure
|
|
|
|
```text
|
|
my-project/
|
|
├── bunfig.toml
|
|
├── tests/
|
|
│ ├── unit/
|
|
│ │ ├── math.test.ts # Sequential
|
|
│ │ └── utils.test.ts # Sequential
|
|
│ └── integration/
|
|
│ ├── concurrent-api.test.ts # Concurrent
|
|
│ └── concurrent-database.test.ts # Concurrent
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### bunfig.toml
|
|
|
|
```toml
|
|
[test]
|
|
# Run all test files with "concurrent-" prefix concurrently
|
|
concurrentTestGlob = "**/concurrent-*.test.ts"
|
|
```
|
|
|
|
## Test Files
|
|
|
|
### Unit Test (Sequential)
|
|
|
|
`tests/unit/math.test.ts`
|
|
|
|
```typescript
|
|
import { test, expect } from "bun:test";
|
|
|
|
// These tests run sequentially by default
|
|
// Good for tests that share state or have specific ordering requirements
|
|
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/integration/concurrent-api.test.ts`
|
|
|
|
```typescript
|
|
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);
|
|
});
|
|
|
|
test("fetch posts", async () => {
|
|
const response = await fetch("/api/posts");
|
|
expect(response.ok).toBe(true);
|
|
});
|
|
|
|
test("fetch comments", async () => {
|
|
const response = await fetch("/api/comments");
|
|
expect(response.ok).toBe(true);
|
|
});
|
|
```
|
|
|
|
## Running Tests
|
|
|
|
```bash
|
|
# 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/integration
|
|
```
|
|
|
|
## Benefits
|
|
|
|
1. **Gradual Migration**: Migrate to concurrent tests file by file by renaming them
|
|
2. **Clear Organization**: File naming convention indicates execution mode
|
|
3. **Performance**: Integration tests run faster in parallel
|
|
4. **Safety**: Unit tests remain sequential where needed
|
|
5. **Flexibility**: Easy to change execution mode by renaming files
|
|
|
|
## Migration Strategy
|
|
|
|
To migrate existing tests to concurrent execution:
|
|
|
|
1. Start with independent integration tests
|
|
2. Rename files to match the glob pattern: `mv api.test.ts concurrent-api.test.ts`
|
|
3. Verify tests still pass
|
|
4. Monitor for race conditions or shared state issues
|
|
5. Continue migrating stable tests incrementally
|
|
|
|
## Tips
|
|
|
|
- Use descriptive prefixes: `concurrent-`, `parallel-`, `async-`
|
|
- Keep related sequential tests together
|
|
- Document why certain tests must remain sequential
|
|
- Use `test.concurrent()` for fine-grained control in sequential files
|
|
(In files matched by `concurrentTestGlob`, plain `test()` already runs concurrently)
|
|
- Consider separate globs for different test types:
|
|
|
|
```toml
|
|
[test]
|
|
# Multiple patterns for different test categories
|
|
concurrentTestGlob = [
|
|
"**/integration/*.test.ts",
|
|
"**/e2e/*.test.ts",
|
|
"**/concurrent-*.test.ts"
|
|
]
|
|
```
|