Skip to content

Commit

Permalink
Add Code coverage report (#79)
Browse files Browse the repository at this point in the history
Add code coverage report to pipeline. Fixes #42.

Design is basically:

1. Capture code coverage files in `test.runsettings` to avoid embedding
settings / logic in the pipeline YAML and make it possible to generate
coverage locally the same as CI
- Currently uses a simple assembly include limited to
`Moq.Analyzers.dll`. Ideally we could say "all project references".
Added a TODO for that, as well as to discuss with the code coverage team
3. Add `CleanCoverageReport` and `GenerateCoverageReport` targets in
test MSBuild slice to handle merging the reports across test projects
4. Use the MSBuild task for `dotnet-reportgenerator` to merge code
coverage reports into:
    - A markdown summary for GitHub
    - An HTML report with line-coverage info
    - A merged Cobertura XML report for tool processing
5. Update GitHub Actions YAML so that:
    - Markdown summary is added to the summary of the run
    - Other coverage reports are added as a build artifact

I didn't add any functionality to fail below a certain threshold, as
tools generally use a static threshold, or do odd things to smuggle
state like creating a branch in the repo or storing information in a
gist, so leaving that for later.
  • Loading branch information
MattKotsenas authored Jun 11, 2024
1 parent 5a8cad8 commit 5212cbe
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 8 deletions.
27 changes: 19 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,34 @@ jobs:
run: dotnet build --no-restore --configuration Release /bl:./artifacts/logs/release/build.release.binlog

- name: Test
run: dotnet test --no-build --configuration Release
run: dotnet test --no-build --configuration Release --settings ./build/targets/tests/test.runsettings

- name: Publish Test Report
- name: Upload *.received.* files
uses: actions/upload-artifact@v4
if: failure()
with:
name: verify-test-results
path: |
**/*.received.*
- name: Upload Test Report
uses: actions/upload-artifact@v4
if: success() || failure()
with:
name: .NET Test Reports (${{ matrix.os }})
path: "artifacts/TestResults/**/*.trx"
if-no-files-found: error

- name: Upload Test Results
uses: actions/upload-artifact@v2
if: failure()
- name: Upload Code Coverage Report
uses: actions/upload-artifact@v4
if: success() || failure()
with:
name: verify-test-results
path: |
**/*.received.*
name: .NET Code Coverage Reports (${{ matrix.os }})
path: "artifacts/TestResults/coverage/**"

- name: Publish coverage summary
run: cat artifacts/TestResults/coverage/SummaryGithub.md >> $GITHUB_STEP_SUMMARY
shell: bash

- name: Upload binlogs
uses: actions/upload-artifact@v4
Expand Down
1 change: 1 addition & 0 deletions build/targets/tests/Packages.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<ItemGroup>
<PackageVersion Include="ReportGenerator" Version="5.3.6" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing" Version="1.1.2-beta1.24273.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" Version="1.1.2-beta1.24273.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
Expand Down
1 change: 1 addition & 0 deletions build/targets/tests/Tests.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<ItemGroup Condition=" '$(IsTestProject)' == 'true' ">
<PackageReference Include="ReportGenerator" />
<PackageReference Include="Meziantou.Xunit.ParallelTestFramework" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
Expand Down
23 changes: 23 additions & 0 deletions build/targets/tests/Tests.targets
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,28 @@
<!-- Enable test logging to TRX files and place them in the artifacts directory -->
<VSTestLogger>trx%3bLogFileName=$(MSBuildProjectName).trx</VSTestLogger>
<VSTestResultsDirectory Condition="'$(VSTestResultsDirectory)' == ''">$(ArtifactsTestResultsPath)/$(TargetFramework)</VSTestResultsDirectory>

<_TestCoverageGlob>$(ArtifactsTestResultsPath)/**/*.cobertura.xml</_TestCoverageGlob>
<_TestCoverageReportDirectory>$(ArtifactsTestResultsPath)/coverage</_TestCoverageReportDirectory>
</PropertyGroup>

<Target Name="CleanCoverageReport" BeforeTargets="Test;VSTest" Condition=" '$(IsTestProject)' == 'true' ">
<!-- Prevent this previous runs' coverage files from being merged into this report run. -->
<RemoveDir Directories="$(_TestCoverageReportDirectory)" />

<ItemGroup>
<_CoverageFiles Include="$(_TestCoverageGlob)" />
</ItemGroup>
<Delete Files="@(_CoverageFiles)" />
<ItemGroup>
<_CoverageFiles Remove="@(_CoverageFiles)" />
</ItemGroup>
</Target>

<Target Name="GenerateCoverageReport" AfterTargets="Test;VSTest" Condition=" '$(IsTestProject)' == 'true' ">
<ItemGroup>
<_CoverageFiles Include="$(_TestCoverageGlob)" />
</ItemGroup>
<ReportGenerator ProjectDirectory="$(MSBuildProjectDirectory)" ReportFiles="@(_CoverageFiles)" TargetDirectory="$(_TestCoverageReportDirectory)" ReportTypes="MarkdownSummaryGithub;Cobertura;HtmlInline" />
</Target>
</Project>
28 changes: 28 additions & 0 deletions build/targets/tests/test.runsettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- File name extension must be .runsettings -->
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<Format>cobertura</Format>
<IncludeTestAssembly>False</IncludeTestAssembly>
<CodeCoverage>
<EnableStaticNativeInstrumentation>False</EnableStaticNativeInstrumentation>
<EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation>
<ModulePaths>
<Include>
<!--
Limit code coverage to the shipping binary.
TODO: Consider using a "Just my code"-esque tool to automatically include all project references.
Discuss in https://github.com/microsoft/codecoverage.
-->
<ModulePath>.*Moq\.Analyzers\.dll$</ModulePath>
</Include>
</ModulePaths>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>

0 comments on commit 5212cbe

Please sign in to comment.