Uh oh!
There was an error while loading. Please reload this page.
Add dotnet test --list-devices support for MAUI - #54565
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the dotnet test Microsoft Testing Platform (MTP) command to support --list-devices, mirroring the existing dotnet run --list-devices behavior so MAUI/Android/iOS test projects can enumerate device IDs without building or running tests.
Changes:
- Added
dotnet test --list-devicesoption and an early-exit listing flow that callsComputeAvailableDevicesviaRunCommandSelector. - Updated
RunCommandSelector.TrySelectDeviceto accept acommandNameso the printed example uses the invoking command (dotnet runvsdotnet test). - Added integration tests for listing behavior and updated the MTP help snapshot.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/dotnet.Tests/CommandTests/Test/snapshots/MTPHelpSnapshotTests.VerifyMTPHelpOutput.verified.txt | Updates dotnet test MTP help snapshot to include --list-devices. |
| test/dotnet.Tests/CommandTests/Test/GivenDotnetTestSelectsDevice.cs | Adds integration tests covering --list-devices scenarios (multi-TFM, single device, missing target, solution error). |
| src/Cli/Microsoft.DotNet.Cli.Definitions/Commands/Test/TestCommandDefinition.MicrosoftTestingPlatform.cs | Adds the --list-devices option to the MTP dotnet test command definition. |
| src/Cli/dotnet/Commands/Test/MTP/SolutionAndProjectUtility.cs | Passes commandName: "dotnet test" into device selection to render correct examples. |
| src/Cli/dotnet/Commands/Test/MTP/Options.cs | Extends BuildOptions to carry the ListDevices flag. |
| src/Cli/dotnet/Commands/Test/MTP/MSBuildUtility.cs | Wires --list-devices parse result into BuildOptions. |
| src/Cli/dotnet/Commands/Test/MTP/MicrosoftTestingPlatformTestCommand.cs | Implements the --list-devices early-exit flow and improves solution handling for --device. |
| src/Cli/dotnet/Commands/Run/RunCommandSelector.cs | Adds commandName parameter to TrySelectDevice and uses it in example output. |
| src/Cli/dotnet/Commands/Run/RunCommand.cs | Updates dotnet run to pass commandName: "dotnet run" into TrySelectDevice. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
42c6c89 to
838816dCompare838816d to
ea200a3CompareEvangelink
commented
Jun 5, 2026
Reviewed the diff against 🐛 Bugs / Correctness1. |
ea200a3 to
baf0f8fCompareThanks for the thorough review! Pushed a follow-up commit (squashed into the single commit on the branch). Summary of what I addressed: Adopted:
Skipped (with rationale):
|
21f746b to
34938eeCompare
Evangelink
left a comment
There was a problem hiding this comment.
Note
This review was generated with AI assistance and reviewed before posting.
Overall this is a clean change that mirrors dotnet run --list-devices closely — signatures and call sites are consistent, the new resource strings exist, .xlf files are regenerated correctly, and the help snapshot matches. A few items below, mostly around test coverage and a behavioral inconsistency between the --device and --list-devices solution guards.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| // Step 2: List devices. This calls ComputeAvailableDevices if the target exists; | ||
| // otherwise it silently no-ops (matches `dotnet run --list-devices`). | ||
| if (!selector.TrySelectDevice( |
There was a problem hiding this comment.
Low confidence / pre-existing: TryComputeAvailableDevices (in RunCommandSelector) returns false identically for three distinct cases — target absent, restore failed, and ComputeAvailableDevices build failed — and TrySelectDevice treats a false target result as "no device support" and returns true. So dotnet test --list-devices on a project that has the target but fails to restore/build exits 0 with no output rather than surfacing the failure. This is inherited from the dotnet run selector, but the behavior is now also on the test path — flagging as an opportunity rather than a blocker.
There was a problem hiding this comment.
Agree this is worth documenting, but keeping the current behavior intentionally: it matches dotnet run --list-devices exactly (the whole point of using RunCommandSelector here is parity with the run path). Improving the diagnostics on restore/build failure would be a good separate change in RunCommandSelector itself, benefiting both dotnet run and dotnet test users.
7524011 to
5b167f7Compare
Evangelink
left a comment
There was a problem hiding this comment.
Note
This review was generated with AI assistance and reviewed before posting.
Re-reviewed after the latest push. The two earlier findings look correctly addressed: the --device + --solution guard was moved out of the TargetFramework check so it now rejects unconditionally (matching --list-devices), and ItErrorsWhenUsingDeviceForSolution covers both the -f and no--f cases. One new blocking issue from the merge with main below.
| string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyDevice, "--device")); | ||
| } | ||
| [Fact] |
There was a problem hiding this comment.
Blocking (compile break): the merge from main migrated this file to MSTest.Sdk — the pre-existing tests above (lines ~18-196) are now [TestClass]/[TestMethod]/[DataRow], but every PR-added test from here down (lines 198-379) still uses xUnit [Fact]/[Theory]/[InlineData]. dotnet.Tests.csproj references Microsoft.NET.TestFramework.MSTest.csproj and has no using Xunit (the Xunit global using only lives in the non-MSTest Microsoft.NET.TestFramework.csproj), so these attributes won't resolve — this is now the only file in dotnet.Tests containing [Fact]. Note the Finding-1 fix ItErrorsWhenUsingDeviceForSolution also uses [Theory]/[InlineData], so it won't compile either. Convert all PR-added tests: [Fact] -> [TestMethod], [Theory] -> [TestMethod], [InlineData(x)] -> [DataRow(x)]. The tests use FluentAssertions and no Assert.Throws, so the attributes are the only change needed.
There was a problem hiding this comment.
Done in 1763335 — converted every PR-added test in this file to MSTest: [Fact] -> [TestMethod], [Theory] + [InlineData(x)] -> [TestMethod] + [DataRow(x)], added [TestClass] on the class, dropped the ITestOutputHelper ctor injection in favor of the parameterless ctor + inherited Log property (matches the pattern the rest of dotnet.Tests uses post-migration). Assertions and test logic are unchanged. Verified dotnet build test/dotnet.Tests/dotnet.Tests.csproj compiles clean locally.
Implements the spec from documentation/general/dotnet-run-for-maui.md to add `--list-devices` and `--device` support to `dotnet test` for MTP-enabled projects. Shares the `RunCommandSelector` plumbing with `dotnet run` so target-framework prompting, MSBuild evaluation, and device discovery all behave consistently between the two commands. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t-test-list-devices # Conflicts: # test/dotnet.Tests/CommandTests/Test/GivenDotnetTestSelectsDevice.cs
5b167f7 to
1763335Compare
Evangelink
left a comment
There was a problem hiding this comment.
Note
This review was generated with AI assistance and reviewed before posting.
Re-reviewed the latest push. The blocking compile break is fully resolved — all PR-added tests now use MSTest attributes ([TestMethod]/[DataRow]), and there are no remaining [Fact]/[Theory]/[InlineData] or other xUnit references anywhere in dotnet.Tests. Combined with the earlier rounds, everything I raised is addressed:
--device+--solutionis now rejected unconditionally (parity with--list-devices+--solution), covered by the parameterizedItErrorsWhenUsingDeviceForSolution.- The
--device-on-solution error-message fix has regression coverage. - The restore/build-failure silent-success behavior is intentional parity with
dotnet run --list-devices, reasonably deferred to a separate change inRunCommandSelector.
The --list-devices flow mirrors dotnet run --list-devices cleanly, signatures/call sites are consistent, resource strings and .xlf regeneration are correct, and the help snapshot matches. LGTM.
Expands on #54295 (which added
dotnet test --device) to implement the--list-devicesswitch ondotnet test, as described indotnet-run-for-maui.md. This lets users discover the device identifiers they can pass to--devicefor MAUI/Android/iOS test projects without first having to run a build.Behavior
dotnet test --list-devicesmirrorsdotnet run --list-devices:$(TargetFramework)for multi-targeted projects in interactive mode; errors with a--frameworksuggestion in non-interactive mode.ComputeAvailableDevicesMSBuild target viaRunCommandSelectorand prints the available devices with a friendlydotnet test --device <id>example.ComputeAvailableDevicestarget, exits silently with success (matchesdotnet run --list-devices).Implementation notes
To keep the listing flow structurally identical to
dotnet run --list-devices,HandleListDevicesreuses a singleRunCommandSelectorinstance forTrySelectTargetFramework->InvalidateGlobalProperties->TrySelectDevice(listDevices: true), the same sequence asRunCommand.TrySelectTargetFrameworkAndDeviceIfNeeded.RunCommandSelector.TrySelectDevicegained a requiredcommandNameparameter so the listed/error example rendersdotnet test --device <id>instead of the previously hard-codeddotnet run --device <id>. The two existing call sites (dotnet run, per-TFM device selection in tests) pass"dotnet run"and"dotnet test"respectively.Code review surfaced a separate latent bug from #54295: when
--devicewas used against a solution, the error told users to specify--frameworkeven though that wouldn't fix the failure. Both--deviceand--list-devicesnow throwTestCommandUseProject(Specifying a project for 'dotnet test' should be via '--project'.). The--deviceguard applies unconditionally, including when-f/--frameworkis also passed, matching--list-devicesbehavior.Tests
Six new integration tests in
GivenDotnetTestSelectsDevice:-f-fComputeAvailableDevices--projecthint when--list-devicesis run against a solution--projecthint when--deviceis used against a solution (parameterized with and without-f)The MTP help snapshot is also updated for the new
--list-devicesline.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com