Migrate Test Project to Native Microsoft.Testing.Platform - #448
Conversation
The .NET 10 SDK dropped the VSTest bridge that dotnet test relied on, so dotnet test failed outright: 'Testing with VSTest target is no longer supported by Microsoft.Testing.Platform on .NET 10 SDK and later.' Opt UtilitiesTests into native MTP (global.json test.runner, the UseMicrosoftTestingPlatformRunner project property) and swap coverlet.collector, a VSTest-only collector, for the native Microsoft.Testing.Extensions.CodeCoverage provider. Bump Microsoft.NET.Test.Sdk and the xunit.v3 family to the versions that ship a compatible Microsoft.Testing.Platform runtime; the prior xunit.v3 3.2.2 pairing threw a TypeLoadException against the newer platform assembly. Update the validate workflow's dotnet test invocation to match (--coverage instead of --collect), naming the output file explicitly: the extension's default GUID basename is not matched by codecov-action's file finder, so the upload step would otherwise silently find nothing under fail_ci_if_error: false. Also fixes three ExtensionsTests.cs null-argument tests that were missing the null-forgiving operator its sibling test already used; TreatWarningsAsErrors never reached these under the old VSTest error, which aborted the build before compiling the test project.
This repo's .editorconfig pins CRLF for *.json/*.jsonc; the file was written LF, which editorconfig-checker in the Lint job caught.
Matches the PrivateAssets treatment already used for coverlet.collector and xunit.analyzers, per Copilot review on PR #447. IncludeAssets keeps 'compile', unlike coverlet.collector: the MTP self-registration code generated for the test project references this extension's types directly, so excluding compile assets breaks the build.
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review. 📝 WalkthroughWalkthroughThe test suite now runs through Microsoft Testing Platform. Coverage uses ChangesMicrosoft Testing Platform migration
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk:⚪ Minimal · up to This PR updates the test project and validation workflow for native Microsoft.Testing.Platform coverage and corrects three test arguments. No actionable merge-blocking risk remains beyond normal checks and review. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. (5 skipped: 5 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@## main #448 +/- ##
==========================================
+ Coverage 66.89% 67.24% +0.34%
==========================================
Files 13 13 Lines 1160 1154 -6 Branches 108 106 -2 ==========================================
Hits 776 776 Misses 338 338 + Partials 46 40 -6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PR Summary by QodoMigrate UtilitiesTests to Native Microsoft.Testing.Platform
AI Description
Diagram
High-Level Assessment
Files changed (6) |
Code Review by Qodo
1. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ptr727
commented
Aug 29, 2026
Re Qodo's two "narrow-wrapped comments" findings (UtilitiesTests/UtilitiesTests.csproj:5-6, 19-22; .github/workflows/validate-task.yml:30): declining. This repo's comment convention (fleet |
There was a problem hiding this comment.
🟡 Changes recommended
The workflow writes --coverage-output to the repo root while Codecov is configured to only scan ./coverage, which can cause coverage uploads to be skipped.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR migrates the UtilitiesTests project and CI test execution to native Microsoft.Testing.Platform so dotnet test continues to work under the .NET 10 SDK (which removed the VSTest bridge).
Changes:
- Opt
UtilitiesTestsinto native MTP (global.jsontest.runner, plusOutputType=ExeandUseMicrosoftTestingPlatformRunner=true). - Replace VSTest-only
coverlet.collectorwithMicrosoft.Testing.Extensions.CodeCoverageand update the validate workflow to usedotnet test --coverage. - Update test/tooling package versions and fix nullable warnings in null-argument tests.
File summaries
| File | Description |
|---|---|
| UtilitiesTests/UtilitiesTests.csproj | Switch test project to MTP runner and adopt MTP-native coverage extension. |
| UtilitiesTests/ExtensionsTests.cs | Add null-forgiving operator in null-argument tests to satisfy nullable analysis. |
| Utilities.slnx | Add global.json to Solution Items. |
| global.json | Configure dotnet test to use Microsoft.Testing.Platform via test.runner. |
| Directory.Packages.props | Remove coverlet version and bump/add MTP-compatible test/coverage package versions. |
| .github/workflows/validate-task.yml | Update CI test invocation to MTP --coverage flow and configure coverage output naming. |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Updated [ptr727.Utilities](https://github.com/ptr727/Utilities) from 4.0.28 to 4.0.38. <details> <summary>Release notes</summary> _Sourced from [ptr727.Utilities's releases](https://github.com/ptr727/Utilities/releases)._ ## 4.0.38 ## What's Changed * Bump actions/checkout from 7.0.0 to 7.0.1 in the actions-deps group by @dependabot[bot] in ptr727/Utilities#432 * Bump DavidAnson/markdownlint-cli2-action from 24.1.0 to 24.2.0 in the actions-deps group by @dependabot[bot] in ptr727/Utilities#435 * Migrate Test Project to Native Microsoft.Testing.Platform by @ptr727 in ptr727/Utilities#448 * Bump AwesomeAssertions and 3 others by @dependabot[bot] in ptr727/Utilities#450 **Full Changelog**: ptr727/Utilities@4.0.28...4.0.38 Commits viewable in [compare view](ptr727/Utilities@4.0.28...4.0.38). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Promotes the hub resync (#451) to `main`. ## Why this is a `promote/` branch rather than `develop` itself `main` carried its own copies of work `develop` had done independently: the Microsoft.Testing.Platform migration (#448 against #447) and an AwesomeAssertions bump (#450 against #449). Combined with the CRLF-to-LF renormalization, `develop -> main` conflicts on seven paths, and `develop`'s `required_linear_history` plus its PR ruleset forbid resolving them on `develop`. This is the documented remedy: resolve on a throwaway branch off `main`, then open that into `main`. ## The resolution is provably exactly `develop` Every conflict was resolved to `develop`'s side, and the result is byte-identical to `develop`'s tree: ```text merged tree 5035943 develop tree 5035943 ``` Each was confirmed lossless before `develop` was taken, per the documented check: | Path | Why taking `develop` drops nothing | | --- | --- | | `global.json` | Content-identical modulo EOL. `main` added it CRLF, `develop` renormalized it. | | `UtilitiesTests/UtilitiesTests.csproj` | Content-identical modulo EOL. | | `UtilitiesTests/ExtensionsTests.cs` | Content-identical modulo EOL. | | `Directory.Packages.props` | Differs in one line, the coverage extension, where `develop` is the newer 18.10.0 against `main`'s 18.9.0. | | `Utilities.slnx` | `main`'s extra entries are a duplicate `dependabot.yml`, a `Data/` folder naming three files this repository does not contain, and the two workflow tasks `develop` deleted because the hub now hosts them. Verified each path is absent on `develop`, and that `dependabot.yml` is still listed there under GitHub Actions. | | `.github/workflows/build-release-task.yml` | Deleted on `develop` per its `retire` disposition. | | `.github/workflows/validate-task.yml` | Deleted on `develop`, which now calls the hub-hosted validator by pin. | ## Verification Run against this branch's tree, not inferred from #451: ```text dotnet build 0 warnings, 0 errors dotnet csharpier check . 43 files, clean dotnet format style --verify-no-changes clean dotnet test (MTP + coverage) 183/183 passed markdownlint-cli2 '**/*.md' 48 files, 0 issues actionlint clean editorconfig-checker clean repo_gate.py eol, eol-coverage, sha-pin all clean prose_lint.py --diff origin/main clean ``` ## Merging The head is `promote/develop-to-main`, not `develop`, so the delete-`develop` trap does not apply here. Merge with a merge commit rather than a squash, per the `main` ruleset. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a `StringHistory` utility for retaining and rendering configurable first and last lines. - Added comprehensive repository architecture, operations, governance, and contribution guidance. - **CI/CD** - Updated validation, testing, and publishing workflows with clearer triggers, scoped permissions, and external workflow integration. - Removed obsolete release and validation workflow definitions. - **Documentation** - Added coding, testing, review, release, and workflow guidance. - **Style** - Standardized text line endings and formatting across the repository. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Why
Same regression as #447, on
mainthis time (per.github/dependabot.yml,mainanddevelopare kept current independently). The .NET 10 SDK dropped the VSTest bridgedotnet testrelied on, sodotnet testfailed outright:Testing with VSTest target is no longer supported by Microsoft.Testing.Platform on .NET 10 SDK and later.This is what was blocking #443 and #444 (both currently fail on theRun unit tests job).What
Identical fix to #447, cherry-picked (the relevant files were byte-identical between
mainanddevelopbefore this PR):UtilitiesTestsinto native Microsoft.Testing.Platform (MTP) viaglobal.json'stest.runnersetting plusUseMicrosoftTestingPlatformRunner/OutputType=Exe.coverlet.collector(VSTest-only) forMicrosoft.Testing.Extensions.CodeCoverage(native MTP coverage), marked test-only viaPrivateAssets.Microsoft.NET.Test.Sdk/xunit.v3/xunit.analyzers/xunit.runner.visualstudioto versions with a compatible MTP runtime.dotnet testinvocation (--coverageinstead of--collect, with an explicit--coverage-outputfilename codecov-action can discover).ExtensionsTests.csnull-argument tests missing a null-forgiving operator.global.jsonin CRLF (this repo's.editorconfigconvention) and added to Solution Items.Verification
Already went through #447's full review loop (local adversarial review, Copilot, CodeRabbit, all findings fixed) on identical content. Re-verified independently on this branch:
dotnet build(0 warnings/errors),dotnet test --coverage --coverage-output-format cobertura --coverage-output coverage.cobertura.xml --results-directory ./coverage(183/183 passed),dotnet csharpier check .,dotnet format style --verify-no-changes, andeditorconfig-checkeronglobal.jsonall clean.Summary by CodeRabbit
Tests
Chores