diff --git a/src/Adapter/MSTestAdapter/Execution/TestExecutionManager.cs b/src/Adapter/MSTestAdapter/Execution/TestExecutionManager.cs index ce183cdb87..cf55868270 100644 --- a/src/Adapter/MSTestAdapter/Execution/TestExecutionManager.cs +++ b/src/Adapter/MSTestAdapter/Execution/TestExecutionManager.cs @@ -102,8 +102,11 @@ public void RunTests(IEnumerable sources, IRunContext runContext, IFrame var logger = (IMessageLogger)frameworkHandle; // discover the tests - (new UnitTestDiscoverer()).DiscoverTestsInSource(source, logger, discoverySink, runContext?.RunSettings); + this.GetUnitTestDiscoverer().DiscoverTestsInSource(source, logger, discoverySink, runContext?.RunSettings); tests.AddRange(discoverySink.Tests); + + //Clear discoverSinksTests so that it just stores test for one source at one point of time + discoverySink.Tests.Clear(); } bool isDeploymentDone = PlatformServiceProvider.Instance.TestDeployment.Deploy(tests, runContext, frameworkHandle); @@ -123,7 +126,7 @@ public void RunTests(IEnumerable sources, IRunContext runContext, IFrame /// /// Execute the parameter tests /// - private void ExecuteTests(IEnumerable tests, IRunContext runContext, IFrameworkHandle frameworkHandle, bool isDeploymentDone) + internal virtual void ExecuteTests(IEnumerable tests, IRunContext runContext, IFrameworkHandle frameworkHandle, bool isDeploymentDone) { var testsBySource = (from test in tests group test by test.Source into testGroup @@ -277,6 +280,11 @@ private void ExecuteTestsWithTestRunner( this.LogWarnings(testExecutionRecorder, warnings); } + internal virtual UnitTestDiscoverer GetUnitTestDiscoverer() + { + return new UnitTestDiscoverer(); + } + private void CacheSessionParameters(IRunContext runContext, ITestExecutionRecorder testExecutionRecorder) { if (!string.IsNullOrEmpty(runContext?.RunSettings?.SettingsXml)) diff --git a/src/Adapter/MSTestAdapter/MSTestDiscoverer.cs b/src/Adapter/MSTestAdapter/MSTestDiscoverer.cs index d0f6dcd250..8f4ec645f2 100644 --- a/src/Adapter/MSTestAdapter/MSTestDiscoverer.cs +++ b/src/Adapter/MSTestAdapter/MSTestDiscoverer.cs @@ -117,7 +117,7 @@ internal void DiscoverTests( /// The logger. /// The discovery Sink. /// The run settings. - internal void DiscoverTestsInSource( + internal virtual void DiscoverTestsInSource( string source, IMessageLogger logger, ITestCaseDiscoverySink discoverySink, diff --git a/test/UnitTests/MSTestAdapter.Tests/Discovery/UnitTestDiscovererTests.cs b/test/UnitTests/MSTestAdapter.Tests/Discovery/UnitTestDiscovererTests.cs index f269ab4933..7e8e758b42 100644 --- a/test/UnitTests/MSTestAdapter.Tests/Discovery/UnitTestDiscovererTests.cs +++ b/test/UnitTests/MSTestAdapter.Tests/Discovery/UnitTestDiscovererTests.cs @@ -261,4 +261,18 @@ public DummyNavigationData(string fileName, int minLineNumber, int maxLineNumber public int MaxLineNumber { get; set; } } + + internal class TestableUnitTestDiscoverer : UnitTestDiscoverer + { + internal override void DiscoverTestsInSource(string source, + IMessageLogger logger, + ITestCaseDiscoverySink discoverySink, + IRunSettings runSettings) + { + var testCase1 = new TestCase("A", new System.Uri("executor://testExecutor"), source); + var testCase2 = new TestCase("B", new System.Uri("executor://testExecutor"), source); + discoverySink.SendTestCase(testCase1); + discoverySink.SendTestCase(testCase2); + } + } } \ No newline at end of file diff --git a/test/UnitTests/MSTestAdapter.Tests/Execution/TestExecutionManagerTests.cs b/test/UnitTests/MSTestAdapter.Tests/Execution/TestExecutionManagerTests.cs index 8c8ba87964..9c25793a7a 100644 --- a/test/UnitTests/MSTestAdapter.Tests/Execution/TestExecutionManagerTests.cs +++ b/test/UnitTests/MSTestAdapter.Tests/Execution/TestExecutionManagerTests.cs @@ -23,6 +23,7 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Execution using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution; using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Discovery; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.TestableImplementations; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; @@ -352,6 +353,22 @@ public void RunTestsForSourceShouldPassInDeploymentInformationAsPropertiesToTheT Assert.IsNotNull(DummyTestClass.TestContextProperties); } + [TestMethodV1] + public void RunTestsForMultipleSourcesShouldRunEachTestJustOnce() + { + int testsCount = 0; + var sources = new List { Assembly.GetExecutingAssembly().Location, Assembly.GetExecutingAssembly().Location }; + TestableTestExecutionManager testableTestExecutionmanager = new TestableTestExecutionManager(); + + testableTestExecutionmanager.ExecuteTestsWrapper = (tests, runContext, frameworkHandle, isDeploymentDone) => + { + testsCount += tests.Count(); + }; + + testableTestExecutionmanager.RunTests(sources, this.runContext, this.frameworkHandle, this.cancellationToken); + Assert.AreEqual(testsCount, 4); + } + #endregion #region private methods @@ -567,6 +584,24 @@ public bool MatchTestCase(TestCase testCase, Func propertyValueP } } + internal class TestableTestExecutionManager : TestExecutionManager + { + internal override void ExecuteTests(IEnumerable tests, IRunContext runContext, + IFrameworkHandle frameworkHandle, bool isDeploymentDone) + { + if (this.ExecuteTestsWrapper != null) + { + this.ExecuteTestsWrapper.Invoke(tests, runContext, frameworkHandle, isDeploymentDone); + } + } + + internal override UnitTestDiscoverer GetUnitTestDiscoverer() + { + return new TestableUnitTestDiscoverer(); + } + + internal Action, IRunContext, IFrameworkHandle, bool> ExecuteTestsWrapper; + } #endregion } }