Summary
A test project declaring <TargetFrameworks>net8.0;net9.0</TargetFrameworks> appears twice at the root of the Testing view, under two labels the user cannot tell apart — with the same namespaces, the same classes and the same tests duplicated beneath each.
Seen on FluentValidation.Tests:
∨ FluentValidation.Tests
> FluentValidation.Tests
> FluentValidation.Tests.DependencyInjectionExtensions
∨ FluentValidation.Tests ← same project, second target framework
Root cause
dotnet test --list-tests announces one Test run for … banner per target framework:
Test run for …\bin\Debug\net10.0\MultiTfm.dll (.NETCoreApp,Version=v10.0)
Test run for …\bin\Debug\net8.0\MultiTfm.dll (.NETCoreApp,Version=v8.0)
namesFrom made one TestAssemblyListing per announced path, and makeAssemblyItem keys the tree root on assembly:${assembly.path} (src/editors/vscode/src/testing.ts:374). Two paths differing only in the bin/<config>/<tfm>/ segment therefore produced two roots with an identical label.
Status — fixed on fixloading (not yet merged)
mergeMultiTargeted in src/editors/vscode/src/test-discovery.ts collapses assemblies sharing a file name into one listing. Names are unioned, not taken from whichever framework was announced first — a test behind #if NET8_0 exists in only one assembly, and dropping it would trade a duplicated tree for a missing test. The surviving path is the lexicographically smallest so the group ids stay stable across sweeps however the build ordered its banners.
Regression suite: src/test/suite/test-explorer-multitarget.test.ts. Its fixture reads <TargetFrameworks> off the agent's installed runtimes rather than pinning them — a second framework with no runtime never gets a test host, so the project would silently degrade to a single target and the suite would pass vacuously against the very bug it exists to catch. A first test asserts the two assemblies really were announced.
Before the fix:
a multi-targeted project is ONE assembly root; the Testing view showed: XunitCs | XunitCs
each test appears once whatever it is compiled for; duplicated leaves in:
Adds_TwoNumbers, Fails_OnPurpose, …, Adds_TwoNumbers, Fails_OnPurpose, …
After: 3 passing; the testexplorer (54) and testexplorer-frameworks (20) chunks stayed green.
[TEST-DISCOVERY-FQN] updated to specify the collapse and the union.
Filed for the record so the fix is traceable; close with the PR.
Environment
- Windows 11, .NET SDK 10.0.303
- FluentValidation.Tests:
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
Summary
A test project declaring
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>appears twice at the root of the Testing view, under two labels the user cannot tell apart — with the same namespaces, the same classes and the same tests duplicated beneath each.Seen on
FluentValidation.Tests:Root cause
dotnet test --list-testsannounces oneTest run for …banner per target framework:namesFrommade oneTestAssemblyListingper announced path, andmakeAssemblyItemkeys the tree root onassembly:${assembly.path}(src/editors/vscode/src/testing.ts:374). Two paths differing only in thebin/<config>/<tfm>/segment therefore produced two roots with an identical label.Status — fixed on
fixloading(not yet merged)mergeMultiTargetedinsrc/editors/vscode/src/test-discovery.tscollapses assemblies sharing a file name into one listing. Names are unioned, not taken from whichever framework was announced first — a test behind#if NET8_0exists in only one assembly, and dropping it would trade a duplicated tree for a missing test. The surviving path is the lexicographically smallest so the group ids stay stable across sweeps however the build ordered its banners.Regression suite:
src/test/suite/test-explorer-multitarget.test.ts. Its fixture reads<TargetFrameworks>off the agent's installed runtimes rather than pinning them — a second framework with no runtime never gets a test host, so the project would silently degrade to a single target and the suite would pass vacuously against the very bug it exists to catch. A first test asserts the two assemblies really were announced.Before the fix:
After: 3 passing; the
testexplorer(54) andtestexplorer-frameworks(20) chunks stayed green.[TEST-DISCOVERY-FQN] updated to specify the collapse and the union.
Filed for the record so the fix is traceable; close with the PR.
Environment
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>