Created
February 16, 2019 19:22
-
-
Save rszuban/b6853b61e8b319e95577258e846aebce to your computer and use it in GitHub Desktop.
Script generating a code coverage report with dotCover and later converting it with Report Generator so that Azure DevOps task Publish Code Coverage Results can use it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Basic configuration variables | |
# Comment out or remove $dotnetExecutable or $vsTestExecutable depending on needs. | |
# Adjust paths so that they lead to executables on a build server. | |
$dotCoverExecutable = 'C:\Program Files\DotCover\dotCover.exe' | |
$dotnetExecutable = 'C:\Program Files\dotnet\dotnet.exe' | |
$vsTestExecutable = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\IDE\Extensions\TestPlatform\vstest.console.exe' | |
$reportGeneratorExecutable = 'C:\Windows\ServiceProfiles\NetworkService\.dotnet\tools\reportgenerator.exe' | |
# This pattern will be used to identify test projects. Use array if necessary. | |
$testProjectPattern = '*Tests.csproj' | |
# For more info on dotCover assembly filter visit: | |
# https://www.jetbrains.com/help/dotcover/Running_Coverage_Analysis_from_the_Command_LIne.html#filters. | |
$dotCoverAssemblyFilter = '+:Module=MyApplication*;' | |
#endregion | |
#region Checks if paths to executables are correct | |
# If you commented or removed any executable paths do the same for apropriate check. | |
if (-not (Test-Path -Path $dotcoverExecutable)) { | |
Throw "Path to DotCover executable is not correct." | |
} | |
if (-not (Test-Path -Path $dotnetExecutable)) { | |
Throw "Path to dotnet executable is not correct." | |
} | |
if (-not (Test-Path -Path $vsTestExecutable)) { | |
Throw "Path to vsTest executable is not correct." | |
} | |
if (-not (Test-Path -Path $reportGeneratorExecutable)) { | |
Throw "Path to Report Generator executable is not correct." | |
} | |
#endregion | |
# If necessary use -Exclude parameter to get full benefits of Get-ChildItem | |
$testProjectsArguments = @{ | |
Path = "$(System.DefaultWorkingDirectory)" | |
Include = $testProjectPattern | |
} | |
$testProjects = Get-ChildItem @testProjectsArguments -Recurse -File | |
if ($testProjects.count -eq 0) { | |
throw "No files matched the $testProjectPattern pattern. The script cannot continue." | |
} | |
#region Directory structure creation | |
<# | |
The script will create the following directory structure. | |
$(System.DefaultWorkingDirectory) | |
└──coverage-report/ | |
├── cobertura/ | |
└── html/ | |
#> | |
$reportDirectory = Join-Path -Path "$(System.DefaultWorkingDirectory)" -ChildPath "coverage-report" | |
if (Test-Path -Path $reportDirectory) { | |
Remove-Item -Path ( Join-Path -Path $reportDirectory -ChildPath "*" ) -Recurse | |
} | |
else { | |
New-Item -Path $reportDirectory -ItemType Directory | |
} | |
$reportDirectoryCobertura = Join-Path -Path $reportDirectory -ChildPath "cobertura" | |
New-Item -Path $reportDirectoryCobertura -ItemType Directory | |
$reportDirectoryHtml = Join-Path -Path $reportDirectory -ChildPath "html" | |
New-Item -Path $reportDirectoryHtml -ItemType Directory | |
#endregion | |
#region Test coverage with DotCover | |
foreach ($testProject in $testProjects) { | |
$reportOutputPathArguments = @{ | |
Path = $reportDirectory | |
ChildPath = "$( $testProject.BaseName )_coverage.xml" | |
} | |
$reportOutputPath = Join-Path @reportOutputPathArguments | |
# Again depending on needs remove or comment out unnecessary region below | |
#region Arguments and dotCover execution for dotnet | |
# CoreInstructionSet is handy when launching dotCover as a service account. | |
# Set its value to either x86 or x64 depending on project bitness | |
$dotCoverDotnetArguments = @( | |
"cover", | |
"/TargetExecutable=$dotnetExecutable", | |
"/TargetArguments=test $( $testProject.FullName ) --configuration=$(BuildConfiguration)", | |
"/Output=$reportOutputPath", | |
"/ReportType=DetailedXML", | |
"/Filters=$dotCoverAssemblyFilter" | |
"/CoreInstructionSet=x64" | |
) | |
Write-Output "Executing DotCover with following arguments: $dotCoverDotnetArguments." | |
& "$dotCoverExecutable" @dotCoverDotnetArguments | |
#endregion | |
#region Arguments and dotCover execution with vsTest | |
# In case of VsTest the test projects needs to be built before execution of this scrip. | |
# The dll file containing tests assemblies needs to be found. | |
$testProjectDllArguments = @{ | |
Path = Join-Path -Path "$( $testProject.DirectoryName )" -ChildPath "\bin\$(BuildConfiguration)" | |
Include = "$( $testProject.BaseName ).dll" | |
} | |
$testProjectDll = Get-ChildItem @testProjectDllArguments -Recurse -File | |
if ($testProjectDll.Count -ne 1) { | |
Throw "Make sure that tests projects are built before running this script." | |
} | |
# CoreInstructionSet is handy when launching dotCover as a service account. | |
# Set its value to either x86 or x64 depending on project bitness | |
$dotCoverVsTestArguments = @( | |
"cover", | |
"/TargetExecutable=$vsTestExecutable", | |
"/TargetArguments=$( $testProjectDll.FullName )", | |
"/Output=$reportOutputPath", | |
"/ReportType=DetailedXML", | |
"/Filters=$dotCoverAssemblyFilter", | |
"/CoreInstructionSet=x64" | |
) | |
Write-Output "Executing DotCover with following arguments: $dotCoverVsTestArguments." | |
& "$dotCoverExecutable" @dotCoverVsTestArguments | |
#endregion | |
if ( -not $? ) { | |
Throw "At least one unit test haven't passed. The script cannot continue." | |
} | |
} | |
#endregion | |
# region Generating reports in html and Cobertura format | |
$coverageReports = Get-ChildItem -Path $reportDirectory -Include '*_coverage.xml' -File -Recurse | |
if ($coverageReports.Count -eq 0) { | |
Throw "No coverage reports were generated. The script cannot continue." | |
} | |
$reportsFilePaths = $coverageReports.FullName -join ';' | |
$reportGeneratorCoberturaParams = @( | |
"-reports: $reportsFilePaths", | |
"-targetdir:$reportDirectoryCobertura", | |
"-reporttypes:Cobertura" | |
) | |
Write-Output "Executing Report Generator with following parameters: $reportGeneratorCoberturaParams." | |
& "$reportGeneratorExecutable" @reportGeneratorCoberturaParams | |
$reportGeneratorHtmlParams = @( | |
"-reports:$reportsFilePaths", | |
"-targetdir:$reportDirectoryHtml", | |
"-reporttypes:HtmlInline_AzurePipelines" | |
) | |
Write-Output "Executing Report Generator with following parameters: $reportGeneratorHtmlParams." | |
& "$reportGeneratorExecutable" @reportGeneratorHtmlParams |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment