Skip to content

fix(dotnet): treat global.json MTP as VsTestBridge instead of native mode#1380

Open
danielmarbach wants to merge 2 commits intortk-ai:developfrom
danielmarbach:dotnet-mtp
Open

fix(dotnet): treat global.json MTP as VsTestBridge instead of native mode#1380
danielmarbach wants to merge 2 commits intortk-ai:developfrom
danielmarbach:dotnet-mtp

Conversation

@danielmarbach
Copy link
Copy Markdown
Contributor

@danielmarbach danielmarbach commented Apr 18, 2026

Fixes #1289

Summary

Problem

PR #746 introduced MtpNative mode which injected --report-trx as a direct flag for repos with global.json MTP mode ("test": { "runner": "Microsoft.Testing.Platform" }). This broke xUnit v3 projects with exit code 5:

Unknown option '--report-trx'
Test run completed with non-success 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-trx is not a universal MTP flag. It requires the Microsoft.Testing.Extensions.TrxReport NuGet package which xUnit v3 doesn't bundle (it has --report-xunit-trx instead). MSTest and TUnit bundle it, so it worked for them but failed for xUnit v3.

Verified behavior

All tested with global.json having "test": { "runner": "Microsoft.Testing.Platform" }:

Framework SDK -- --report-trx Direct --report-trx
xUnit v3 3.2.2 .NET 9 ✗ Unknown option ✗ Unknown option
xUnit v3 3.2.2 .NET 10 ✗ Unknown option ✗ Unknown option
MSTest 4.0.2 .NET 9 N/A (MSBuild error)
TUnit 1.36.0 .NET 9 ✓ TRX generated N/A
TUnit 1.36.0 .NET 10 ✓ TRX generated ✓ TRX generated

The xUnit v3 issue reporter confirmed (xunit/xunit#3456) that adding Microsoft.Testing.Extensions.TrxReport NuGet makes --report-trx work universally.

Additionally, -nologo breaks on .NET 10 native MTP with "Unknown option '--nologo'", so it's now skipped for all MTP mode.

Fix

Simplified TestRunnerMode from three variants to two:

  • Classic: VSTest runner → --logger trx --results-directory, -nologo injected
  • MtpVsTestBridge: Any MTP detection (global.json OR project-file) → -- --report-trx, -nologo skipped

Removed MtpNative and MtpGlobalJson. Both global.json MTP and project-file MTP properties now use MtpVsTestBridge, injecting -- --report-trx after 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 test
  • Manual testing: rtk <command> output inspected

Important: All PRs must target the develop branch (not master).
See CONTRIBUTING.md for details.

…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
@danielmarbach danielmarbach changed the base branch from master to develop April 18, 2026 13:22
@pszymkowiak pszymkowiak added bug Something isn't working effort-medium 1-2 jours, quelques fichiers labels Apr 18, 2026
@pszymkowiak
Copy link
Copy Markdown
Collaborator

[w] wshm · Automated triage by AI

📊 Automated PR Analysis

🐛 Type bug-fix
🟡 Risk medium

Summary

Fixes 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

  • Tests present
  • Breaking change
  • Docs updated

Linked issues: #1289


Analyzed automatically by wshm · This is an automated analysis, not a human review.

@danielmarbach danielmarbach marked this pull request as ready for review April 18, 2026 13:27
@aeppling aeppling added the P2-important Devrait être fixé bientôt label Apr 21, 2026
Copy link
Copy Markdown
Contributor

@F0rty-Tw0 F0rty-Tw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compatibility matrix in the description made me back off two concerns I'd flagged on first read:

  1. -nologo skip across MTP modes: I worried this was over-conservative, until the .NET 10 native MTP "Unknown option --nologo" repro. Skip is correct.

  2. 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,
Copy link
Copy Markdown
Contributor

@F0rty-Tw0 F0rty-Tw0 May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/cmds/dotnet/dotnet_cmd.rs
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() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working effort-medium 1-2 jours, quelques fichiers P2-important Devrait être fixé bientôt

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rtk dotnet test fails on repositories that use the new testing infrastructure

4 participants