Skip to content

Instantly share code, notes, and snippets.

@Wind010
Created March 22, 2025 00:30
Show Gist options
  • Save Wind010/34ff123942c00de4ef285372321f6452 to your computer and use it in GitHub Desktop.
Save Wind010/34ff123942c00de4ef285372321f6452 to your computer and use it in GitHub Desktop.
Some functions to help with Coverlet code coverage execution from CLI.
# Common useful commands
# Must be sourced first.
# . .\CcHelper.ps1
# Dependencies
# donet package add coverlet.msbuild
# dotnet tool install -g dotnet-reportgenerator-globaltool
# dotnet tool install --global coverlet.console
# Useful
# https://marketplace.visualstudio.com/items?itemName=FortuneNgwenya.FineCodeCoverage
$ErrorActionPreference = "Stop"
$comma = '%2C' # URL encoded comma.
$exclude = "[*]*.Program${comma}[*]*.Controllers.*${comma}[*]*.Models.*${comma}[*]*.Exceptions*"
$excludeByAttribute = "Obsolete${comma}GeneratedCodeAttribute${comma}CompilerGeneratedAttribute"
$testFilter = "Category!=E2E"
$coverageRunSettingsPath = "CodeCoverage.runsettings" # Unused in coverlet.msbuild. Relevant for coverlet.collector.
$coverletOutputFormat = "cobertura${comma}json"
#$testResultsDir=".\TestResults"
$testResultsDir="$($(Get-Location).Path)\TestResults"
$coverletJson = "$testResultsDir\CodeCoverageResults.json"
$coverageReportDir = "$testResultsDir\CoverageReport"
# Update below as needed
$lineThreshold=100
$branchThreshold=100
$methodThreshold=100
$threshold = "${lineThreshold}${comma}${branchThreshold}${comma}${methodThreshold}"
$thresholdType = "line${comma}branch${comma}method"
$thresholdStat = "total" # Minimum, Average, Total
# /p:VSTestUseMSBuildOutput=false allows percentage results to be shown to console.
# Consider /p:DeterministicSourcePaths=true `
function Invoke-CodeCoverage {
Remove-CodeCoverageOutput
$files = Get-ChildItem -Path $Path -Recurse -Filter "*sln"
#Write-Host "dotnet test $files[0] --no-build --no-restore --results-directory:$testResultsDir /p:Exclude=""$exclude"" /p:ExcludeByAttribute=""$excludeByAttribute"""
dotnet test $files[0] --filter $testFilter --results-directory:$testResultsDir --verbosity=minimal `
/p:CollectCoverage=true `
/p:CoverletOutput=$coverletJson `
/p:CoverletOutputFormat=$coverletOutputFormat `
/p:MergeWith=$coverletJson `
/p:VSTestUseMSBuildOutput=false `
/p:IncludeTestAssembly=false `
/p:Exclude="$exclude" `
/p:ExcludeByAttribute=$excludeByAttribute
}
function Invoke-CodeCoverageWithThresholdSln {
Remove-CodeCoverageOutput
$files = Get-ChildItem -Path $Path -Recurse -Filter "*sln"
dotnet test $files[0] --filter $testFilter --results-directory:$testResultsDir --verbosity=minimal `
/p:CollectCoverage=true `
/p:Threshold=$threshold `
/p:ThresholdType=$thresholdType `
/p:ThresholdStat=$thresholdStat `
/p:CoverletOutputFormat=$coverletOutputFormat `
/p:MergeWith=$coverletJson `
/p:VSTestUseMSBuildOutput=false `
/p:CoverletOutput=$coverletJson `
/p:IncludeTestAssembly=false `
/p:Exclude="$exclude" `
/p:ExcludeByAttribute=$excludeByAttribute
}
function Invoke-CodeCoverageWithThreshold {
Remove-CodeCoverageOutput
$files = Get-ChildItem -Path $Path -Recurse -Filter "*csproj"
foreach ($file in $files) {
Write-Host "Processing $file" -ForegroundColor Blue
dotnet test $file --no-build --no-restore --filter $testFilter `
--results-directory:$testResultsDir --verbosity=minimal `
/p:CollectCoverage=true `
/p:CoverletOutput=$coverletJson `
/p:MergeWith=$coverletJson `
/p:VSTestUseMSBuildOutput=false `
/p:IncludeTestAssembly=false `
/p:Exclude="$exclude" `
/p:ExcludeByAttribute=$excludeByAttribute
if ($file -eq $files[-1]) {
dotnet test $file --no-build --no-restore --filter $testFilter `
--results-directory:$testResultsDir --verbosity=minimal `
/p:CollectCoverage=true `
/p:Threshold=$threshold `
/p:ThresholdType=$thresholdType `
/p:ThresholdStat=$thresholdStat `
/p:MergeWith=$coverletJson `
/p:VSTestUseMSBuildOutput=false `
/p:CoverletOutput=$coverletJson `
/p:IncludeTestAssembly=false `
/p:Exclude="$exclude" `
/p:ExcludeByAttribute=$excludeByAttribute
}
}
}
function New-CodeCoverageReport {
Invoke-CodeCoverage
reportgenerator -reports:"..\**\coverage.cobertura.xml" -targetdir:"$coverageReportDir" -reporttypes:Html
}
function Remove-CodeCoverageOutput {
$ErrorActionPreference = "Continue"
Get-ChildItem -Include TestResults,TestCoverage,coverage.json,CoverageOutput.json,coverage.cobertura.xml,CoverageResults.json -Recurse -force `
| Remove-Item -Force -Recurse
$ErrorActionPreference = "Stop"
}
function Remove-BinAndObjDirectories {
Get-ChildItem -include bin,obj -recurse | remove-item -force -recurse
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment