CoverBouncer.MSBuild
1.0.0-preview.10
dotnet add package CoverBouncer.MSBuild --version 1.0.0-preview.10
NuGet\Install-Package CoverBouncer.MSBuild -Version 1.0.0-preview.10
<PackageReference Include="CoverBouncer.MSBuild" Version="1.0.0-preview.10"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="CoverBouncer.MSBuild" Version="1.0.0-preview.10" />
<PackageReference Include="CoverBouncer.MSBuild"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add CoverBouncer.MSBuild --version 1.0.0-preview.10
#r "nuget: CoverBouncer.MSBuild, 1.0.0-preview.10"
#:package CoverBouncer.MSBuild@1.0.0-preview.10
#addin nuget:?package=CoverBouncer.MSBuild&version=1.0.0-preview.10&prerelease
#tool nuget:?package=CoverBouncer.MSBuild&version=1.0.0-preview.10&prerelease
đĒ Cover-Bouncer
The Coverage Doorman for .NET Projects
Cover-Bouncer enforces profile-based code coverage policies in your .NET projects. Tag your files, set thresholds, and let the bouncer keep your coverage standards high.
Why Cover-Bouncer?
Standard coverage tools give you one number: "X% coverage." But not all code is equal:
- Your critical business logic should have 90%+ coverage
- Your DTOs might not need any tests
- Your integration adapters need moderate coverage
Cover-Bouncer lets you enforce different coverage requirements for different parts of your codebase.
đ¨ Profiles Are Completely Customizable!
You are NOT limited to any specific profile names or percentages:
â Common Misconception: "I must use 'Critical' (90%), 'Standard' (80%), etc."
â Reality: "I can use ANY names with ANY thresholds!"
Examples of Valid Profiles:
{
"profiles": {
"MustHaveTests": { "minLine": 0.45 }, // Start achievable!
"NiceToHave": { "minLine": 0.25 },
"SecurityStuff": { "minLine": 0.75 }, // Your own names!
"LegacyCode": { "minLine": 0.10 }, // Be honest about reality
"WillFixLater": { "minLine": 0.0 }
}
}
Start Where YOU Are:
- Have 30% coverage now? Start with 35% threshold
- Have 60% coverage? Maybe aim for 65-70%
- Have 5% coverage? Start at 10% and celebrate progress!
The goal is IMPROVEMENT, not perfection! đ
The built-in templates (Basic, Strict, Relaxed) are just suggestions to get you started. Feel free to customize them to match your team's current reality and goals.
đ Adoption Path (Recommended)
Don't try to tag everything at once! CoverBouncer defaults to no coverage enforcement so you can adopt gradually.
Step 1: Install and Initialize
dotnet add MyApp.Tests package CoverBouncer.MSBuild
dotnet coverbouncer init
Your build will pass immediately - untagged files default to NoCoverage (0%).
Step 2: Tag ONE Critical File
Pick your most important file (payments, auth, etc.) and tag it:
// [CoverageProfile("Critical")]
public class PaymentProcessor { }
Step 3: Customize Profiles (Optional)
Adjust thresholds to match your codebase:
{
"defaultProfile": "NoCoverage",
"profiles": {
"Critical": { "minLine": 0.90 }, // Payments, Auth, Security
"Standard": { "minLine": 0.60 }, // Code you want tested
"NoCoverage": { "minLine": 0.0 } // Default - no enforcement
}
}
Step 4: Expand Gradually
Once Critical is stable, expand to more areas:
# Week 2: Tag your core business logic
dotnet coverbouncer tag --path "./Core" --profile Standard
# Week 3: Tag standard application code
dotnet coverbouncer tag --pattern "**/*Service.cs" --profile Standard
# Week 4: Tag DTOs to exclude from coverage requirements
dotnet coverbouncer tag --pattern "**/*Dto.cs" --profile Dto
Pro tip: Use --dry-run to preview changes before applying them!
Quick Start
1. Install
# Install CoverBouncer
dotnet add MyApp.Tests package CoverBouncer.MSBuild
# Install Coverlet for coverage collection
dotnet add MyApp.Tests package coverlet.msbuild
2. Initialize
dotnet coverbouncer init
3. Configure Coverage (one-time)
Add to Directory.Build.props:
<PropertyGroup>
<CollectCoverage>true</CollectCoverage>
<CoverletOutput>$(MSBuildProjectDirectory)/TestResults/coverage.json</CoverletOutput>
<CoverletOutputFormat>json</CoverletOutputFormat>
<EnableCoverBouncer>true</EnableCoverBouncer>
</PropertyGroup>
4. Tag Your Files (Optional!)
Note: Untagged files automatically use your
defaultProfile. You can start with zero tags and add them later for files needing different thresholds.
You can tag files manually or use the CLI tagging features:
Manual Tagging
Add a comment with the profile attribute:
// [CoverageProfile("Critical")]
namespace MyApp.PaymentProcessing
{
public class PaymentService { }
}
Automated Tagging
Interactive Mode (Recommended for beginners):
dotnet coverbouncer tag --interactive
Batch Mode - Tag by pattern:
# Tag all service files with "Standard" profile
dotnet coverbouncer tag --pattern "**/*Service.cs" --profile Standard
# Tag entire folder with "Critical" profile
dotnet coverbouncer tag --path "./Security" --profile Critical
# Tag files from a list
dotnet coverbouncer tag --files services.txt --profile Standard
Smart Detection - Auto-suggest profiles:
# Automatically suggest profiles based on file patterns
dotnet coverbouncer tag --auto-suggest
# Preview changes without modifying files
dotnet coverbouncer tag --pattern "**/*.cs" --profile Standard --dry-run
The CLI automatically detects patterns like:
*Controller.csâ Integration*Service.csâ BusinessLogicSecurity/*â CriticalModels/*â Dto
5. Run Tests
dotnet test
Coverage policy automatically enforced! â
Features
- đ¯ Profile-Based Coverage - Different thresholds for different code types
- đ¤ Smart Tagging - Interactive, batch, and auto-suggest modes for tagging files
- đ Drop-In Integration - Works with your existing
dotnet testworkflow - đ Filtered Run Support -
dotnet test --filterworks without false failures - đĢ CI/CD Ready - Blocks merges when coverage drops below thresholds
- đĻ NuGet Packaged - Easy to install and distribute
- đˇī¸ File-Level Tags - Simple attribute-based profile assignment
- âī¸ Single Config File - No configuration sprawl
- đ§ Auto-Configuration - Automatically excludes CoverBouncer from coverage
- đ¨ Fully Customizable - Use any profile names and thresholds you want
đ Filtered Test Runs (--filter)
Running dotnet test --filter "Category=Unit" or any --filter expression? CoverBouncer handles it automatically.
The Problem
When you use --filter, Coverlet still instruments the entire assembly. Files not targeted by the filtered tests appear with 0% coverage, even though no tests were supposed to run against them. Without awareness, CoverBouncer would report false failures for every untargeted file.
How CoverBouncer Solves It
CoverBouncer automatically detects filtered test runs via the $(VSTestTestCaseFilter) MSBuild property. When a filter is active, files with zero covered lines are skipped â they were instrumented but not targeted.
No configuration needed â it just works.
Example: Same Coverage Data, Different Modes
Filtered run (dotnet test --filter "Category=OrderTests"):
âšī¸ Filtered test run mode: files with zero coverage will be skipped
Coverage Summary by Profile
âââââââââââââââââââââââââââââââââââââââââ
â
BusinessLogic: 1 passed, 0 failed (80% required)
â
Critical: 1 passed, 0 failed (100% required)
âī¸ 4 file(s) skipped (no coverage data in filtered test run)
âââââââââââââââââââââââââââââââââââââââââ
â
All 2 files passed coverage requirements
Full run (dotnet test, same data):
Coverage Summary by Profile
âââââââââââââââââââââââââââââââââââââââââ
â BusinessLogic: 1 passed, 1 failed (80% required)
â Critical: 1 passed, 1 failed (100% required)
â
Dto: 1 passed, 0 failed (exempt)
â Standard (default): 0 passed, 1 failed (60% required)
âââââââââââââââââââââââââââââââââââââââââ
â 3 coverage violation(s) found
â ī¸ Best Practice: Use Full Runs as Your CI Gate
Filtered runs are great for fast local feedback â validate just the files you're working on. But only a full run validates coverage across your entire codebase.
Recommended CI setup:
jobs:
quick-check:
# Fast feedback on PRs â only validates targeted files
run: dotnet test --filter "Category=Unit"
coverage-gate:
# Final gate â validates ALL coverage thresholds
run: dotnet test
How It Works Under the Hood
| Situation | CoveredLines | Filtered Run | Full Run |
|---|---|---|---|
| File targeted by tests, meets threshold | > 0 | â Pass | â Pass |
| File targeted by tests, below threshold | > 0 | â Fail | â Fail |
| File NOT targeted (not in filter) | 0 | âī¸ Skip | â Fail |
| File with Dto profile (0% allowed) | 0 | âī¸ Skip | â Pass |
Key insight: On a filtered run, there's no way to distinguish "file not in the filter" from "file genuinely has no tests." That's why the full run is essential as your final gate â it catches files that truly need tests.
CLI Usage
For CLI usage (outside MSBuild), pass the --filtered flag:
coverbouncer verify --coverage coverage.json --config coverbouncer.json --filtered
Coverlet Integration
CoverBouncer works seamlessly with Coverlet, the popular .NET code coverage library.
Automatic Exclusions
When you add CoverBouncer.MSBuild as a NuGet package, it automatically excludes all CoverBouncer assemblies from Coverlet instrumentation via buildTransitive targets. This prevents warnings about missing debug symbols and improves performance.
What's excluded automatically:
[CoverBouncer.Core]*[CoverBouncer.Coverlet]*[CoverBouncer.MSBuild]*
No manual configuration needed! đ
Optional: Exclude Test Frameworks
During dotnet coverbouncer init, you'll be prompted to exclude common test frameworks and mocking libraries for better performance. This is optional but recommended:
<PropertyGroup>
<Exclude>$(Exclude);[xunit.*]*;[FluentAssertions]*;[Moq]*;[NSubstitute]*</Exclude>
</PropertyGroup>
Why Exclude These?
- Performance: Faster test runs by skipping unnecessary instrumentation
- Noise Reduction: Focus coverage reports on your actual code
- No Warnings: Prevents "missing symbols" warnings for NuGet packages
Manual Configuration
If you need more control over Coverlet exclusions:
<PropertyGroup>
<Include>[MyApp]*</Include>
<Exclude>$(Exclude);[MyApp.Tests]*;[ThirdParty.*]*</Exclude>
</PropertyGroup>
See Coverlet documentation for more options.
How It Works
- Tag files with coverage profiles using file-level attributes
- Set thresholds in
coverbouncer.json - Run tests - Cover-Bouncer validates coverage automatically
- Build fails if any file violates its profile's threshold
Project Structure
CoverBouncer.Core- Core coverage policy engineCoverBouncer.Coverlet- Coverlet adapter for coverage dataCoverBouncer.MSBuild- MSBuild integration (main user package)CoverBouncer.Analyzers- Roslyn analyzers (coming soon)
Example Configuration
{
"coverageReportPath": "TestResults/coverage.json",
"defaultProfile": "Standard",
"profiles": {
"Critical": {
"minLine": 0.90
},
"Standard": {
"minLine": 0.60
},
"Integration": {
"minLine": 0.40
},
"Dto": {
"minLine": 0.00
}
}
}
Note: Values are decimals (0.0-1.0), not percentages. So 0.90 = 90% line coverage.
Installation & Usage
MSBuild Task (Recommended)
Automatically validates coverage after dotnet test:
dotnet add package CoverBouncer.MSBuild
Add to your test project's .csproj:
<PropertyGroup>
<EnableCoverBouncer>true</EnableCoverBouncer>
</PropertyGroup>
See MSBuild Configuration for all available properties.
CLI Tool
For manual validation or CI/CD scripts:
dotnet tool install -g CoverBouncer.CLI
coverbouncer verify --coverage coverage.json --config coverbouncer.json
Validation Tests
This project includes comprehensive validation tests:
- â All files pass thresholds
- â Mixed pass/fail scenarios
- â Critical violations
- â Untagged file handling
- â Multiple profile scenarios
- â Edge cases (exact thresholds, zero coverage)
- â Real-world project simulation
- â Filtered test run (untargeted files skipped)
- â Full run with same data (contrast â same data fails without filter awareness)
Run validation tests: dotnet test tests/CoverBouncer.ValidationTests
Building from Source
# Build all projects
./build.sh build
# Run all tests
./build.sh test
# Create NuGet packages
./build.sh pack
# Install CLI tool locally
./build.sh install-cli
Documentation
- Getting Started Guide - Complete setup walkthrough
- File Tagging Guide - Learn all the ways to tag files (manual & automated)
- Configuration Reference - Detailed
coverbouncer.jsonoptions - MSBuild Configuration - MSBuild properties & customization
- Coverlet Integration - Best practices for Coverlet setup
Contributing
We welcome contributions! See CONTRIBUTING.md for details.
License
MIT License - see LICENSE for details.
Built with â¤ī¸ for the .NET community
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-preview.10 | 41 | 3/19/2026 |
| 1.0.0-preview.9 | 66 | 3/5/2026 |
| 1.0.0-preview.8 | 46 | 2/25/2026 |
| 1.0.0-preview.7 | 59 | 1/1/2026 |
| 1.0.0-preview.6 | 57 | 12/31/2025 |
| 1.0.0-preview.5 | 60 | 12/31/2025 |
| 1.0.0-preview.4 | 56 | 12/31/2025 |
| 1.0.0-preview.3 | 180 | 12/15/2025 |
| 1.0.0-preview.2 | 121 | 12/14/2025 |
| 1.0.0-preview.1 | 114 | 12/13/2025 |
ANSI colorized output for terminal clarity. Compact violation format (actual/required). Relative file paths in error output. Package icon added.