fix(dotnet): treat global.json MTP as VsTestBridge instead of native mode#1380
fix(dotnet): treat global.json MTP as VsTestBridge instead of native mode#1380danielmarbach wants to merge 2 commits intortk-ai:developfrom
Conversation
…mode PR rtk-ai#746 introduced MtpNative mode which injected --report-trx directly for global.json MTP, breaking xUnit v3 projects with 'Unknown option' (exit 5). --report-trx requires Microsoft.Testing.Extensions.TrxReport which xUnit v3 doesn't bundle (it has --report-xunit-trx instead). Both global.json MTP and project-file MTP now use MtpVsTestBridge, injecting -- --report-trx after the separator. This works for MSTest/TUnit which bundle TrxReport. For xUnit v3 without the extension, the error is informative — tells users to add the NuGet package (per xunit/xunit#3456). Also skips -nologo for all MTP mode since it breaks on .NET 10 native MTP. Fixes rtk-ai#1289
📊 Automated PR Analysis
SummaryFixes global.json MTP detection to use VsTestBridge mode instead of the removed MtpNative mode, which was injecting --report-trx directly and breaking xUnit v3 projects with 'Unknown option' errors. Also skips -nologo for all MTP modes since it breaks on .NET 10 native MTP, and refactors the project file scanning into a separate function. Review Checklist
Linked issues: #1289 Analyzed automatically by wshm · This is an automated analysis, not a human review. |
F0rty-Tw0
left a comment
There was a problem hiding this comment.
The compatibility matrix in the description made me back off two concerns I'd flagged on first read:
-
-nologoskip across MTP modes: I worried this was over-conservative, until the .NET 10 native MTP "Unknown option--nologo" repro. Skip is correct. -
xUnit v3 "Unknown option" surfacing: initially read as a silent UX downgrade, but the trade-off is conscious. A silent skip would regress token savings for the MSTest/TUnit majority who do bundle TrxReport, and the error is informative once a user knows the package name. NuGet detection from csproj/Directory.Build.props/Directory.Packages.props is impractical for the cited reasons (MSBuild inheritance, central package management), so surfacing the error is the right call.
I also ran a fresh sub-review against .claude/rules/rust-patterns.md and cli-testing.md. Variant deletion is complete: every MtpNative site the diff touches is a removal or rewrite, no residue. The scan_project_files_for_mtp early-return refactor is behavior-preserving (no multi-project regression), and there are no new unwrap() outside tests.
Three small follow-ups follow as inline comments, none blocking.
Open since April 18 with P2-important, three-OS CI green, repro from Altinn/altinn-register. Would be great to see this land.
| /// `UseMicrosoftTestingPlatformRunner`, `TestingPlatformDotnetTestSupport`). | ||
| /// `--logger trx` is silently ignored or breaks the run; inject `-- --report-trx` | ||
| /// after the separator so it reaches the MTP runtime. | ||
| MtpVsTestBridge, |
There was a problem hiding this comment.
After this PR, MtpVsTestBridge covers any MTP detection: TestingPlatformDotnetTestSupport=true, UseMicrosoftTestingPlatformRunner=true, UseTestingPlatformRunner=true, and global.json MTP. Per the PR description matrix, several of these don't go through an actual VSTest bridge for MTP at all (the previous code classified some as MtpNative).
The variant doc handles the dual coverage well, but the name biases readers toward the bridge interpretation when the variant is really describing an injection strategy (-- --report-trx), not a single runtime.
Two options to avoid confusing a future reader:
- Rename to
MtpAfterSeparator(descriptive of the action: inject-- --report-trx) rather than the runtime. - Or add a
// Naming note:line stating that "VsTestBridge" here is a historical name kept for diff minimization, covering both bridge and native MTP cases.
Cheap, prevents future churn.
| fn detect_test_runner_mode(args: &[String]) -> TestRunnerMode { | ||
| // global.json MTP mode takes overall precedence — when set, dotnet test runs MTP | ||
| // natively regardless of project file properties. | ||
| if is_global_json_mtp_mode() { |
There was a problem hiding this comment.
The three new tests exercise helpers (parse_global_json_mtp_mode, scan_mtp_kind_in_file, scan_project_files_for_mtp) but none drives the full detect_test_runner_mode returning MtpVsTestBridge from the global.json-only path that motivated the PR.
is_global_json_mtp_mode walks the current directory via std::env::current_dir(), which makes an end-to-end test awkward without test isolation (set_current_dir + serial_test). Every other detection branch (csproj, Directory.Build.props) has an end-to-end test, and global.json is the actual regression path here.
Cleanest fix: refactor is_global_json_mtp_mode() to take a starting-dir parameter and have a thin wrapper read current_dir(). That unblocks unit testing without filesystem juggling and lets a future test exercise the full priority chain (global.json → MtpVsTestBridge) end-to-end.
Co-authored-by: Artiom Tofan <60610474+F0rty-Tw0@users.noreply.github.com>
Fixes #1289
Summary
Problem
PR #746 introduced
MtpNativemode which injected--report-trxas a direct flag for repos withglobal.jsonMTP mode ("test": { "runner": "Microsoft.Testing.Platform" }). This broke xUnit v3 projects with exit code 5:The Altinn/altinn-register repo was affected: .NET 9 SDK, global.json MTP mode, xUnit v3 — no project-file MTP properties at all.
Root cause
--report-trxis not a universal MTP flag. It requires theMicrosoft.Testing.Extensions.TrxReportNuGet package which xUnit v3 doesn't bundle (it has--report-xunit-trxinstead). MSTest and TUnit bundle it, so it worked for them but failed for xUnit v3.Verified behavior
All tested with
global.jsonhaving"test": { "runner": "Microsoft.Testing.Platform" }:-- --report-trx--report-trxThe xUnit v3 issue reporter confirmed (xunit/xunit#3456) that adding
Microsoft.Testing.Extensions.TrxReportNuGet makes--report-trxwork universally.Additionally,
-nologobreaks on .NET 10 native MTP with "Unknown option '--nologo'", so it's now skipped for all MTP mode.Fix
Simplified
TestRunnerModefrom three variants to two:Classic: VSTest runner →--logger trx --results-directory,-nologoinjectedMtpVsTestBridge: Any MTP detection (global.json OR project-file) →-- --report-trx,-nologoskippedRemoved
MtpNativeandMtpGlobalJson. Both global.json MTP and project-file MTP properties now useMtpVsTestBridge, injecting-- --report-trxafter the separator.For xUnit v3 without
Microsoft.Testing.Extensions.TrxReport, this produces an informative "Unknown option" error — the user knows to add the package. This is preferable to silently skipping TRX injection, which would regress token savings for the majority of MTP users (MSTest, TUnit) who do bundle TrxReport and benefit from the optimized TRX parsing path. Detecting the NuGet package from csproj/Directory.Build.props/Directory.Packages.props was ruled out as impractical (MSBuild inheritance, central package management).Test plan
cargo fmt --all && cargo clippy --all-targets && cargo testrtk <command>output inspected