Skip to content

Collect and report coverage for UnitsNet.Modular - #1726

Open
Rafael-SOWNet wants to merge 1 commit into
angularsen:masterfrom
Rafael-SOWNet:ci/modular-coverage
Open

Collect and report coverage for UnitsNet.Modular#1726
Rafael-SOWNet wants to merge 1 commit into
angularsen:masterfrom
Rafael-SOWNet:ci/modular-coverage

Conversation

@Rafael-SOWNet

@Rafael-SOWNet Rafael-SOWNet commented Aug 6, 2026

Copy link
Copy Markdown

Motivation

Nothing in the repository measures UnitsNet.Modular's coverage. Build/test-projects.psm1
lists seven test projects and none of the three Modular ones are among them, and this workflow
ran plain dotnet test. codecov.yml sets the target range to 80–100, but that target has only
ever seen the legacy projects.

The Modular projects cannot simply be added to test-projects.psm1, for two reasons.

Start-Tests runs dotnet test --no-build against projects that build.ps1 has already built
from UnitsNet.slnx, whereas Modular is a separate solution needing -p:Platform=ProjectReferences.

More to the point, #1693 introduced that list specifically so the net48 compatibility
workflow
could share it without importing the full build-functions module. So it means "the
main test projects that also run on .NET Framework". The Modular test projects target net10.0
only, so adding them there would pull them into a net48 run where they cannot build.

Collecting here, where the solution is already built correctly and the platform is already set,
avoids both.

Changes

  • restore the local tools, so the dotCover the repository already depends on is available
  • wrap the existing test run in dotCover cover-dotnet, writing DetailedXML to Artifacts/Coverage
  • upload with the same codecov/codecov-action@v6 step and options pr.yml uses
  • grant id-token: write

Two of those deserve a reason.

id-token. pr.yml declares no permissions block and inherits the repository default.
This workflow declares contents: read explicitly, which sets everything else to none, so
Codecov's use_oidc: true would have no token to request.

The filter is narrower than the legacy one. Start-Tests uses
+:module=UnitsNet*;-:module=*Tests. Applied here that reports assemblies this workflow does
not own, because the compatibility suite compiles the current UnitsNet project and generates a
large fixture:

filter reported
+:module=UnitsNet*;-:module=*Tests 31% — legacy UnitsNet at 24% (35 557 statements) and UnitsNet.Modular.Compatibility.GeneratedFixture, a generated test fixture, at 37% (19 435 statements)
this PR's filter 90%UnitsNet.Modular 81%, UnitsNet.Modular.Generator 93%

Legacy UnitsNet is already measured by pr.yml, so including it here would double-count it
against a number this workflow cannot move.

Result

Modular's coverage turns out to be healthy — 2 498 / 2 764 statements, inside the repository's
80–100 target. This PR does not improve coverage; it makes an existing good number visible and
guards it against regressing unnoticed. The thinnest areas, for anyone interested later, are
UnitDescriptor at 21%, BaseDimensions at 31% and LogarithmicQuantityMath at 55%.

What this does not do

No test is added or changed, and no product code is touched. The AOT smoke test, the NuGet
consumer checks and packing are untouched and still run in the same order.

Validation

I cannot run this workflow against upstream, so I ran it on my fork, from this branch, with the
workflow file as it stands in this PR:

https://github.com/Rafael-SOWNet/UnitsNet/actions/runs/31126042733all steps green,
including the two new ones.

Passed! - Failed: 0, Passed: 40, Skipped: 0, Total: 40   UnitsNet.Modular.Tests
Passed! - Failed: 0, Passed: 43, Skipped: 0, Total: 43   UnitsNet.Modular.Compatibility.Tests
Passed! - Failed: 0, Passed: 33, Skipped: 0, Total: 33   UnitsNet.Modular.Generator.Tests

Found 1 coverage files to report
 > Artifacts/Coverage/UnitsNet.Modular.coverage.xml
