From 668335abc02abd9fd073e5c46d6c3223a1c914fa Mon Sep 17 00:00:00 2001 From: Amaury Leveque Date: Sun, 5 Jul 2026 12:03:37 +0200 Subject: [PATCH] Remove IFrameworkHandle from the PlatformServices execution engine (Phase 6e-1) The execution engine used the VSTest IFrameworkHandle exclusively to obtain an IAdapterMessageLogger via ToAdapterMessageLogger(). Replace the IFrameworkHandle parameter with the neutral IAdapterMessageLogger throughout TestExecutionManager (RunTestsAsync both overloads, ExecuteTestsAsync, ExecuteTestsInSourceAsync, Deploy); the adapter boundary (MSTestExecutor) now calls frameworkHandle.ToAdapterMessageLogger() once and injects the result. This removes the last VSTest ObjectModel.Adapter reference from the execution engine. No behavior change: the logger wrapper is stateless, so injecting one instance is identical to building one per call site. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../VSTestAdapter/MSTestExecutor.cs | 4 +- .../TestExecutionManager.Parallelization.cs | 15 ++--- .../Execution/TestExecutionManager.cs | 28 ++++---- .../Utilities/CLITestBase.discovery.cs | 4 +- .../Execution/TestExecutionManagerTests.cs | 66 +++++++++---------- 5 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs b/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs index 0db5ce45f8..f1fd235958 100644 --- a/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs +++ b/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs @@ -161,7 +161,7 @@ internal async Task RunTestsAsync(IEnumerable? tests, IRunContext? run // this boundary so the execution engine no longer depends on the VSTest run context. var deploymentContext = new DeploymentContext(runContext?.TestRunDirectory, runContext?.RunSettings?.SettingsXml); - await RunTestsFromRightContextAsync(frameworkHandle, async testRunToken => await TestExecutionManager.RunTestsAsync(testElements, deploymentContext, frameworkHandle, testResultRecorder, new TestElementFilterProvider(runContext), testRunToken).ConfigureAwait(false)).ConfigureAwait(false); + await RunTestsFromRightContextAsync(frameworkHandle, async testRunToken => await TestExecutionManager.RunTestsAsync(testElements, deploymentContext, frameworkHandle.ToAdapterMessageLogger(), testResultRecorder, new TestElementFilterProvider(runContext), testRunToken).ConfigureAwait(false)).ConfigureAwait(false); } finally { @@ -223,7 +223,7 @@ internal async Task RunTestsAsync(IEnumerable? sources, IRunContext? run // this boundary so the execution engine no longer depends on the VSTest run context. var deploymentContext = new DeploymentContext(runContext?.TestRunDirectory, runContext?.RunSettings?.SettingsXml); - await RunTestsFromRightContextAsync(frameworkHandle, async testRunToken => await TestExecutionManager.RunTestsAsync(sources, deploymentContext, frameworkHandle, testResultRecorder, new TestElementFilterProvider(runContext), testSourceHandler, isMTP, testRunToken).ConfigureAwait(false)).ConfigureAwait(false); + await RunTestsFromRightContextAsync(frameworkHandle, async testRunToken => await TestExecutionManager.RunTestsAsync(sources, deploymentContext, frameworkHandle.ToAdapterMessageLogger(), testResultRecorder, new TestElementFilterProvider(runContext), testSourceHandler, isMTP, testRunToken).ConfigureAwait(false)).ConfigureAwait(false); } finally { diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.Parallelization.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.Parallelization.cs index 379f5308b8..9f7b4ffdd3 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.Parallelization.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.Parallelization.cs @@ -6,7 +6,6 @@ using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Deployment; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface; -using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestTools.UnitTesting; using ExecutionScope = Microsoft.VisualStudio.TestTools.UnitTesting.ExecutionScope; @@ -20,16 +19,16 @@ internal partial class TestExecutionManager /// /// Tests to execute. /// Host-provided test-run directory and run settings XML. - /// Handle to record test start/end/results. + /// Logger used to report test messages back to the host. /// Recorder used to report test results back to the host. /// Provider for the test filter, or for no filter. /// Indicates if deployment is done. - internal virtual async Task ExecuteTestsAsync(IEnumerable tests, DeploymentContext deploymentContext, IFrameworkHandle frameworkHandle, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, bool isDeploymentDone) + internal virtual async Task ExecuteTestsAsync(IEnumerable tests, DeploymentContext deploymentContext, IAdapterMessageLogger messageLogger, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, bool isDeploymentDone) { _testResultRecorder = testResultRecorder; _testElementFilterProvider = filterProvider; - InitializeRandomTestOrder(frameworkHandle.ToAdapterMessageLogger()); + InitializeRandomTestOrder(messageLogger); var testsBySource = (from test in tests group test by test.TestMethod.AssemblyName into testGroup @@ -43,7 +42,7 @@ group test by test.TestMethod.AssemblyName into testGroup foreach (var group in testsBySource) { _testRunCancellationToken?.ThrowIfCancellationRequested(); - await ExecuteTestsInSourceAsync(group.Tests, deploymentContext, frameworkHandle, group.Source, isDeploymentDone).ConfigureAwait(false); + await ExecuteTestsInSourceAsync(group.Tests, deploymentContext, messageLogger, group.Source, isDeploymentDone).ConfigureAwait(false); } } @@ -52,10 +51,10 @@ group test by test.TestMethod.AssemblyName into testGroup /// /// Tests to execute. /// Host-provided test-run directory and run settings XML. - /// Handle to record test start/end/results. + /// Logger used to report test messages back to the host. /// The test container for the tests. /// Indicates if deployment is done. - private async Task ExecuteTestsInSourceAsync(IEnumerable tests, DeploymentContext deploymentContext, IFrameworkHandle frameworkHandle, string source, bool isDeploymentDone) + private async Task ExecuteTestsInSourceAsync(IEnumerable tests, DeploymentContext deploymentContext, IAdapterMessageLogger messageLogger, string source, bool isDeploymentDone) { DebugEx.Assert(!StringEx.IsNullOrEmpty(source), "Source cannot be empty"); @@ -66,7 +65,7 @@ private async Task ExecuteTestsInSourceAsync(IEnumerable tests, } #endif - IAdapterMessageLogger adapterMessageLogger = frameworkHandle.ToAdapterMessageLogger(); + IAdapterMessageLogger adapterMessageLogger = messageLogger; using ITestSourceHost isolationHost = PlatformServiceProvider.Instance.CreateTestSourceHost(source, deploymentContext.RunSettingsXml); bool usesAppDomains = isolationHost is TestSourceHost { UsesAppDomain: true }; diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.cs index f08ddb0a52..d8858cdaea 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.cs @@ -2,11 +2,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.ObjectModel; -using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Deployment; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Helpers; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface; -using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution; @@ -89,31 +87,31 @@ private static Task DefaultFactoryAsync(Func taskGetter) /// /// Tests to be run. /// Host-provided test-run directory and run settings XML. - /// Handle to the framework to record results and to do framework operations. + /// Logger used to report test messages back to the host. /// Recorder used to report test results back to the host. /// Provider for the test filter, or for no filter. /// Test run cancellation token. - internal async Task RunTestsAsync(IEnumerable tests, DeploymentContext deploymentContext, IFrameworkHandle frameworkHandle, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, TestRunCancellationToken runCancellationToken) + internal async Task RunTestsAsync(IEnumerable tests, DeploymentContext deploymentContext, IAdapterMessageLogger messageLogger, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, TestRunCancellationToken runCancellationToken) { DebugEx.Assert(tests != null, "tests"); DebugEx.Assert(deploymentContext != null, "deploymentContext"); - DebugEx.Assert(frameworkHandle != null, "frameworkHandle"); + DebugEx.Assert(messageLogger != null, "messageLogger"); DebugEx.Assert(runCancellationToken != null, "runCancellationToken"); _testRunCancellationToken = runCancellationToken; PlatformServiceProvider.Instance.TestRunCancellationToken = _testRunCancellationToken; #if !WINDOWS_UWP && !WIN_UI - bool isDeploymentDone = Deploy(tests, deploymentContext, frameworkHandle); + bool isDeploymentDone = Deploy(tests, deploymentContext, messageLogger); #else const bool isDeploymentDone = false; #endif // Placing this after deployment since we need information post deployment that we pass in as properties. - CacheSessionParameters(deploymentContext.RunSettingsXml, frameworkHandle.ToAdapterMessageLogger()); + CacheSessionParameters(deploymentContext.RunSettingsXml, messageLogger); // Execute the tests - await ExecuteTestsAsync(tests, deploymentContext, frameworkHandle, testResultRecorder, filterProvider, isDeploymentDone).ConfigureAwait(false); + await ExecuteTestsAsync(tests, deploymentContext, messageLogger, testResultRecorder, filterProvider, isDeploymentDone).ConfigureAwait(false); #if !WINDOWS_UWP && !WIN_UI if (!_hasAnyTestFailed) @@ -123,7 +121,7 @@ internal async Task RunTestsAsync(IEnumerable tests, Deployment #endif } - internal async Task RunTestsAsync(IEnumerable sources, DeploymentContext deploymentContext, IFrameworkHandle frameworkHandle, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, ITestSourceHandler testSourceHandler, bool isMTP, TestRunCancellationToken cancellationToken) + internal async Task RunTestsAsync(IEnumerable sources, DeploymentContext deploymentContext, IAdapterMessageLogger messageLogger, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, ITestSourceHandler testSourceHandler, bool isMTP, TestRunCancellationToken cancellationToken) { _testRunCancellationToken = cancellationToken; PlatformServiceProvider.Instance.TestRunCancellationToken = _testRunCancellationToken; @@ -132,7 +130,7 @@ internal async Task RunTestsAsync(IEnumerable sources, DeploymentContext var tests = new List(); - IAdapterMessageLogger logger = frameworkHandle.ToAdapterMessageLogger(); + IAdapterMessageLogger logger = messageLogger; // deploy everything first. foreach (string source in sources) @@ -148,16 +146,16 @@ internal async Task RunTestsAsync(IEnumerable sources, DeploymentContext } #if !WINDOWS_UWP && !WIN_UI - bool isDeploymentDone = Deploy(tests, deploymentContext, frameworkHandle); + bool isDeploymentDone = Deploy(tests, deploymentContext, messageLogger); #else const bool isDeploymentDone = false; #endif // Placing this after deployment since we need information post deployment that we pass in as properties. - CacheSessionParameters(deploymentContext.RunSettingsXml, frameworkHandle.ToAdapterMessageLogger()); + CacheSessionParameters(deploymentContext.RunSettingsXml, messageLogger); // Run tests. - await ExecuteTestsAsync(tests, deploymentContext, frameworkHandle, testResultRecorder, filterProvider, isDeploymentDone).ConfigureAwait(false); + await ExecuteTestsAsync(tests, deploymentContext, messageLogger, testResultRecorder, filterProvider, isDeploymentDone).ConfigureAwait(false); #if !WINDOWS_UWP && !WIN_UI if (!_hasAnyTestFailed) @@ -172,8 +170,8 @@ internal async Task RunTestsAsync(IEnumerable sources, DeploymentContext /// Runs deployment for the given tests via the platform-agnostic deployment service using the neutral /// supplied by the adapter boundary. /// - private static bool Deploy(IEnumerable tests, DeploymentContext deploymentContext, IFrameworkHandle frameworkHandle) - => PlatformServiceProvider.Instance.TestDeployment.Deploy(tests, deploymentContext, frameworkHandle.ToAdapterMessageLogger()); + private static bool Deploy(IEnumerable tests, DeploymentContext deploymentContext, IAdapterMessageLogger messageLogger) + => PlatformServiceProvider.Instance.TestDeployment.Deploy(tests, deploymentContext, messageLogger); #endif internal virtual UnitTestDiscoverer GetUnitTestDiscoverer(ITestSourceHandler testSourceHandler) => new(testSourceHandler); diff --git a/test/IntegrationTests/MSTest.IntegrationTests/Utilities/CLITestBase.discovery.cs b/test/IntegrationTests/MSTest.IntegrationTests/Utilities/CLITestBase.discovery.cs index f80f61eeba..40326955f6 100644 --- a/test/IntegrationTests/MSTest.IntegrationTests/Utilities/CLITestBase.discovery.cs +++ b/test/IntegrationTests/MSTest.IntegrationTests/Utilities/CLITestBase.discovery.cs @@ -42,7 +42,7 @@ internal static async Task> RunTestsAsync(IEnumerable var frameworkHandle = new InternalFrameworkHandle(); ITestResultRecorder testResultRecorder = frameworkHandle.ToTestResultRecorder(Environment.MachineName, MSTestSettings.CurrentSettings); - await testExecutionManager.ExecuteTestsAsync(ToUnitTestElements(testCases), new DeploymentContext(null, null), frameworkHandle, testResultRecorder, filterProvider: null, false); + await testExecutionManager.ExecuteTestsAsync(ToUnitTestElements(testCases), new DeploymentContext(null, null), frameworkHandle.ToAdapterMessageLogger(), testResultRecorder, filterProvider: null, false); return frameworkHandle.GetFlattenedTestResults(); } @@ -55,7 +55,7 @@ internal static async Task> RunTestsAsync(IEnumerable var runContext = new InternalRunContext(runSettingsXml, testCaseFilter); ITestResultRecorder testResultRecorder = frameworkHandle.ToTestResultRecorder(Environment.MachineName, MSTestSettings.CurrentSettings); - await testExecutionManager.ExecuteTestsAsync(ToUnitTestElements(testCases), new DeploymentContext(runContext.TestRunDirectory, runContext.RunSettings?.SettingsXml), frameworkHandle, testResultRecorder, new TestElementFilterProvider(runContext), false); + await testExecutionManager.ExecuteTestsAsync(ToUnitTestElements(testCases), new DeploymentContext(runContext.TestRunDirectory, runContext.RunSettings?.SettingsXml), frameworkHandle.ToAdapterMessageLogger(), testResultRecorder, new TestElementFilterProvider(runContext), false); return frameworkHandle.GetFlattenedTestResults(); } diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs index 12395a78d3..4e15c282a4 100644 --- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs +++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/TestExecutionManagerTests.cs @@ -107,7 +107,7 @@ public async Task RunTestsForTestWithFilterErrorShouldSendZeroResults() // Causing the FilterExpressionError _runContext = new TestableRunContextTestExecutionTests(() => throw new TestPlatformFormatException()); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); // No Results _frameworkHandle.TestCaseStartList.Count.Should().Be(0); @@ -123,7 +123,7 @@ public async Task RunTestsForTestWithFilterShouldSendResultsForFilteredTests() _runContext = new TestableRunContextTestExecutionTests(() => new TestableTestCaseFilterExpression(p => p.DisplayName == "PassingTest")); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); // FailingTest should be skipped because it does not match the filter criteria. List expectedTestCaseStartList = ["PassingTest"]; @@ -151,7 +151,7 @@ public async Task RunTestsForIgnoredTestShouldSendResultsMarkingIgnoredTestsAsSk TestCase testCase = GetTestCase(typeof(DummyTestClass), "IgnoredTest"); TestCase[] tests = [testCase]; - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); _frameworkHandle.TestCaseStartList[0].Should().Be("IgnoredTest"); _frameworkHandle.TestCaseEndList[0].Should().Be("IgnoredTest:Skipped"); @@ -164,7 +164,7 @@ public async Task RunTestsForASingleTestShouldSendSingleResult() TestCase[] tests = [testCase]; - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); List expectedTestCaseStartList = ["PassingTest"]; List expectedTestCaseEndList = ["PassingTest:Passed"]; @@ -181,7 +181,7 @@ public async Task RunTestsForMultipleTestShouldSendMultipleResults() TestCase failingTestCase = GetTestCase(typeof(DummyTestClass), "FailingTest"); TestCase[] tests = [testCase, failingTestCase]; - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); List expectedTestCaseStartList = ["PassingTest", "FailingTest"]; List expectedTestCaseEndList = ["PassingTest:Passed", "FailingTest:Failed"]; @@ -201,7 +201,7 @@ public async Task RunTestsForCancellationTokenCanceledSetToTrueShouldSendZeroRes // Cancel the test run _cancellationToken.Cancel(); - Func func = () => _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); + Func func = () => _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _cancellationToken); await func.Should().ThrowAsync(); // No Results @@ -224,7 +224,7 @@ public async Task RunTestsForTestShouldDeployBeforeExecution() await _testExecutionManager.RunTestsAsync( ToUnitTestElements(tests), CurrentDeploymentContext, - _frameworkHandle, + _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); _callers[0].Should().Be("Deploy", "Deploy should be called before execution."); @@ -245,7 +245,7 @@ public async Task RunTestsForTestShouldCleanupAfterExecution() td => td.Cleanup()).Callback(() => SetCaller("Cleanup")); #endif - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); _callers[0].Should().Be("LoadAssembly", "Cleanup should be called after execution."); @@ -262,7 +262,7 @@ public async Task RunTestsForTestShouldNotCleanupOnTestFailure() TestCase[] tests = [testCase, failingTestCase]; TestablePlatformServiceProvider testablePlatformService = SetupTestablePlatformService(); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); testablePlatformService.MockTestDeployment.Verify(td => td.Cleanup(), Times.Never); } @@ -281,7 +281,7 @@ public async Task RunTestsForTestShouldLoadSourceFromDeploymentDirectoryIfDeploy testablePlatformService.MockTestDeployment.Setup(td => td.GetDeploymentDirectory()) .Returns(@"C:\temp"); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); testablePlatformService.MockFileOperations.Verify( fo => fo.LoadAssembly(It.Is(s => s.StartsWith("C:\\temp"))), @@ -307,7 +307,7 @@ public async Task RunTestsForTestShouldPassInTestRunParametersInformationAsPrope """); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); DummyTestClass.TestContextProperties!.Contains( new KeyValuePair("webAppUrl", "http://localhost")).Should().BeTrue(); @@ -329,7 +329,7 @@ public async Task RunTestsForTestShouldPassInTcmPropertiesAsPropertiesToTheTest( """); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); VerifyTcmProperties(DummyTestClass.TestContextProperties, testCase); } @@ -342,7 +342,7 @@ public async Task RunTestsForTestShouldPassInDeploymentInformationAsPropertiesTo // Setup mocks. TestablePlatformServiceProvider testablePlatformService = SetupTestablePlatformService(); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); testablePlatformService.MockSettingsProvider.Verify(sp => sp.GetProperties(It.IsAny()), Times.Once); } @@ -366,7 +366,7 @@ public async Task RunTestsShouldClearSessionParametersAcrossRuns() """); // Trigger First Run - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); // Update runsettings to have different values for similar keys _runContext.MockRunSettings.Setup(rs => rs.SettingsXml).Returns( @@ -383,7 +383,7 @@ public async Task RunTestsShouldClearSessionParametersAcrossRuns() """); // Trigger another Run - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); "http://updatedLocalHost".Equals(DummyTestClass.TestContextProperties!["webAppUrl"]).Should().BeTrue(); } @@ -397,7 +397,7 @@ private async Task RunTestsForSourceShouldRunTestsInASource() { var sources = new List { Assembly.GetExecutingAssembly().Location }; - await _testExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); + await _testExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); _frameworkHandle.TestCaseStartList.Contains("PassingTest").Should().BeTrue(); _frameworkHandle.TestCaseEndList.Contains("PassingTest:Passed").Should().BeTrue(); @@ -419,7 +419,7 @@ private async Task RunTestsForSourceShouldPassInTestRunParametersInformationAsPr """); - await _testExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); + await _testExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); DummyTestClass.TestContextProperties!.Contains( new KeyValuePair("webAppUrl", "http://localhost")).Should().BeTrue(); @@ -430,7 +430,7 @@ private async Task RunTestsForSourceShouldPassInDeploymentInformationAsPropertie { var sources = new List { Assembly.GetExecutingAssembly().Location }; - await _testExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); + await _testExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); DummyTestClass.TestContextProperties.Should().NotBeNull(); } @@ -444,7 +444,7 @@ public async Task RunTestsForMultipleSourcesShouldRunEachTestJustOnce() ExecuteTestsWrapper = (tests, runContext, frameworkHandle, testResultRecorder, isDeploymentDone) => testsCount += tests.Count(), }; - await testableTestExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); + await testableTestExecutionManager.RunTestsAsync(sources, CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), _mockTestSourceHandler.Object, false, _cancellationToken); testsCount.Should().Be(4); } @@ -477,7 +477,7 @@ public async Task RunTestsForTestShouldRunTestsInParallelWhenEnabledInRunsetting try { MSTestSettings.PopulateSettings(_runContext.RunSettings?.SettingsXml, _mockMessageLogger.Object.ToAdapterMessageLogger(), null); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); DummyTestClassForParallelize.ThreadIds.Count.Should().Be(1); DummyTestClassForParallelize2.ThreadIds.Count.Should().Be(1); @@ -514,7 +514,7 @@ public async Task RunTestsForTestShouldRunTestsByMethodLevelWhenSpecified() try { MSTestSettings.PopulateSettings(_runContext.RunSettings?.SettingsXml, _mockMessageLogger.Object.ToAdapterMessageLogger(), null); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); _enqueuedParallelTestsCount.Should().Be(2); @@ -551,7 +551,7 @@ public async Task RunTestsForTestShouldRunTestsWithSpecifiedNumberOfWorkers() try { MSTestSettings.PopulateSettings(_runContext.RunSettings?.SettingsXml, _mockMessageLogger.Object.ToAdapterMessageLogger(), null); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); DummyTestClassForParallelize.ThreadIds.Count.Should().Be(1); DummyTestClassForParallelize2.ThreadIds.Count.Should().Be(1); @@ -614,7 +614,7 @@ public async Task RunTestsForTestShouldNotRunTestsInParallelWhenDisabledFromRuns testablePlatformService.MockReflectionOperations.Setup(fo => fo.GetRuntimeMethods(It.IsAny())) .Returns((Type t) => originalReflectionOperation.GetRuntimeMethods(t)); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); DummyTestClassForParallelize.ThreadIds.Count.Should().Be(1); } @@ -673,7 +673,7 @@ public async Task RunTestsForTestShouldNotRunTestsInParallelWhenDisabledFromSour testablePlatformService.MockReflectionOperations.Setup(fo => fo.GetRuntimeMethods(It.IsAny())) .Returns((Type t) => originalReflectionOperation.GetRuntimeMethods(t)); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); DummyTestClassForParallelize.ThreadIds.Count.Should().Be(1); } @@ -712,7 +712,7 @@ public async Task RunTestsForTestShouldRunNonParallelizableTestsSeparately() try { MSTestSettings.PopulateSettings(_runContext.RunSettings?.SettingsXml, _mockMessageLogger.Object.ToAdapterMessageLogger(), null); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); _enqueuedParallelTestsCount.Should().Be(2); DummyTestClassWithDoNotParallelizeMethods.ParallelizableTestsThreadIds.Count.Should().BeOneOf(1, 2); @@ -778,7 +778,7 @@ public async Task RunTestsForTestShouldPreferParallelSettingsFromRunSettingsOver testablePlatformService.MockReflectionOperations.Setup(fo => fo.GetRuntimeMethods(It.IsAny())) .Returns((Type t) => originalReflectionOperation.GetRuntimeMethods(t)); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); _enqueuedParallelTestsCount.Should().Be(2); @@ -818,7 +818,7 @@ private async Task RunTestsForTestShouldRunTestsInTheParentDomainsApartmentState try { MSTestSettings.PopulateSettings(_runContext.RunSettings?.SettingsXml, _mockMessageLogger.Object.ToAdapterMessageLogger(), null); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); DummyTestClassWithDoNotParallelizeMethods.ThreadApartmentStates.Count.Should().Be(1); DummyTestClassWithDoNotParallelizeMethods.ThreadApartmentStates.ToArray()[0].Should().Be(Thread.CurrentThread.GetApartmentState()); @@ -861,11 +861,11 @@ static TestCase[] BuildTests() => var firstHandle = new TestableFrameworkHandle(); var firstManager = new TestExecutionManager(task => task()); - await firstManager.RunTestsAsync(ToUnitTestElements(BuildTests()), CurrentDeploymentContext, firstHandle, firstHandle.ToTestResultRecorder(EnvironmentWrapper.Instance.MachineName, MSTestSettings.CurrentSettings), new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await firstManager.RunTestsAsync(ToUnitTestElements(BuildTests()), CurrentDeploymentContext, firstHandle.ToAdapterMessageLogger(), firstHandle.ToTestResultRecorder(EnvironmentWrapper.Instance.MachineName, MSTestSettings.CurrentSettings), new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); var secondHandle = new TestableFrameworkHandle(); var secondManager = new TestExecutionManager(task => task()); - await secondManager.RunTestsAsync(ToUnitTestElements(BuildTests()), CurrentDeploymentContext, secondHandle, secondHandle.ToTestResultRecorder(EnvironmentWrapper.Instance.MachineName, MSTestSettings.CurrentSettings), new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await secondManager.RunTestsAsync(ToUnitTestElements(BuildTests()), CurrentDeploymentContext, secondHandle.ToAdapterMessageLogger(), secondHandle.ToTestResultRecorder(EnvironmentWrapper.Instance.MachineName, MSTestSettings.CurrentSettings), new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); // Same seed must produce the same order across separate runs. firstHandle.TestCaseStartList.Should().Equal(secondHandle.TestCaseStartList); @@ -902,7 +902,7 @@ public async Task RunTestsWithoutRandomizeTestOrderShouldPreserveInputOrder() MSTestSettings.PopulateSettings(_runContext.RunSettings?.SettingsXml, _mockMessageLogger.Object.ToAdapterMessageLogger(), null); - await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle, TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); + await _testExecutionManager.RunTestsAsync(ToUnitTestElements(tests), CurrentDeploymentContext, _frameworkHandle.ToAdapterMessageLogger(), TestResultRecorder, new TestElementFilterProvider(_runContext), new TestRunCancellationToken()); _frameworkHandle.TestCaseStartList.Should().Equal("TestA", "TestB", "TestC"); } @@ -1278,11 +1278,11 @@ internal sealed class TestableTestCaseFilterExpression : ITestCaseFilterExpressi internal class TestableTestExecutionManager : TestExecutionManager { - internal Action, DeploymentContext, IFrameworkHandle, ITestResultRecorder, bool> ExecuteTestsWrapper { get; set; } = null!; + internal Action, DeploymentContext, IAdapterMessageLogger, ITestResultRecorder, bool> ExecuteTestsWrapper { get; set; } = null!; - internal override Task ExecuteTestsAsync(IEnumerable tests, DeploymentContext deploymentContext, IFrameworkHandle frameworkHandle, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, bool isDeploymentDone) + internal override Task ExecuteTestsAsync(IEnumerable tests, DeploymentContext deploymentContext, IAdapterMessageLogger messageLogger, ITestResultRecorder testResultRecorder, ITestElementFilterProvider? filterProvider, bool isDeploymentDone) { - ExecuteTestsWrapper?.Invoke(tests, deploymentContext, frameworkHandle, testResultRecorder, isDeploymentDone); + ExecuteTestsWrapper?.Invoke(tests, deploymentContext, messageLogger, testResultRecorder, isDeploymentDone); return Task.CompletedTask; }