Learn how to use Bun’s built-in code coverage reporting to track test coverage and find untested areas in your codebase
Bun’s test runner now supports built-in code coverage reporting. This makes it easy to see how much of the codebase is covered by tests, and find areas that are not currently well-tested.
bun:test supports seeing which lines of code are covered by tests. To use this feature, pass --coverage to the CLI. It will print out a coverage report to the console:
To always enable coverage reporting by default, add the following line to your bunfig.toml:
bunfig.toml
Copy
Ask AI
[test]# Always enable coveragecoverage = true
By default coverage reports will include test files and exclude sourcemaps. This is usually what you want, but it can be configured otherwise in bunfig.toml.
It is possible to specify a coverage threshold in bunfig.toml. If your test suite does not meet or exceed this threshold, bun test will exit with a non-zero exit code to indicate the failure.
By default, coverage reports will be printed to the console.For persistent code coverage reports in CI environments and for other tools, you can pass a --coverage-reporter=lcov CLI option or coverageReporter option in bunfig.toml.
This option accepts glob patterns and works similarly to Jest’s collectCoverageFrom ignore patterns. Files matching any of these patterns will be excluded from coverage calculation and reporting in both text and LCOV outputs.
Internally, Bun transpiles all files by default, so Bun automatically generates an internal source map that maps lines of your original source code onto Bun’s internal representation. If for any reason you want to disable this, set test.coverageIgnoreSourcemaps to true; this will rarely be desirable outside of advanced use cases.
# Run coverage only on specific test filesbun test --coverage src/components/*.test.ts# Run coverage with name patternbun test --coverage --test-name-pattern="API"
// Good: Test actual functionalitytest('calculateTax should handle different tax rates', () => { expect(calculateTax(100, 0.08)).toBe(8); expect(calculateTax(100, 0.1)).toBe(10); expect(calculateTax(0, 0.08)).toBe(0);});// Avoid: Just hitting lines for coveragetest('calculateTax exists', () => { calculateTax(100, 0.08); // No assertions!});
test('user input validation', () => { // Test normal case expect(validateEmail('user@example.com')).toBe(true); // Test edge cases that improve coverage meaningfully expect(validateEmail('')).toBe(false); expect(validateEmail('invalid')).toBe(false); expect(validateEmail(null)).toBe(false);});
If files aren’t appearing in coverage reports, they might not be imported by your tests. Coverage only tracks files that are actually loaded.
test.ts
Copy
Ask AI
// Make sure to import the modules you want to testimport {myFunction} from '../src/my-module';test('my function works', () => { expect(myFunction()).toBeDefined();});