diff --git a/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs b/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs
index c6350c762c..a0aa82b313 100644
--- a/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs
+++ b/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs
@@ -137,6 +137,11 @@ internal class RunSpecificTestsArgumentExecutor : IArgumentExecutor
///
private ITestDiscoveryEventsRegistrar discoveryEventsRegistrar;
+ ///
+ /// Registers and Unregisters for test run events before and after test run
+ ///
+ private ITestRunEventsRegistrar testRunEventsRegistrar;
+
#endregion
#region Constructor
@@ -159,6 +164,7 @@ internal class RunSpecificTestsArgumentExecutor : IArgumentExecutor
this.runSettingsManager = runSettingsProvider;
this.output = output;
this.discoveryEventsRegistrar = new DiscoveryEventsRegistrar(this.discoveryRequest_OnDiscoveredTests);
+ this.testRunEventsRegistrar = new TestRunRequestEventsRegistrar(this.output, this.commandLineOptions);
}
#endregion
@@ -259,7 +265,7 @@ private void ExecuteSelectedTests()
EqtTrace.Verbose("RunSpecificTestsArgumentProcessor:Execute: Test run is queued.");
var runRequestPayload = new TestRunRequestPayload() { TestCases = this.selectedTestCases.ToList(), RunSettings = this.effectiveRunSettings, KeepAlive = keepAlive, TestPlatformOptions = new TestPlatformOptions() { TestCaseFilter = this.commandLineOptions.TestCaseFilterValue }};
- this.testRequestManager.RunTests(runRequestPayload, null, null, Constants.DefaultProtocolConfig);
+ this.testRequestManager.RunTests(runRequestPayload, null, this.testRunEventsRegistrar, Constants.DefaultProtocolConfig);
}
else
{
@@ -335,5 +341,53 @@ public void UnregisterDiscoveryEvents(IDiscoveryRequest discoveryRequest)
discoveryRequest.OnDiscoveredTests -= this.discoveredTestsHandler;
}
}
+
+ private class TestRunRequestEventsRegistrar : ITestRunEventsRegistrar
+ {
+ private IOutput output;
+ private CommandLineOptions commandLineOptions;
+
+ public TestRunRequestEventsRegistrar(IOutput output, CommandLineOptions commandLineOptions)
+ {
+ this.output = output;
+ this.commandLineOptions = commandLineOptions;
+ }
+
+ public void LogWarning(string message)
+ {
+ ConsoleLogger.RaiseTestRunWarning(message);
+ }
+
+ public void RegisterTestRunEvents(ITestRunRequest testRunRequest)
+ {
+ testRunRequest.OnRunCompletion += TestRunRequest_OnRunCompletion;
+ }
+
+ public void UnregisterTestRunEvents(ITestRunRequest testRunRequest)
+ {
+ testRunRequest.OnRunCompletion -= TestRunRequest_OnRunCompletion;
+ }
+
+ ///
+ /// Handles the TestRunRequest complete event
+ ///
+ ///
+ /// RunCompletion args
+ private void TestRunRequest_OnRunCompletion(object sender, TestRunCompleteEventArgs e)
+ {
+ // If run is not aborted/cancelled then check the count of executed tests.
+ // we need to check if there are any tests executed - to try show some help info to user to check for installed vsix extensions
+ if (!e.IsAborted && !e.IsCanceled)
+ {
+ var testsFoundInAnySource = (e.TestRunStatistics == null) ? false : (e.TestRunStatistics.ExecutedTests > 0);
+
+ // Indicate the user to use testadapterpath command if there are no tests found
+ if (!testsFoundInAnySource && string.IsNullOrEmpty(CommandLineOptions.Instance.TestAdapterPath) && this.commandLineOptions.TestCaseFilterValue == null)
+ {
+ this.output.Warning(false, CommandLineResources.SuggestTestAdapterPathIfNoTestsIsFound);
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
index 1e8cd30055..109479fa63 100644
--- a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
+++ b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
@@ -435,7 +435,7 @@ private void CheckSourcesForCompatibility(Framework chosenFramework, Architectur
if (!string.IsNullOrEmpty(incompatibleSettingWarning))
{
EqtTrace.Warning(incompatibleSettingWarning);
- registrar.LogWarning(incompatibleSettingWarning);
+ registrar?.LogWarning(incompatibleSettingWarning);
}
// Log compatible sources
diff --git a/test/Microsoft.TestPlatform.AcceptanceTests/FrameworkTests.cs b/test/Microsoft.TestPlatform.AcceptanceTests/FrameworkTests.cs
index fd7dbb729a..2fa5b9823e 100644
--- a/test/Microsoft.TestPlatform.AcceptanceTests/FrameworkTests.cs
+++ b/test/Microsoft.TestPlatform.AcceptanceTests/FrameworkTests.cs
@@ -50,5 +50,29 @@ public void OnWrongFrameworkPassedTestRunShouldNotRun(RunnerInfo runnerInfo)
this.StdErrorContains("Test Run Aborted.");
}
}
+
+ [TestMethod]
+ [NetFullTargetFrameworkDataSource]
+ [NetCoreTargetFrameworkDataSource]
+ public void RunSpecificTestsShouldWorkWithFrameworkInCompatibleWarning(RunnerInfo runnerInfo)
+ {
+ AcceptanceTestBase.SetTestEnvironment(this.testEnvironment, runnerInfo);
+
+ var arguments = PrepareArguments(GetSampleTestAssembly(), string.Empty, string.Empty, this.FrameworkArgValue);
+ arguments = string.Concat(arguments, " ", "/tests:PassingTest");
+ arguments = string.Concat(arguments, " ", "/Framework:Framework40");
+
+ this.InvokeVsTest(arguments);
+
+ if (runnerInfo.TargetFramework.Contains("netcore"))
+ {
+ this.StdOutputContains("No test is available");
+ }
+ else
+ {
+ this.StdOutputContains("Following DLL(s) do not match framework/platform settings. ");
+ this.ValidateSummaryStatus(1, 0, 0);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs
index fb417c54d4..a569d331c9 100644
--- a/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs
+++ b/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs
@@ -482,6 +482,64 @@ public void ExecutorShouldRunTestsWhenTestsAreCommaSeparatedWithEscape()
Assert.AreEqual(ArgumentProcessorResult.Success, argumentProcessorResult);
}
+ [TestMethod]
+ public void ExecutorShouldDisplayWarningIfNoTestsAreExecuted()
+ {
+ var mockTestPlatform = new Mock();
+ var mockTestRunRequest = new Mock();
+ var mockDiscoveryRequest = new Mock();
+ var mockTestRunStats = new Mock();
+
+ List list = new List();
+ list.Add(new TestCase("Test1", new Uri("http://FooTestUri1"), "Source1"));
+ list.Add(new TestCase("Test2", new Uri("http://FooTestUri2"), "Source2"));
+ mockDiscoveryRequest.Setup(dr => dr.DiscoverAsync()).Raises(dr => dr.OnDiscoveredTests += null, new DiscoveredTestsEventArgs(list));
+
+ mockTestRunRequest.Setup(tr => tr.ExecuteAsync()).Returns(1).Raises(tr => tr.OnRunCompletion += null,
+ new TestRunCompleteEventArgs(mockTestRunStats.Object, false, false, null, null, new TimeSpan()));
+
+ mockTestPlatform.Setup(tp => tp.CreateTestRunRequest(It.IsAny(), It.IsAny(), It.IsAny())).Returns(mockTestRunRequest.Object);
+ mockTestPlatform.Setup(tp => tp.CreateDiscoveryRequest(It.IsAny(), It.IsAny(), It.IsAny())).Returns(mockDiscoveryRequest.Object);
+
+ this.ResetAndAddSourceToCommandLineOptions();
+ var testRequestManager = new TestRequestManager(CommandLineOptions.Instance, mockTestPlatform.Object, TestRunResultAggregator.Instance, this.mockTestPlatformEventSource.Object, this.inferHelper, this.mockMetricsPublisherTask);
+ var executor = GetExecutor(testRequestManager);
+
+ executor.Initialize("Test1");
+ executor.Execute();
+
+ this.mockOutput.Verify(op => op.WriteLine(It.Is(st => st.Contains("Additionally, path to test adapters can be specified using /TestAdapterPath command.")), OutputLevel.Warning), Times.Once);
+ }
+
+ [TestMethod]
+ public void ExecutorShouldNotDisplayWarningIfTestsAreExecuted()
+ {
+ var mockTestPlatform = new Mock();
+ var mockTestRunRequest = new Mock();
+ var mockDiscoveryRequest = new Mock();
+ var testRunStats = new TestRunStatistics(1, new Dictionary { { TestOutcome.Passed, 1 } });
+
+ List list = new List();
+ list.Add(new TestCase("Test1", new Uri("http://FooTestUri1"), "Source1"));
+ list.Add(new TestCase("Test2", new Uri("http://FooTestUri2"), "Source2"));
+ mockDiscoveryRequest.Setup(dr => dr.DiscoverAsync()).Raises(dr => dr.OnDiscoveredTests += null, new DiscoveredTestsEventArgs(list));
+
+ mockTestRunRequest.Setup(tr => tr.ExecuteAsync()).Returns(1).Raises(tr => tr.OnRunCompletion += null,
+ new TestRunCompleteEventArgs(testRunStats, false, false, null, null, new TimeSpan()));
+
+ mockTestPlatform.Setup(tp => tp.CreateTestRunRequest(It.IsAny(), It.IsAny(), It.IsAny())).Returns(mockTestRunRequest.Object);
+ mockTestPlatform.Setup(tp => tp.CreateDiscoveryRequest(It.IsAny(), It.IsAny(), It.IsAny())).Returns(mockDiscoveryRequest.Object);
+
+ this.ResetAndAddSourceToCommandLineOptions();
+ var testRequestManager = new TestRequestManager(CommandLineOptions.Instance, mockTestPlatform.Object, TestRunResultAggregator.Instance, this.mockTestPlatformEventSource.Object, this.inferHelper, this.mockMetricsPublisherTask);
+ var executor = GetExecutor(testRequestManager);
+
+ executor.Initialize("Test1");
+ executor.Execute();
+
+ this.mockOutput.Verify(op => op.WriteLine(It.Is(st => st.Contains("Additionally, path to test adapters can be specified using /TestAdapterPath command.")), OutputLevel.Warning), Times.Never);
+ }
+
#endregion
private void ResetAndAddSourceToCommandLineOptions()