None of the above-mentioned answers can help you with failing a build in CI, when the overall coverage of the solution falls below a certain threshold. All you get is a JSON, XML or HTML report which you need to parse with an additional script and that's too much work.
Instead, this is what I did.
First, run dotnet test and tell coverlet to merge all your coverage results. (You need to reference coverlet.msbuild in your test projects)
dotnet test your_solution.sln /p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json
If you add your threshold switches (/p:Threshold, etc) to the same command, it will try to apply it for each project individually, but that's not what we want.
So to go around that limitation, what we can do is to run the above command one more time to merge the existing result with one of the test projects you have. Merging the total with a subsection is not going to change your total.
dotnet test one_of_your_test_projects.csproj /p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json /p:ThresholdType=branch /p:Threshold=80 /p:ThresholdStat=total
Now, that command fails only when your solution's coverage falls below your threshold. Here are some YAML tasks for AzureDevOps which I use. It should be somewhat similar for any other too.
- task: DotNetCoreCLI@2
displayName: 'Calculate code coverage'
continueOnError: false
inputs:
command: test
projects: '**/*.Test.csproj'
arguments: '/p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json /m:1'
publishTestResults: false
- task: DotNetCoreCLI@2
displayName: 'Checkpoint: Total branch coverage >= $(codeCoverageBranchThreshold)'
continueOnError: false
inputs:
command: test
projects: './one_of_your_test_projects_dir/one_of_your_test_projects.csproj'
arguments: '/p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json /p:ThresholdType=branch /p:Threshold=$(codeCoverageBranchThreshold) /p:ThresholdStat=total'
publishTestResults: false