Skip to content

Suggest Microsoft.NET.Test.Sdk when a managed test project brings no testhost - #16169

Merged
Jakub Jareš (nohwnd) merged 1 commit into
microsoft:mainfrom
nohwnd:native-aware-testhost-error
Jun 26, 2026
Merged

Suggest Microsoft.NET.Test.Sdk when a managed test project brings no testhost#16169
Jakub Jareš (nohwnd) merged 1 commit into
microsoft:mainfrom
nohwnd:native-aware-testhost-error

Conversation

@nohwnd

@nohwnd Jakub Jareš (nohwnd) commented Jun 25, 2026

Copy link
Copy Markdown
Member

The Microsoft.TestPlatform package ships a .NET Core testhost right next to the runner. So when a managed test project brings no testhost of its own — i.e. it does not reference Microsoft.NET.Test.SdkDotnetTestHostManager quietly falls back to that built-in testhost, plus the package's testhost.deps.json and a synthesized runtimeconfig. That fallback is meant for native (C++) runners only. A managed project landing there just spins up a testhost that discovers nothing, and the user gets a confusing "no tests" instead of "you forgot Microsoft.NET.Test.Sdk".

I confirmed it — a plain managed net8.0 project without Test.Sdk goes straight into the fallback:

ManagedNoTestSdk.runtimeconfig.json, does not exist
Found testhost.dll next to runner executable: ...\testhost.dll
  --additional-deps "...\testhost.deps.json"
  --runtimeconfig  "...\testhost-8.0.runtimeconfig.json"

So the fix throws at that point: when we are about to use the testhost-next-to-runner fallback and the source is managed (not native), fail and tell the user to reference Microsoft.NET.Test.Sdk (the CouldNotFindTesthost message already lists it). Native (C++) sources keep the fallback, that is what it is for. IsNativeModule (the PEReader check already used for x64 forcing) is promoted to a method so both paths share it.

Tests: unit tests for both branches (managed -> throws, native -> uses the fallback), and an acceptance test that runs a managed project without Test.Sdk (ProjectWithoutTestSdk) through the real package runner and asserts the guidance.

Verified: Microsoft.TestPlatform.TestHostProvider.UnitTests green on net481 (49/49). The net11.0 unit legs and the acceptance test I could not run locally (no pinned .NET 11 preview runtime here), so CI covers those. 🤞

Copilot AI review requested due to automatic review settings June 25, 2026 08:16

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 improves diagnostic clarity when DotnetTestHostManager fails to locate a testhost by restoring a targeted hint for managed test sources that are missing a .deps.json (commonly due to not referencing Microsoft.NET.Test.Sdk), while keeping the existing generic behavior for native sources.

Changes:

  • Use Resources.UnableToFindDepsFile (Test.Sdk guidance) only when the source is managed and the corresponding .deps.json is missing.
  • Promote native-module detection to an internal virtual IsNativeModule(string) helper (shared by both the x64-forcing logic and the new error-message decision).
  • Add unit tests covering the native vs managed/no-deps branches.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs Chooses a more actionable error message for managed sources missing .deps.json; refactors native detection into an overridable helper.
test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs Adds tests for native vs managed/no-deps error message selection, with a test hook overriding native detection.

@nohwnd

Copy link
Copy Markdown
Member Author

still needs work the fix is not correct.

@nohwnd
Jakub Jareš (nohwnd) force-pushed the native-aware-testhost-error branch from 76927e7 to 0f751a8 Compare June 25, 2026 08:46
@nohwnd

Copy link
Copy Markdown
Member Author

Improves #16053

Copilot AI review requested due to automatic review settings June 25, 2026 09:31
@nohwnd
Jakub Jareš (nohwnd) force-pushed the native-aware-testhost-error branch from 0f751a8 to a710b52 Compare June 25, 2026 09:31

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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Comment thread test/Microsoft.TestPlatform.Acceptance.IntegrationTests/MissingTestSdkTests.cs Outdated
…s back to the built-in testhost

The Microsoft.TestPlatform package ships a .NET Core testhost next to the runner, so when a managed test project brings
no testhost of its own (it does not reference Microsoft.NET.Test.Sdk), DotnetTestHostManager silently falls back to that
built-in testhost plus the package's testhost.deps.json and a synthesized runtimeconfig. That fallback exists for native
(C++) runners only; a managed project landing there just discovers no tests.

So when we are about to use the testhost-next-to-runner fallback and the source is managed (not native), throw and point
the user at the missing Microsoft.NET.Test.Sdk reference instead. Native (C++) sources keep the fallback.