Sending upload (186600 bytes) to storage
Upload queued for processing complete

So the upload path works, not just the collection. It landed in my fork's Codecov project
rather than yours, which is the one part of this that can only be confirmed once it runs here.

The Modular test projects are absent from Build/test-projects.psm1, and this
workflow ran plain dotnet test, so nothing in the repository measured Modular
coverage. codecov.yml targets the 80-100 range, but that target only ever saw
the legacy projects.

Wraps the existing test run in the dotCover tool the repository already
depends on, and uploads the report the same way pr.yml does.

The filter is narrower than the legacy '+:module=UnitsNet*;-:module=*Tests'.
The compatibility suite compiles the current UnitsNet project and generates a
large fixture assembly, so the broad filter reports legacy UnitsNet at 24% and
a 19k-statement generated test fixture at 37%, dragging the headline to 31%
and measuring things this workflow does not own. Restricting it to the two
product assemblies reports what Modular is actually responsible for.

id-token is granted because this workflow, unlike pr.yml, declares its
permissions explicitly, so Codecov's use_oidc would otherwise have no token.
@Rafael-SOWNet

Copy link
Copy Markdown
Author

CI evidence, since this PR shows no checks (first-time-contributor gate).

Full run of this workflow on my fork, dispatched against this PR's branch itself — no
ci-check branch and no extra commit, because unitsnet-modular-ci.yml already carries a
workflow_dispatch trigger. The tree is 3069f64a3560f207cf030f667980ca523e96b8a7, byte-identical
to this PR's head:

https://github.com/Rafael-SOWNet/UnitsNet/actions/runs/31479702848success. Every step green
except Verify tagged package versions, which is skipped by design on a non-tag ref.

Passed! - Failed: 0, Passed: 40, Skipped: 0, Total: 40   UnitsNet.Modular.Tests
Passed! - Failed: 0, Passed: 33, Skipped: 0, Total: 33   UnitsNet.Modular.Generator.Tests
Passed! - Failed: 0, Passed: 43, Skipped: 0, Total: 43   UnitsNet.Modular.Compatibility.Tests

The two things this PR actually claims are both exercised end to end, rather than argued:

1. dotCover produces the report. The Test with coverage step ran the same test command
wrapped in the tool already in .config/dotnet-tools.json, and wrote the file:

JetBrains dotCover Console Runner 2025.1.8
[JetBrains dotCover] Coverage session started  [08/11/2026 09:54:16]
[JetBrains dotCover] Coverage session finished [08/11/2026 09:54:43]
[JetBrains dotCover] Report generation finished (count = 1)

2. id-token: write is what makes the upload possible. This is the part I could not
demonstrate without a real run, since it is a permissions question rather than a code one. This
workflow declares its permissions: block explicitly, so use_oidc: true has no token unless
id-token is named there. With it named, the upload completes:

info -- ci service found: github-actions
info -- Found 1 coverage files to report
info -- > Artifacts/Coverage/UnitsNet.Modular.coverage.xml
info -- Your upload is now queued for processing.
info -- Upload queued for processing complete

Codecov then reports, for the two product assemblies the filter selects:

coverage 91.21%
lines 2549
hits 2325
misses 224
files 36

That is the number the narrow filter was chosen to produce. The contrast figure in the commit
message — 31% under the legacy +:module=UnitsNet*;-:module=*Tests filter — was measured locally
rather than on this run; the compatibility suite compiles the current UnitsNet project and
generates a ~19k-statement fixture assembly, neither of which this workflow owns.

Nothing else in the workflow moved: the Native AOT smoke test, all three sample consumers
(GettingStartedSample, CustomQuantitySample, the published-package run) and Pack are green on
the same run, so the added steps do not disturb the existing ones.

One caveat stated plainly: the Codecov upload is verified, but the resulting report lands on my
fork's Codecov project, not this repository's. Whether the number lands inside the 80–100 target in
codecov.yml can only be seen once the workflow runs here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants