Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion docs/test/code-coverage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,59 @@ jobs:
file: ./coverage/lcov.info
```

## Including Uncovered Files

By default, coverage reports only include files that are actually imported by your tests. To also show files that aren't imported by any test (with 0% coverage), use the `collectCoverageFrom` option — similar to Jest's [`collectCoverageFrom`](https://jestjs.io/docs/configuration#collectcoveragefrom-array) configuration.

### Configuration

```toml title="bunfig.toml" icon="settings"
[test]
collectCoverageFrom = [
"src/**/*.ts",
"src/**/*.tsx",
"!src/**/*.d.ts"
]
```

This accepts glob patterns specifying which source files should be included in coverage reports, even if no test imports them. Files matching these patterns that are not loaded during tests will appear in the coverage report with 0% coverage for both functions and lines.

### Example Output

```bash terminal icon="terminal"
bun test --coverage

-------------|---------|---------|-------------------
File | % Funcs | % Lines | Uncovered Line #s
-------------|---------|---------|-------------------
All files | 50.00 | 60.00 |
src/
tested.ts | 100.00 | 100.00 |
untested.ts| 0.00 | 0.00 | Not imported by tests
-------------|---------|---------|-------------------
```

Files that are not imported by any test will show "Not imported by tests" in the uncovered lines column, making it easy to identify source files that have no test coverage at all.

### Common Patterns

```toml title="bunfig.toml" icon="settings"
[test]
# Include all TypeScript source files
collectCoverageFrom = ["src/**/*.ts", "src/**/*.tsx"]

# Include specific directories
collectCoverageFrom = ["src/components/**/*.ts", "src/utils/**/*.ts"]

# Single pattern
collectCoverageFrom = "src/**/*.ts"
```

The `collectCoverageFrom` option works together with other coverage options:
- Files matching `coveragePathIgnorePatterns` will still be excluded
- If `coverageSkipTestFiles` is enabled, test files will be excluded
- `node_modules` and hidden directories (starting with `.`) are always excluded

## Excluding Files from Coverage

### Skip Test Files
Expand Down Expand Up @@ -373,7 +426,16 @@ Coverage is just one metric. Also consider:

### Coverage Not Showing for Some Files

If files aren't appearing in coverage reports, they might not be imported by your tests. Coverage only tracks files that are actually loaded.
If files aren't appearing in coverage reports, they might not be imported by your tests. You have two options:

1. **Use `collectCoverageFrom`** to automatically include all source files in the coverage report, even if they aren't imported by tests:

```toml title="bunfig.toml" icon="settings"
[test]
collectCoverageFrom = ["src/**/*.ts"]
```

2. **Import the modules** in your test files:

```ts title="test.ts" icon="/icons/typescript.svg"
// Make sure to import the modules you want to test
Expand Down
23 changes: 23 additions & 0 deletions docs/test/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,25 @@ coverageThreshold = {
}
```

### Collect Coverage From

Specify glob patterns for source files that should be included in coverage reports, even if they are not imported by any test. This is equivalent to Jest's [`collectCoverageFrom`](https://jestjs.io/docs/configuration#collectcoveragefrom-array) option.

```toml title="bunfig.toml" icon="settings"
[test]
# Single pattern
collectCoverageFrom = "src/**/*.ts"

# Multiple patterns
collectCoverageFrom = [
"src/**/*.ts",
"src/**/*.tsx",
"lib/**/*.js"
]
```

Files matching these patterns that are not loaded during tests will appear in coverage reports with 0% coverage, making it easy to identify completely untested source files. See the [coverage documentation](/test/code-coverage#including-uncovered-files) for more details and examples.

### Coverage Path Ignore Patterns

Exclude specific files or file patterns from coverage reports using glob patterns:
Expand Down Expand Up @@ -426,6 +445,10 @@ coverageReporter = ["text", "lcov"]
coverageDir = "./coverage"
coverageThreshold = { lines = 0.85, functions = 0.90, statements = 0.80 }
coverageSkipTestFiles = true
collectCoverageFrom = [
"src/**/*.ts",
"src/**/*.tsx"
]
coveragePathIgnorePatterns = [
"**/*.spec.ts",
"src/utils/**",
Expand Down
28 changes: 28 additions & 0 deletions src/bunfig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,34 @@ pub const Bunfig = struct {
},
}
}

if (test_.get("collectCoverageFrom")) |expr| brk: {
switch (expr.data) {
.e_string => |str| {
const pattern = try str.string(allocator);
const patterns = try allocator.alloc(string, 1);
patterns[0] = pattern;
this.ctx.test_options.coverage.collect_coverage_from = patterns;
},
.e_array => |arr| {
if (arr.items.len == 0) break :brk;

const patterns = try allocator.alloc(string, arr.items.len);
for (arr.items.slice(), 0..) |item, i| {
if (item.data != .e_string) {
try this.addError(item.loc, "collectCoverageFrom array must contain only strings");
return;
}
patterns[i] = try item.data.e_string.string(allocator);
}
this.ctx.test_options.coverage.collect_coverage_from = patterns;
},
else => {
try this.addError(expr.loc, "collectCoverageFrom must be a string or array of strings");
return;
},
}
}
}
}

Expand Down
Loading