IsNativeModule is promoted to a method so the failure path and the x64-forcing path share it. Adds unit tests for both
branches, plus acceptance tests: a managed project without Test.Sdk (ProjectWithoutTestSdk) that must fail with the
guidance, and a native C++ project (the prebuilt Microsoft.TestPlatform.TestAsset.NativeCPP) that must keep the fallback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nohwnd
Jakub Jareš (nohwnd) merged commit b0e039f into microsoft:main Jun 26, 2026
20 checks passed
ptr727-codegen Bot pushed a commit to ptr727/NxWitness that referenced this pull request Aug 14, 2026
Updated [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest)
from 18.8.1 to 18.9.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.NET.Test.Sdk's
releases](https://github.com/microsoft/vstest/releases)._

## 18.9.0

## What's Changed
* Fix tilde/exclamation characters corrupted in TerminalLogger test
output by @​nohwnd in microsoft/vstest#16046
* Make TranslationLayer Native AOT-compatible by @​drewnoakes in
microsoft/vstest#16045
* Guard GenerateProgramFile target against UseWinUI/UseUwpTools
evaluation order by @​nohwnd in
microsoft/vstest#16072
* Add RequestingAssembly to AssemblyResolveEventArgs for binary compat
by @​nohwnd in microsoft/vstest#16076
* Remove stale Microsoft.Extensions.FileSystemGlobbing binding redirect
from testhost.x86 and datacollector by @​Evangelink in
microsoft/vstest#16082
* Fix TRX attachment paths when LogFileName contains a subdirectory by
@​nohwnd in microsoft/vstest#15791
* Fix missing dumps for .NET Framework child processes in
NetClientHangDumper by @​nohwnd in
microsoft/vstest#16098
* Fix data collection channels to use negotiated protocol version
instead of V1 by @​nohwnd in
microsoft/vstest#16096
* Fix race condition in BlameCollector: skip hang dump when testhost
hasn't launched yet by @​nohwnd in
microsoft/vstest#16065
* Replace TestSDKAutoGeneratedCode with ExcludeFromCodeCoverage in
auto-generated Program files by @​nohwnd in
microsoft/vstest#16101
* Include testhost process path in crash error messages by @​nohwnd in
microsoft/vstest#16108
* Fix DataDriven test results being double-counted in TRX logger totals
by @​nohwnd in microsoft/vstest#15766
* Fix datacollector crash visibility: replace Assert with throwable
exceptions by @​nohwnd in microsoft/vstest#16048
* Add TreatErrorMessagesAsWarnings parameter to TRX logger by @​nohwnd
in microsoft/vstest#16106
* Wait for testhost stderr to drain before reading its crash output by
@​nohwnd in microsoft/vstest#16128
* Handle runtimeconfig.dev.json without additionalProbingPaths by @​tmat
in microsoft/vstest#16166
* Suggest Microsoft.NET.Test.Sdk when a managed test project brings no
testhost by @​nohwnd in microsoft/vstest#16169
* Fix x86 testhost loading mismatched x64 hostfxr (0x800700C1) when run
via vstest.console.exe directly (#​16151) by @​azat-msft in
microsoft/vstest#16156
* Preserve the real exception (type + stack trace) when a test run
aborts in BaseRunTests by @​nohwnd in
microsoft/vstest#16167

## New Contributors
* @​drewnoakes made their first contribution in
microsoft/vstest#16045

**Full Changelog**:
microsoft/vstest@v18.8.0...v18.9.0

Commits viewable in [compare
view](microsoft/vstest@v18.8.1...v18.9.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.NET.Test.Sdk&package-manager=nuget&previous-version=18.8.1&new-version=18.9.0)](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>
ptr727-codegen Bot added a commit to ptr727/NxWitness that referenced this pull request Aug 14, 2026
Updated [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest)
from 18.8.1 to 18.9.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.NET.Test.Sdk's
releases](https://github.com/microsoft/vstest/releases)._

## 18.9.0

## What's Changed
* Fix tilde/exclamation characters corrupted in TerminalLogger test
output by @​nohwnd in microsoft/vstest#16046
* Make TranslationLayer Native AOT-compatible by @​drewnoakes in
microsoft/vstest#16045
* Guard GenerateProgramFile target against UseWinUI/UseUwpTools
evaluation order by @​nohwnd in
microsoft/vstest#16072
* Add RequestingAssembly to AssemblyResolveEventArgs for binary compat
by @​nohwnd in microsoft/vstest#16076
* Remove stale Microsoft.Extensions.FileSystemGlobbing binding redirect
from testhost.x86 and datacollector by @​Evangelink in
microsoft/vstest#16082
* Fix TRX attachment paths when LogFileName contains a subdirectory by
@​nohwnd in microsoft/vstest#15791
* Fix missing dumps for .NET Framework child processes in
NetClientHangDumper by @​nohwnd in
microsoft/vstest#16098
* Fix data collection channels to use negotiated protocol version
instead of V1 by @​nohwnd in
microsoft/vstest#16096
* Fix race condition in BlameCollector: skip hang dump when testhost
hasn't launched yet by @​nohwnd in
microsoft/vstest#16065
* Replace TestSDKAutoGeneratedCode with ExcludeFromCodeCoverage in
auto-generated Program files by @​nohwnd in
microsoft/vstest#16101
* Include testhost process path in crash error messages by @​nohwnd in
microsoft/vstest#16108
* Fix DataDriven test results being double-counted in TRX logger totals
by @​nohwnd in microsoft/vstest#15766
* Fix datacollector crash visibility: replace Assert with throwable
exceptions by @​nohwnd in microsoft/vstest#16048
* Add TreatErrorMessagesAsWarnings parameter to TRX logger by @​nohwnd
in microsoft/vstest#16106
* Wait for testhost stderr to drain before reading its crash output by
@​nohwnd in microsoft/vstest#16128
* Handle runtimeconfig.dev.json without additionalProbingPaths by @​tmat
in microsoft/vstest#16166
* Suggest Microsoft.NET.Test.Sdk when a managed test project brings no
testhost by @​nohwnd in microsoft/vstest#16169
* Fix x86 testhost loading mismatched x64 hostfxr (0x800700C1) when run
via vstest.console.exe directly (#​16151) by @​azat-msft in
microsoft/vstest#16156
* Preserve the real exception (type + stack trace) when a test run
aborts in BaseRunTests by @​nohwnd in
microsoft/vstest#16167

## New Contributors
* @​drewnoakes made their first contribution in
microsoft/vstest#16045

**Full Changelog**:
microsoft/vstest@v18.8.0...v18.9.0

Commits viewable in [compare
view](microsoft/vstest@v18.8.1...v18.9.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.NET.Test.Sdk&package-manager=nuget&previous-version=18.8.1&new-version=18.9.0)](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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants