Skip to content

Abstract VSTest result reporting in PlatformServices (Phase 5 of platform-agnostic effort)#9550

Open
Evangelink wants to merge 1 commit into
mainfrom
dev/amauryleve/abstract-vstest-results-platformservices
Open

Abstract VSTest result reporting in PlatformServices (Phase 5 of platform-agnostic effort)#9550
Evangelink wants to merge 1 commit into
mainfrom
dev/amauryleve/abstract-vstest-results-platformservices

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Why

Part of the multi-PR effort to make MSTestAdapter.PlatformServices platform-agnostic by removing its dependency on the VSTest object model (Microsoft.VisualStudio.TestPlatform.ObjectModel.*). The VSTest coupling is being concentrated into small adapter-facing bridges so it can later be lifted entirely out of PlatformServices.

Phase 5 targets the execution result / output path: the VSTest result-side types (TestResult, TestOutcome, TestResultMessage, AttachmentSet, UriDataAttachment) and the recorder role used to report results.

What

  • New neutral abstraction ITestResultRecorder (Interfaces/ITestResultRecorder.cs, namespace …PlatformServices.Interface): a functional, platform-agnostic sink with RecordStart / RecordEmptyResult / RecordResult(TestCase, framework TestResult, start, end). It carries no VSTest result-type naming and reuses the framework TestResult.
  • Single VSTest translation point HostTestResultRecorder behind TestResultRecorderExtensions.ToTestResultRecorder(this ITestExecutionRecorder, computerName, settings) (Services/TestResultRecorderExtensions.cs, namespace …PlatformServices). This bridge is the only place that builds a VSTest TestResult/TestOutcome, records attachments/messages, and calls the VSTest recorder — mirroring the Phase 1 IAdapterMessageLogger + AdapterMessageLoggerExtensions pattern.
  • Execution/TestExecutionManager.Runner.cs now reports start/empty/result through ITestResultRecorder, so it no longer constructs any VSTest result-side type. The VSTest recorder is wrapped once at the boundary (inside ExecuteTestsWithTestRunnerAsync) to avoid touching Phase 1 files.
  • TestResultExtensions.ToTestResult and UnitTestOutcomeHelper.ToTestOutcome are unchanged (still directly unit-tested) and are now invoked from the bridge.

No behavior change

This is a pure refactor. The UnitTestOutcome → VSTest TestOutcome mapping and the assembled TestResult (messages, attachments, error info, timings) are byte-for-byte equivalent, and every branch of the original SendTestResults flow is preserved: empty-results → RecordEnd(None); per result → RecordEnd(mapped), trace on Failed, _hasAnyTestFailed (under #if !WINDOWS_UWP && !WIN_UI), and the guarded RecordResult inside try/catch(TestCanceledException) with the NotFound + hot-reload skip.

Verification

  • build.cmd -c Debug green across all TFMs (net462, net8.0, net9.0, UWP, WinUI); analyzers-as-errors clean.
  • MSTestAdapter.PlatformServices.UnitTests (net8.0): 889 passed.
  • MSTestAdapter.UnitTests (net8.0): 21 passed.
  • expert-reviewer confirmed byte-for-byte equivalence of the refactored flow.

Relationship to other PRs

Independent of and parallel to #9548 (Phase 1). The diff is disjoint from Phase 1's production files. One Phase-1 test file (TestExecutionManagerTests.cs) is touched by a single line — the direct SendTestResults call now wraps _frameworkHandle.ToTestResultRecorder(...); this hunk is far from Phase 1's edits and should not conflict.

Introduce a platform-agnostic `ITestResultRecorder` so the execution result
path in PlatformServices no longer constructs VSTest result-side types
(`TestResult`, `TestOutcome`, `TestResultMessage`, `AttachmentSet`,
`UriDataAttachment`). The single VSTest translation point now lives in the
adapter-facing bridge `HostTestResultRecorder`
(`Services/TestResultRecorderExtensions.ToTestResultRecorder`), mirroring the
Phase 1 `IAdapterMessageLogger` + `AdapterMessageLoggerExtensions` pattern.

`TestExecutionManager.Runner.cs` routes start/empty/result reporting through the
neutral recorder. `TestResultExtensions.ToTestResult` and
`UnitTestOutcomeHelper.ToTestOutcome` are unchanged and are now called from the
bridge. This is a pure refactor with no behavior change: the outcome mapping,
assembled `TestResult`, and the trace / `_hasAnyTestFailed` / NotFound+HotReload
branches are preserved.

Independent of and parallel to PR #9548 (Phase 1).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 1, 2026 15:42

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 is Phase 5 of the effort to make MSTestAdapter.PlatformServices platform-agnostic by concentrating VSTest result-object-model usage into a single bridge and having the execution pipeline report results through a neutral abstraction.

Changes:

  • Introduces a new internal result-recording abstraction: ITestResultRecorder.
  • Adds a single VSTest bridge (TestResultRecorderExtensions / HostTestResultRecorder) that translates framework results into VSTest TestResult and forwards to ITestExecutionRecorder.
  • Refactors TestExecutionManager.Runner to record start/empty/result via ITestResultRecorder, and updates the relevant unit test call site.
Show a summary per file
File Description
test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs Updates a direct SendTestResults call to pass an ITestResultRecorder wrapper instead of a raw VSTest recorder.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestResultRecorderExtensions.cs Adds the single translation point from VSTest ITestExecutionRecorder to the platform-agnostic ITestResultRecorder.
src/Adapter/MSTestAdapter.PlatformServices/Interfaces/ITestResultRecorder.cs Introduces the new internal recorder interface used by PlatformServices to report execution lifecycle and results.
src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.Runner.cs Switches result reporting from direct VSTest result-type construction to the new recorder abstraction.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Low

Comment on lines +15 to +18
/// This abstraction lets the platform services layer report test start/end and results without taking a
/// dependency on a specific test platform's result object model (for example the VSTest <c>TestResult</c>,
/// <c>TestOutcome</c> and attachment types). The mapping to a concrete host recorder (for example the
/// VSTest <c>ITestExecutionRecorder</c>) is provided by the adapter layer.
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.

2 participants