Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort) - #9566

Merged
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms
Jul 3, 2026
Merged

Abstract VSTest discovery sink in PlatformServices (Phase 3 of platform-agnostic effort)#9566
Amaury Levé (Evangelink) merged 1 commit into
dev/amauryleve/vstest-decoupling-basefrom
dev/amauryleve/abstract-vstest-discovery-sink-platforms

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 3, 2026

Copy link
Copy Markdown
Member

Why

Part of the multi-PR initiative to make src/Adapter/MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.TestPlatform.ObjectModel). VSTest coupling moves up into the adapter boundary; the platform-services engine becomes neutral.

This is Phase 3 (discovery output / sink). It follows the exact pattern established by:

What

The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic sink instead of building VSTest TestCases and pushing them to ITestCaseDiscoverySink.

  • NewInterfaces/IUnitTestElementSink.cs — neutral sink (namespace …PlatformServices.Interface) with void SendTestElement(UnitTestElement testElement). The name deliberately carries no VSTest/TestCase/ObjectModel terms.
  • NewServices/UnitTestElementSinkExtensions.cs — the single VSTest translation point: ToUnitTestElementSink(this ITestCaseDiscoverySink) wraps the host sink and materializes element.ToTestCase() at the boundary.
  • Discovery/UnitTestDiscoverer.csDiscoverTests/DiscoverTestsInSource/SendTestCases now take IUnitTestElementSink; the engine no longer references ITestCaseDiscoverySink or calls ToTestCase().
  • VSTestAdapter/MSTestDiscoverer.cs — wraps the host's real ITestCaseDiscoverySink via .ToUnitTestElementSink() at the adapter boundary.
  • Execution/TestCaseDiscoverySink.cs — the internal execution-side collector now implements IUnitTestElementSink but still materializes TestCase into its ICollection<TestCase> Tests, preserving the execution path.
  • Tests updated: Mock<ITestCaseDiscoverySink> kept and wrapped at call sites (so existing Verify assertions stay meaningful); TestCaseDiscoverySinkTests rewritten for the new API; integration helper CLITestBase.discovery.cs wraps its sink.

No behavior change

Pure refactor. element.ToTestCase() is still invoked exactly once per emitted element in both the discovery and execution paths, the filter application point and the Phase 2 filterHasError bail-out semantics are unchanged, and discovered TestCase fields/Id/properties/traits/ordering are byte-for-byte identical. Execution still consumes TestCase internally (that decoupling is Phase 4, intentionally out of scope here).

Remaining move-to-adapter work (future phases)

  • The Services/UnitTestElementSinkExtensions bridge still lives in PlatformServices for now (same as the Phase 1/2/5 bridges); it is expected to move fully into the adapter layer once discovery no longer flows VSTest sinks through platform services.
  • The execution-side TestCaseDiscoverySink still materializes TestCase because execution consumes TestCase end-to-end — that is Phase 4.

Verification

  • .\build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI) — 0 warnings, 0 errors.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 893/893 passed.
  • MSTestAdapter.UnitTests (net8.0): 21/21 passed.
  • expert-reviewer run on the diff: no blocking/major findings; two doc-consistency nits addressed.

⚠️ Stacked PR

Phase 1 (#9548) and Phase 5 (#9550) are already on main. This PR is stacked on Phase 2 (#9567) and should be reviewed/merged after#9567 lands on main.

Current base is the integration branch dev/amauryleve/vstest-decoupling-base (= main + Phase 2), which keeps the diff clean today. Once #9567 merges, this PR can be retargeted to base=main directly — that is the intended final base. Please do not rebase/reset the base branch in the meantime.

…rm-agnostic effort)
The discovery engine (UnitTestDiscoverer) now emits the neutral UnitTestElement model to a new platform-agnostic IUnitTestElementSink instead of building VSTest TestCase objects and pushing them to ITestCaseDiscoverySink. The single VSTest translation (element.ToTestCase()) moves behind the boundary: a Services/ bridge wraps the host's ITestCaseDiscoverySink, and the internal execution-side collector materializes TestCase itself. Pure refactor, no behavior change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 3, 2026 09:53
@EvangelinkAmaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 3, 2026
@Evangelink
Amaury Levé (Evangelink) merged commit f846008 into dev/amauryleve/vstest-decoupling-baseJul 3, 2026
42 of 47 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/abstract-vstest-discovery-sink-platforms branch July 3, 2026 10:19
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 5, 2026
…ervices
Squashed rebase of the vstest-decoupling PlatformServices stack onto main.
Phases 1, 2 and 5 already landed on main via #9548/#9567/#9550; this commit
carries the remaining net-new work:
- Phase 3 (#9566): abstract the VSTest discovery sink (IUnitTestElementSink).
- Phase 4 (#9572): abstract VSTest execution input.
- Phase 6a (#9576): neutralize deployment input (DeploymentContext).
- Phase 6b (#9579): neutralize test result recording (ITestResultRecorder).
- Phase 6c (#9585): neutralize test message logging.
- Phase 6c2: neutralize run-settings input in the host layer (settingsXml).
- Phase 6d-1: move test-case filter parsing to the adapter boundary
(ITestElementFilterProvider / TestElementFilterProvider).
- Phase 6d-2: remove IRunContext/IDiscoveryContext from PlatformServices.
- Phase 6e-1 (#9622): remove IFrameworkHandle from the execution engine.
- Phase 6e-2 (#9623): relocate VSTest logger/sink bridges to the adapter.
- Phase 6e-3a (#9624): neutralize the trait type on UnitTestElement.
Result: MSTestAdapter.PlatformServices no longer references the VSTest
run/discovery context or result object model; those types live only at the
MSTest.TestAdapter boundary.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-reviewAwaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Evangelink@0101