Skip to content

Switch HelixTestRunner from dotnet test to dotnet vstest#66896

Closed
mmitche wants to merge 3 commits into
mainfrom
dev/switch-to-dotnet-vstest
Closed

Switch HelixTestRunner from dotnet test to dotnet vstest#66896
mmitche wants to merge 3 commits into
mainfrom
dev/switch-to-dotnet-vstest

Conversation

@mmitche

@mmitche mmitche commented May 28, 2026

Copy link
Copy Markdown
Member

Switch HelixTestRunner from dotnet test to dotnet vstest

Why

Both commands delegate to vstest.console internally, but dotnet vstest:

Argument mapping

dotnet test dotnet vstest
--filter "expr" --testcasefilter:"expr"
--blame-crash --blame-hang-timeout 15m --blame:CollectDump
--logger name --logger:name
--diag:path --diag:"path"

Other changes

  • Deduplicates the quarantined/non-quarantined if/else branches into a shared filter variable
  • No functional change to test execution — same vstest.console engine, same test results format

Both delegate to vstest.console, but dotnet vstest accepts multiple
DLL paths (needed for batching) and has a more predictable arg format.
Already used for discovery. Deduplicates quarantine branches.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework label May 28, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey @dotnet/aspnet-build, looks like this PR is something you want to take a look at.

@mmitche

mmitche commented May 28, 2026

Copy link
Copy Markdown
Member Author

@wtgodbe This is in prep for the batching changes. I wanted to break them down into smaller chunks, and switching to vstest allows for passing of multiple test dlls at once.

The dotnet test --blame-hang-timeout 15m flag kills individual hung
tests after 15 minutes and collects a dump. Without it, a single
hung test blocks the entire work item until the Helix timeout (45 min)
with no dump for diagnosis. The vstest equivalent is
--blame:CollectDump;CollectHangDump;TestTimeout=15min.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mmitche mmitche marked this pull request as ready for review May 28, 2026 17:01
Copilot AI review requested due to automatic review settings May 28, 2026 17:01
@mmitche mmitche requested review from a team and wtgodbe as code owners May 28, 2026 17:01
@mmitche

mmitche commented May 28, 2026

Copy link
Copy Markdown
Member Author

Not yet ready.

Copilot AI left a comment

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.

Pull request overview

This PR updates the HelixTestRunner’s test execution path to invoke dotnet vstest instead of dotnet test, aligning execution with the already-used discovery approach and enabling future batching scenarios.

Changes:

  • Switches test execution to dotnet vstest with mapped arguments (--testcasefilter, --diag, --logger, blame options).
  • Deduplicates quarantined vs non-quarantined execution logic by using a shared filter variable.

Comment thread eng/tools/HelixTestRunner/TestRunner.cs
The original code intentionally did not set exitCode when quarantined
tests failed — quarantined tests are expected to fail and should not
cause the Helix work item to be marked as failed. The refactor
accidentally started propagating the exit code for both cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
// (needed for future batching) and has a more predictable argument format.
// Argument mapping: --filter → --testcasefilter, --blame-crash → --blame:CollectDump
var commonTestArgs = $"vstest {Options.Target} --diag:\"{diagLog}\" --logger:xunit --logger:\"console;verbosity=normal\" " +
"--blame:CollectDump;CollectHangDump;TestTimeout=15min";

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Validated locally that these work.

@Youssef1313 Youssef1313 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure this is good long-term.

@nohwnd What's the current status of dotnet vstest?

https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-vstest

The dotnet vstest command is superseded by dotnet test, which can now be used to run assemblies. See dotnet test.

Should I read this as "kinda deprecated"?

@nohwnd

nohwnd commented May 29, 2026

Copy link
Copy Markdown
Member

I would like to remove dotnet vstest eventually, so I would not recommend moving to it.

All that dotnet vstest can do, dotnet test should be able to do as well. As soon as you give it a single (or more) dll parameters it will switch to "dotnet vstest" mode. Apart from the issues listed in the description is there anything else?

  • Accepts multiple DLL paths as positional arguments - dotnet test does that as well
  • Has a more predictable argument format - is that significant advantage when you are running it programatically?
  • Is already used for test discovery - dotnet test has the same parameter that works the same way.

Since you talk about discovering tests? What is the task here that is being achieved? If you are orchestrating test runs then maybe running via translation layer (like VS does it) might provide more power to what you are doing.

And give us more push to implement things like sharding of test runs based on historical results, to optimized utilization of servers etc.

@mmitche

mmitche commented May 29, 2026

Copy link
Copy Markdown
Member Author

I would like to remove dotnet vstest eventually, so I would not recommend moving to it.

All that dotnet vstest can do, dotnet test should be able to do as well. As soon as you give it a single (or more) dll parameters it will switch to "dotnet vstest" mode. Apart from the issues listed in the description is there anything else?

  • Accepts multiple DLL paths as positional arguments - dotnet test does that as well
  • Has a more predictable argument format - is that significant advantage when you are running it programatically?
  • Is already used for test discovery - dotnet test has the same parameter that works the same way.

Since you talk about discovering tests? What is the task here that is being achieved? If you are orchestrating test runs then maybe running via translation layer (like VS does it) might provide more power to what you are doing.

And give us more push to implement things like sharding of test runs based on historical results, to optimized utilization of servers etc.

Ahh interesting! The models do NOT think that dotnet test can accept multiple dlls. The help and documentation also does not make this obvious.

I'm not sure what the purpose of the discovery is.

@mmitche

mmitche commented May 29, 2026

Copy link
Copy Markdown
Member Author

@wtgodbe Do you happen to know what the discovery is for?

@mmitche mmitche closed this May 29, 2026
@mmitche

mmitche commented May 29, 2026

Copy link
Copy Markdown
Member Author

Note that roslyn uses dotnet vstest so we might want to make a change there.

@nohwnd

nohwnd commented May 29, 2026

Copy link
Copy Markdown
Member

👍 we did not do any analysis on impact of removing vstest recently, so no hurry. I expect many places still using it. There should be some telemetry when revisiting.

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

Labels

area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants