diff --git a/TestPlatform.sln b/TestPlatform.sln index b4b03614bd..5824a83e66 100644 --- a/TestPlatform.sln +++ b/TestPlatform.sln @@ -170,7 +170,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AttachVS", "src\AttachVS\At EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "playground", "playground", "{6CE2F530-582B-4695-A209-41065E103426}" ProjectSection(SolutionItems) = preProject - README.md = README.md + playground\README.md = playground\README.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlatform.Playground", "playground\TestPlatform.Playground\TestPlatform.Playground.csproj", "{545A88D3-1AE2-4D39-9B7C-C691768AD17F}" diff --git a/src/Microsoft.TestPlatform.Client/TestPlatform.cs b/src/Microsoft.TestPlatform.Client/TestPlatform.cs index 9d3115d4a8..2676096fdd 100644 --- a/src/Microsoft.TestPlatform.Client/TestPlatform.cs +++ b/src/Microsoft.TestPlatform.Client/TestPlatform.cs @@ -12,24 +12,24 @@ namespace Microsoft.VisualStudio.TestPlatform.Client; using System.Linq; using System.Reflection; -using Discovery; -using Execution; -using Common; -using Common.ExtensionFramework; -using Common.Hosting; -using Common.Logging; +using Microsoft.VisualStudio.TestPlatform.Client.Discovery; +using Microsoft.VisualStudio.TestPlatform.Client.Execution; +using Microsoft.VisualStudio.TestPlatform.Common; +using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; +using Microsoft.VisualStudio.TestPlatform.Common.Hosting; +using Microsoft.VisualStudio.TestPlatform.Common.Logging; using Microsoft.VisualStudio.TestPlatform.Common.Utilities; -using CrossPlatEngine; -using ObjectModel; +using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; -using ObjectModel.Engine; -using ObjectModel.Host; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; -using PlatformAbstractions; -using Utilities.Helpers; -using Utilities.Helpers.Interfaces; +using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; -using ClientResources = Resources.Resources; +using ClientResources = Microsoft.VisualStudio.TestPlatform.Client.Resources.Resources; /// /// Implementation for TestPlatform. @@ -87,27 +87,18 @@ public IDiscoveryRequest CreateDiscoveryRequest( DiscoveryCriteria discoveryCriteria!!, TestPlatformOptions options) { - - // Update cache with Extension folder's files. - AddExtensionAssemblies(discoveryCriteria.RunSettings); - - // Update extension assemblies from source when design mode is false. - var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(discoveryCriteria.RunSettings); - if (!runConfiguration.DesignMode) - { - AddExtensionAssembliesFromSource(discoveryCriteria.Sources); - } + PopulateExtensions(discoveryCriteria.RunSettings, discoveryCriteria.Sources); // Initialize loggers. - var loggerManager = TestEngine.GetLoggerManager(requestData); + ITestLoggerManager loggerManager = TestEngine.GetLoggerManager(requestData); loggerManager.Initialize(discoveryCriteria.RunSettings); - var testHostManager = _testHostProviderManager.GetTestHostManagerByRunConfiguration(discoveryCriteria.RunSettings); - ThrowExceptionIfTestHostManagerIsNull(testHostManager, discoveryCriteria.RunSettings); + ITestRuntimeProvider testHostManager = _testHostProviderManager.GetTestHostManagerByRunConfiguration(discoveryCriteria.RunSettings); + TestPlatform.ThrowExceptionIfTestHostManagerIsNull(testHostManager, discoveryCriteria.RunSettings); testHostManager.Initialize(TestSessionMessageLogger.Instance, discoveryCriteria.RunSettings); - var discoveryManager = TestEngine.GetDiscoveryManager(requestData, testHostManager, discoveryCriteria); + IProxyDiscoveryManager discoveryManager = TestEngine.GetDiscoveryManager(requestData, testHostManager, discoveryCriteria); discoveryManager.Initialize(options?.SkipDefaultAdapters ?? false); return new DiscoveryRequest(requestData, discoveryCriteria, discoveryManager, loggerManager); @@ -119,22 +110,15 @@ public ITestRunRequest CreateTestRunRequest( TestRunCriteria testRunCriteria!!, TestPlatformOptions options) { - AddExtensionAssemblies(testRunCriteria.TestRunSettings); - - var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(testRunCriteria.TestRunSettings); - - // Update extension assemblies from source when design mode is false. - if (!runConfiguration.DesignMode) - { - AddExtensionAssembliesFromSource(testRunCriteria); - } + IEnumerable sources = GetSources(testRunCriteria); + PopulateExtensions(testRunCriteria.TestRunSettings, sources); // Initialize loggers. - var loggerManager = TestEngine.GetLoggerManager(requestData); + ITestLoggerManager loggerManager = TestEngine.GetLoggerManager(requestData); loggerManager.Initialize(testRunCriteria.TestRunSettings); - var testHostManager = _testHostProviderManager.GetTestHostManagerByRunConfiguration(testRunCriteria.TestRunSettings); - ThrowExceptionIfTestHostManagerIsNull(testHostManager, testRunCriteria.TestRunSettings); + ITestRuntimeProvider testHostManager = _testHostProviderManager.GetTestHostManagerByRunConfiguration(testRunCriteria.TestRunSettings); + TestPlatform.ThrowExceptionIfTestHostManagerIsNull(testHostManager, testRunCriteria.TestRunSettings); testHostManager.Initialize(TestSessionMessageLogger.Instance, testRunCriteria.TestRunSettings); @@ -144,7 +128,7 @@ public ITestRunRequest CreateTestRunRequest( testHostManager.SetCustomLauncher(testRunCriteria.TestHostLauncher); } - var executionManager = TestEngine.GetExecutionManager(requestData, testHostManager, testRunCriteria); + IProxyExecutionManager executionManager = TestEngine.GetExecutionManager(requestData, testHostManager, testRunCriteria); executionManager.Initialize(options?.SkipDefaultAdapters ?? false); return new TestRunRequest(requestData, testRunCriteria, executionManager, loggerManager); @@ -156,15 +140,17 @@ public bool StartTestSession( StartTestSessionCriteria testSessionCriteria!!, ITestSessionEventsHandler eventsHandler) { - AddExtensionAssemblies(testSessionCriteria.RunSettings); + RunConfiguration runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(testSessionCriteria.RunSettings); + TestAdapterLoadingStrategy strategy = runConfiguration.TestAdapterLoadingStrategy; + + AddExtensionAssemblies(testSessionCriteria.RunSettings, strategy); - var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(testSessionCriteria.RunSettings); if (!runConfiguration.DesignMode) { return false; } - var testSessionManager = TestEngine.GetTestSessionManager(requestData, testSessionCriteria); + IProxyTestSessionManager testSessionManager = TestEngine.GetTestSessionManager(requestData, testSessionCriteria); if (testSessionManager == null) { // The test session manager is null because the combination of runsettings and @@ -178,6 +164,21 @@ public bool StartTestSession( return testSessionManager.StartSession(eventsHandler, requestData); } + private void PopulateExtensions(string runSettings, IEnumerable sources) + { + RunConfiguration runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runSettings); + TestAdapterLoadingStrategy strategy = runConfiguration.TestAdapterLoadingStrategy; + + // Update cache with Extension folder's files. + AddExtensionAssemblies(runSettings, strategy); + + // Update extension assemblies from source when design mode is false. + if (!runConfiguration.DesignMode) + { + AddLoggerAssembliesFromSource(sources, strategy); + } + } + /// /// The dispose. /// @@ -200,24 +201,19 @@ public void ClearExtensions() TestEngine.GetExtensionManager().ClearExtensions(); } - private void ThrowExceptionIfTestHostManagerIsNull( + private static void ThrowExceptionIfTestHostManagerIsNull( ITestRuntimeProvider testHostManager, string settingsXml) { if (testHostManager == null) { - EqtTrace.Error("TestPlatform.CreateTestRunRequest: No suitable testHostProvider found for runsettings : {0}", settingsXml); + EqtTrace.Error($"{nameof(TestPlatform)}.{nameof(ThrowExceptionIfTestHostManagerIsNull)}: No suitable testHostProvider found for runsettings: {settingsXml}"); throw new TestPlatformException(string.Format(CultureInfo.CurrentCulture, ClientResources.NoTestHostProviderFound)); } } - /// - /// Updates the test adapter paths provided through run settings to be used by the test - /// service. - /// - /// - /// The run settings. - private void AddExtensionAssemblies(string runSettings) + + private void AddExtensionAssemblies(string runSettings, TestAdapterLoadingStrategy adapterLoadingStrategy) { IEnumerable customTestAdaptersPaths = RunSettingsUtilities.GetTestAdaptersPaths(runSettings); @@ -225,67 +221,44 @@ private void AddExtensionAssemblies(string runSettings) { foreach (string customTestAdaptersPath in customTestAdaptersPaths) { - var adapterPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(customTestAdaptersPath)); - if (!Directory.Exists(adapterPath)) - { - EqtTrace.Warning($"AdapterPath Not Found: {adapterPath}"); - continue; - } + IEnumerable extensionAssemblies = ExpandTestAdapterPaths(customTestAdaptersPath, _fileHelper, adapterLoadingStrategy); - var extensionAssemblies = new List( - _fileHelper.EnumerateFiles( - adapterPath, - SearchOption.AllDirectories, - TestPlatformConstants.TestAdapterEndsWithPattern, - TestPlatformConstants.TestLoggerEndsWithPattern, - TestPlatformConstants.DataCollectorEndsWithPattern, - TestPlatformConstants.RunTimeEndsWithPattern)); - - if (extensionAssemblies.Count > 0) + if (extensionAssemblies.Any()) { UpdateExtensions(extensionAssemblies, skipExtensionFilters: false); } + } } } /// - /// Updates the extension assemblies from source directory. + /// Updates the test logger paths from source directory. /// /// - /// The test run criteria. - private void AddExtensionAssembliesFromSource(TestRunCriteria testRunCriteria) + /// The list of sources. + private void AddLoggerAssembliesFromSource(IEnumerable sources, TestAdapterLoadingStrategy strategy) { - IEnumerable sources = testRunCriteria.Sources; - if (testRunCriteria.HasSpecificTests) + // Skip discovery unless we're using the default behavior, or NextToSource is specified. + if (strategy != TestAdapterLoadingStrategy.Default && strategy.HasFlag(TestAdapterLoadingStrategy.NextToSource)) { - // If the test execution is with a test filter, group them by sources. - sources = testRunCriteria.Tests.Select(tc => tc.Source).Distinct(); + return; } - AddExtensionAssembliesFromSource(sources); - } - - /// - /// Updates the test logger paths from source directory. - /// - /// - /// The list of sources. - private void AddExtensionAssembliesFromSource(IEnumerable sources) - { // Currently we support discovering loggers only from Source directory. - var loggersToUpdate = new List(); + List loggersToUpdate = new(); - foreach (var source in sources) + foreach (string source in sources) { - var sourceDirectory = Path.GetDirectoryName(source); - if (!string.IsNullOrEmpty(sourceDirectory) - && _fileHelper.DirectoryExists(sourceDirectory)) + string sourceDirectory = Path.GetDirectoryName(source); + if (!string.IsNullOrEmpty(sourceDirectory) && _fileHelper.DirectoryExists(sourceDirectory)) { + SearchOption searchOption = GetSearchOption(strategy, SearchOption.TopDirectoryOnly); + loggersToUpdate.AddRange( _fileHelper.EnumerateFiles( sourceDirectory, - SearchOption.TopDirectoryOnly, + searchOption, TestPlatformConstants.TestLoggerEndsWithPattern)); } } @@ -303,21 +276,127 @@ private void AddExtensionAssembliesFromSource(IEnumerable sources) /// private static void AddExtensionAssembliesFromExtensionDirectory() { - var fileHelper = new FileHelper(); - var extensionsFolder = Path.Combine( - Path.GetDirectoryName( - typeof(TestPlatform).GetTypeInfo().Assembly.GetAssemblyLocation()), - "Extensions"); + // This method needs to run statically before we have any adapter discovery. + // TestHostProviderManager get initialized just after this call and it + // requires DefaultExtensionPaths to be set to resolve a TestHostProvider. + // Since it's static, it forces us to set the adapter paths. + // + // Otherwise we will always get a "No suitable test runtime provider found for this run." error. + // I (@haplois) will modify this behavior later on, but we also need to consider legacy adapters + // and make sure they still work after modification. + string runSettings = RunSettingsManager.Instance.ActiveRunSettings.SettingsXml; + RunConfiguration runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runSettings); + TestAdapterLoadingStrategy strategy = runConfiguration.TestAdapterLoadingStrategy; + + FileHelper fileHelper = new(); + IEnumerable defaultExtensionPaths = Enumerable.Empty(); + + // Explicit adapter loading + if (strategy.HasFlag(TestAdapterLoadingStrategy.Explicit)) + { + defaultExtensionPaths = RunSettingsUtilities.GetTestAdaptersPaths(runSettings) + .SelectMany(path => ExpandTestAdapterPaths(path, fileHelper, strategy)) + .Union(defaultExtensionPaths); + } + string extensionsFolder = Path.Combine(Path.GetDirectoryName(typeof(TestPlatform).GetTypeInfo().Assembly.GetAssemblyLocation()), "Extensions"); if (fileHelper.DirectoryExists(extensionsFolder)) { - var defaultExtensionPaths = fileHelper.EnumerateFiles( - extensionsFolder, - SearchOption.TopDirectoryOnly, - ".dll", - ".exe"); + // Load default runtime providers + if (strategy.HasFlag(TestAdapterLoadingStrategy.DefaultRuntimeProviders)) + { + defaultExtensionPaths = fileHelper + .EnumerateFiles(extensionsFolder, SearchOption.TopDirectoryOnly, TestPlatformConstants.RunTimeEndsWithPattern) + .Union(defaultExtensionPaths); + } - TestPluginCache.Instance.DefaultExtensionPaths = defaultExtensionPaths; + // Default extension loader + if (strategy == TestAdapterLoadingStrategy.Default || strategy.HasFlag(TestAdapterLoadingStrategy.ExtensionsDirectory)) + { + defaultExtensionPaths = fileHelper + .EnumerateFiles(extensionsFolder, SearchOption.TopDirectoryOnly, ".dll", ".exe") + .Union(defaultExtensionPaths); + } } + + TestPluginCache.Instance.DefaultExtensionPaths = defaultExtensionPaths.Distinct(); } + + private static SearchOption GetSearchOption(TestAdapterLoadingStrategy strategy, SearchOption defaultStrategyOption) + { + return strategy == TestAdapterLoadingStrategy.Default + ? defaultStrategyOption + : strategy.HasFlag(TestAdapterLoadingStrategy.Recursive) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + } + + private static IEnumerable ExpandTestAdapterPaths(string path, IFileHelper fileHelper, TestAdapterLoadingStrategy strategy) + { + string adapterPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(path)); + + // Default behavior is to only accept directories. + if (strategy == TestAdapterLoadingStrategy.Default) + { + return ExpandAdaptersWithDefaultStrategy(adapterPath, fileHelper); + } + + IEnumerable adapters = ExpandAdaptersWithExplicitStrategy(adapterPath, fileHelper, strategy); + + return adapters.Distinct(); + } + + private static IEnumerable ExpandAdaptersWithExplicitStrategy(string path, IFileHelper fileHelper, TestAdapterLoadingStrategy strategy) + { + if (strategy.HasFlag(TestAdapterLoadingStrategy.Explicit)) + { + return Enumerable.Empty(); + } + + if (fileHelper.Exists(path)) + { + return new[] { path }; + } + else if (fileHelper.DirectoryExists(path)) + { + SearchOption searchOption = GetSearchOption(strategy, SearchOption.TopDirectoryOnly); + + IEnumerable adapterPaths = fileHelper.EnumerateFiles( + path, + searchOption, + TestPlatformConstants.TestAdapterEndsWithPattern, + TestPlatformConstants.TestLoggerEndsWithPattern, + TestPlatformConstants.DataCollectorEndsWithPattern, + TestPlatformConstants.RunTimeEndsWithPattern); + + return adapterPaths; + } + + EqtTrace.Warning($"{nameof(TestPlatform)}.{nameof(ExpandAdaptersWithExplicitStrategy)} AdapterPath Not Found: {path}"); + return Enumerable.Empty(); + } + + private static IEnumerable ExpandAdaptersWithDefaultStrategy(string path, IFileHelper fileHelper) + { + // This is the legacy behavior, please do not modify this method unless you're sure of + // side effect when running tests with legacy adapters. + if (!fileHelper.DirectoryExists(path)) + { + EqtTrace.Warning($"{nameof(TestPlatform)}.{nameof(ExpandAdaptersWithDefaultStrategy)} AdapterPath Not Found: {path}"); + + return Enumerable.Empty(); + } + + return fileHelper.EnumerateFiles( + path, + SearchOption.AllDirectories, + TestPlatformConstants.TestAdapterEndsWithPattern, + TestPlatformConstants.TestLoggerEndsWithPattern, + TestPlatformConstants.DataCollectorEndsWithPattern, + TestPlatformConstants.RunTimeEndsWithPattern); + } + + private static IEnumerable GetSources(TestRunCriteria testRunCriteria) => + testRunCriteria.HasSpecificTests + // If the test execution is with a test filter, filter sources too. + ? testRunCriteria.Tests.Select(tc => tc.Source).Distinct() + : testRunCriteria.Sources; } diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/DataCollectionExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/DataCollectionExtensionManager.cs index f9f1b727b1..8900da5b8e 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/DataCollectionExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/DataCollectionExtensionManager.cs @@ -53,7 +53,7 @@ protected DataCollectorExtensionManager( /// public static DataCollectorExtensionManager Create(IMessageLogger messageLogger) { - TestPluginManager.Instance.GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.DataCollectorEndsWithPattern, out var unfilteredTestExtensions, out var filteredTestExtensions); @@ -78,7 +78,7 @@ public static DataCollectorExtensionManager Create(IMessageLogger messageLogger) /// public static DataCollectorExtensionManager Create(string extensionAssemblyFilePath, bool skipCache, IMessageLogger messageLogger) { - TestPluginManager.Instance.GetTestExtensions( + TestPluginManager.GetTestExtensions( extensionAssemblyFilePath, out var unfilteredTestExtensions, out var filteredTestExtensions, diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs index b15c48f77c..7c8dd21d9f 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs @@ -64,8 +64,7 @@ public static TestDiscoveryExtensionManager Create() if (s_testDiscoveryExtensionManager == null) { - TestPluginManager.Instance - .GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out var unfilteredTestExtensions, out var testExtensions); @@ -90,8 +89,7 @@ public static TestDiscoveryExtensionManager Create() public static TestDiscoveryExtensionManager GetDiscoveryExtensionManager(string extensionAssembly) { - TestPluginManager.Instance - .GetTestExtensions( + TestPluginManager.GetTestExtensions( extensionAssembly, out var unfilteredTestExtensions, out var testExtensions); diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs index 524fc3ff71..6e431591c4 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs @@ -107,15 +107,13 @@ internal static TestExecutorExtensionManager Create() { // Get all extensions for ITestExecutor. - TestPluginManager.Instance - .GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out var unfilteredTestExtensions1, out var testExtensions1); // Get all extensions for ITestExecutor2. - TestPluginManager.Instance - .GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out var unfilteredTestExtensions2, out var testExtensions2); @@ -152,15 +150,13 @@ internal static TestExecutorExtensionManager GetExecutionExtensionManager(string { // Get all extensions for ITestExecutor. - TestPluginManager.Instance - .GetTestExtensions( + TestPluginManager.GetTestExtensions( extensionAssembly, out var unfilteredTestExtensions1, out var testExtensions1); // Get all extensions for ITestExecutor2. - TestPluginManager.Instance - .GetTestExtensions( + TestPluginManager.GetTestExtensions( extensionAssembly, out var unfilteredTestExtensions2, out var testExtensions2); diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExtensionManager.cs index f1be92a674..5f12dd7afa 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExtensionManager.cs @@ -128,6 +128,7 @@ public LazyExtension TryGetTestExtension(string extension break; } } + return testExtension; } diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestLoggerExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestLoggerExtensionManager.cs index b5fb7b5770..fc5df639bf 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestLoggerExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestLoggerExtensionManager.cs @@ -53,7 +53,7 @@ protected TestLoggerExtensionManager( public static TestLoggerExtensionManager Create(IMessageLogger messageLogger) { - TestPluginManager.Instance.GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestLoggerEndsWithPattern, out IEnumerable>> unfilteredTestExtensions, out IEnumerable> filteredTestExtensions); diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs index f89092aaa3..8e3982d41b 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs @@ -107,13 +107,13 @@ public static T CreateTestExtension(Type extensionType!!) /// /// Receives test extensions filtered by Identifier data /// - public void GetSpecificTestExtensions( + public static void GetSpecificTestExtensions( string endsWithPattern, out IEnumerable>> unfiltered, out IEnumerable> filtered) where TMetadata : IMetadata where TPluginInfo : TestPluginInformation { var extensions = TestPluginCache.Instance.DiscoverTestExtensions(endsWithPattern); - GetExtensions(extensions, out unfiltered, out filtered); + TestPluginManager.GetExtensions(extensions, out unfiltered, out filtered); } /// @@ -142,14 +142,14 @@ public void GetSpecificTestExtensions /// Skip the extensions cache. /// - public void GetTestExtensions( + public static void GetTestExtensions( string extensionAssembly, out IEnumerable>> unfiltered, out IEnumerable> filtered, bool skipCache = false) where TMetadata : IMetadata where TPluginInfo : TestPluginInformation { var extensions = TestPluginCache.Instance.GetTestExtensions(extensionAssembly, skipCache); - GetExtensions(extensions, out unfiltered, out filtered); + TestPluginManager.GetExtensions(extensions, out unfiltered, out filtered); } /// @@ -158,7 +158,7 @@ public void GetTestExtensions( /// Type of TestPluginIInformation. /// The dictionary containing plugin identifier data and its info. /// Collection of test plugins information - private IEnumerable GetValuesFromDictionary(Dictionary dictionary) where T : TestPluginInformation + private static IEnumerable GetValuesFromDictionary(Dictionary dictionary) where T : TestPluginInformation { var values = new List(); @@ -193,7 +193,7 @@ private IEnumerable GetValuesFromDictionary(Dictionary /// /// Receives test extensions filtered by Identifier data /// - private void GetExtensions( + private static void GetExtensions( Dictionary testPluginInfo, out IEnumerable>> unfiltered, out IEnumerable> filtered) where TMetadata : IMetadata where TPluginInfo : TestPluginInformation @@ -201,7 +201,7 @@ private void GetExtensions( var unfilteredExtensions = new List>>(); var filteredExtensions = new List>(); - var testPlugins = GetValuesFromDictionary(testPluginInfo); + var testPlugins = TestPluginManager.GetValuesFromDictionary(testPluginInfo); foreach (var plugin in testPlugins) { if (!string.IsNullOrEmpty(plugin.IdentifierData)) diff --git a/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs b/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs index de3809caca..7372fb487c 100644 --- a/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs @@ -54,7 +54,7 @@ protected TestRuntimeExtensionManager( /// public static TestRuntimeExtensionManager Create(IMessageLogger messageLogger) { - TestPluginManager.Instance.GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.RunTimeEndsWithPattern, out IEnumerable>> unfilteredTestExtensions, out IEnumerable> filteredTestExtensions); diff --git a/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs b/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs index 809b84936a..8c7a8cccf1 100644 --- a/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs @@ -106,8 +106,7 @@ public static SettingsProviderExtensionManager Create() if (s_settingsProviderExtensionManager == null) { - TestPluginManager.Instance - .GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out var unfilteredTestExtensions, out var testExtensions); diff --git a/src/Microsoft.TestPlatform.Common/Utilities/RunSettingsUtilities.cs b/src/Microsoft.TestPlatform.Common/Utilities/RunSettingsUtilities.cs index 1ecc3ffa20..9a66fbc8de 100644 --- a/src/Microsoft.TestPlatform.Common/Utilities/RunSettingsUtilities.cs +++ b/src/Microsoft.TestPlatform.Common/Utilities/RunSettingsUtilities.cs @@ -190,4 +190,15 @@ public static IEnumerable GetTestAdaptersPaths(string runSettings) return testAdaptersPaths; } + /// + /// Gets the test adapter loading strategy + /// + /// Test run settings + /// Test adapter loading strategy + internal static TestAdapterLoadingStrategy GetLoadingStrategy(string runSettings) + { + var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runSettings); + + return runConfiguration.TestAdapterLoadingStrategy; + } } diff --git a/src/Microsoft.TestPlatform.ObjectModel/Friends.cs b/src/Microsoft.TestPlatform.ObjectModel/Friends.cs index 1261d15c99..1eabaf534d 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Friends.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/Friends.cs @@ -8,8 +8,11 @@ [assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Extensions.MSPhoneAdapter, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("datacollector, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Common, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Client, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.TestPlatform.ObjectModel.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("datacollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] diff --git a/src/Microsoft.TestPlatform.ObjectModel/RunSettings/RunConfiguration.cs b/src/Microsoft.TestPlatform.ObjectModel/RunSettings/RunConfiguration.cs index 18ed049720..165a249cf7 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/RunSettings/RunConfiguration.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/RunSettings/RunConfiguration.cs @@ -211,6 +211,11 @@ public bool DisableAppDomain } } + /// + /// Gets or sets the test adapter loading strategy. + /// + internal TestAdapterLoadingStrategy TestAdapterLoadingStrategy { get; set; } + /// /// Gets a value indicating whether parallelism needs to be disabled by the adapters. /// @@ -323,11 +328,7 @@ public string TestAdaptersPaths /// Gets or sets the execution thread apartment state. /// [CLSCompliant(false)] - public PlatformApartmentState ExecutionThreadApartmentState - { - get; - set; - } + public PlatformApartmentState ExecutionThreadApartmentState { get; set; } /// /// Gets or sets a value indicating whether to treat the errors from test adapters as warnings. @@ -501,6 +502,13 @@ public override XmlElement ToXml() root.AppendChild(testAdaptersPaths); } + if (this.TestAdapterLoadingStrategy != TestAdapterLoadingStrategy.Default) + { + XmlElement adapterLoadingStrategy = doc.CreateElement("TestAdapterLoadingStrategy"); + adapterLoadingStrategy.InnerXml = this.TestAdapterLoadingStrategy.ToString(); + root.AppendChild(adapterLoadingStrategy); + } + XmlElement treatTestAdapterErrorsAsWarnings = doc.CreateElement("TreatTestAdapterErrorsAsWarnings"); treatTestAdapterErrorsAsWarnings.InnerXml = TreatTestAdapterErrorsAsWarnings.ToString(); root.AppendChild(treatTestAdapterErrorsAsWarnings); @@ -761,6 +769,21 @@ public static RunConfiguration FromXml(XmlReader reader) runConfiguration.TestAdaptersPaths = reader.ReadElementContentAsString(); break; + case "TestAdapterLoadingStrategy": + XmlRunSettingsUtilities.ThrowOnHasAttributes(reader); + value = reader.ReadElementContentAsString(); + if (Enum.TryParse(value, out var loadingStrategy)) + { + runConfiguration.TestAdapterLoadingStrategy = loadingStrategy; + } + else + { + throw new SettingsException(string.Format(CultureInfo.CurrentCulture, + Resources.Resources.InvalidSettingsIncorrectValue, Constants.RunConfigurationSettingsName, value, elementName)); + } + + break; + case "TreatTestAdapterErrorsAsWarnings": XmlRunSettingsUtilities.ThrowOnHasAttributes(reader); bool treatTestAdapterErrorsAsWarnings = false; diff --git a/src/Microsoft.TestPlatform.ObjectModel/TestAdapterLoadingStrategy.cs b/src/Microsoft.TestPlatform.ObjectModel/TestAdapterLoadingStrategy.cs new file mode 100644 index 0000000000..14465435cc --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/TestAdapterLoadingStrategy.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.VisualStudio.TestPlatform.ObjectModel; + +using System; + +/// +/// Represents a loading strategy +/// +[Flags] +internal enum TestAdapterLoadingStrategy +{ + /// + /// A strategy not defined, Test Platform will load adapters normally. + /// + Default = 0, + + /// + /// Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + /// If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded. + /// If no adapter path is specified, test run will fail. + /// This will imply /InIsolation switch and force the tests to be run in an isolated process. + /// + Explicit = 1, + + /// + /// Load adapters next to source. + /// + NextToSource = 2, + + /// + /// Default runtime providers inside Extensions folder will be included. + /// + DefaultRuntimeProviders = 4, + + /// + /// Load adapters inside Extensions folder. + /// + ExtensionsDirectory = 8, + + /// + /// Directory wide searches will be recursive, this is required to be used with or . + /// + Recursive = 16, +} diff --git a/src/vstest.console/CommandLine/CommandLineOptions.cs b/src/vstest.console/CommandLine/CommandLineOptions.cs index 443318c3f7..bbaccb8909 100644 --- a/src/vstest.console/CommandLine/CommandLineOptions.cs +++ b/src/vstest.console/CommandLine/CommandLineOptions.cs @@ -121,7 +121,12 @@ public IEnumerable Sources /// /// Path to the custom test adapters. /// - public string TestAdapterPath { get; set; } + public string[] TestAdapterPath { get; set; } + + /// + /// Test adapter loading strategy. + /// + public TestAdapterLoadingStrategy TestAdapterLoadingStrategy { get; set; } /// /// Process Id of the process which launched vstest runner @@ -176,13 +181,9 @@ public IEnumerable Sources /// /// Specifies whether the target device has a Windows Phone context or not /// - public bool HasPhoneContext - { - get - { - return !string.IsNullOrEmpty(TargetDevice); - } - } + public bool HasPhoneContext => !string.IsNullOrEmpty(TargetDevice); + + public bool TestAdapterPathsSet => (TestAdapterPath?.Length ?? 0) != 0; /// /// Specifies the target platform type for test run. diff --git a/src/vstest.console/CommandLine/Executor.cs b/src/vstest.console/CommandLine/Executor.cs index 44c1e5692b..00975f5b29 100644 --- a/src/vstest.console/CommandLine/Executor.cs +++ b/src/vstest.console/CommandLine/Executor.cs @@ -222,7 +222,16 @@ private int GetArgumentProcessors(string[] args, out List pr // Examples: processors to enable loggers that are statically configured, and to start logging, // should always be executed. var processorsToAlwaysExecute = processorFactory.GetArgumentProcessorsToAlwaysExecute(); - processors.AddRange(processorsToAlwaysExecute); + foreach (var processor in processorsToAlwaysExecute) + { + if (processors.Any(i => i.Metadata.Value.CommandName == processor.Metadata.Value.CommandName)) + { + continue; + } + + // We need to initialize the argument executor if it's set to always execute. This ensures it will be initialized with other executors. + processors.Add(ArgumentProcessorFactory.WrapLazyProcessorToInitializeOnInstantiation(processor)); + } // Initialize Runsettings with defaults RunSettingsManager.Instance.AddDefaultRunSettings(); diff --git a/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs b/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs index 15e1828c0e..adbed0ec90 100644 --- a/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs +++ b/src/vstest.console/Processors/RunSpecificTestsArgumentProcessor.cs @@ -274,7 +274,7 @@ private void ExecuteSelectedTests() // No tests were discovered from the given sources. warningMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.NoTestsAvailableInSources, string.Join(", ", _commandLineOptions.Sources)); - if (string.IsNullOrEmpty(_commandLineOptions.TestAdapterPath)) + if (!_commandLineOptions.TestAdapterPathsSet) { warningMessage = string.Format(CultureInfo.CurrentCulture, CommandLineResources.StringFormatToJoinTwoStrings, warningMessage, CommandLineResources.SuggestTestAdapterPathIfNoTestsIsFound); } @@ -376,7 +376,7 @@ private void TestRunRequest_OnRunCompletion(object sender, TestRunCompleteEventA var testsFoundInAnySource = e.TestRunStatistics != null && (e.TestRunStatistics.ExecutedTests > 0); // Indicate the user to use testadapterpath command if there are no tests found - if (!testsFoundInAnySource && string.IsNullOrEmpty(CommandLineOptions.Instance.TestAdapterPath) && _commandLineOptions.TestCaseFilterValue == null) + if (!testsFoundInAnySource && !CommandLineOptions.Instance.TestAdapterPathsSet && _commandLineOptions.TestCaseFilterValue == null) { _output.Warning(false, CommandLineResources.SuggestTestAdapterPathIfNoTestsIsFound); } diff --git a/src/vstest.console/Processors/RunTestsArgumentProcessor.cs b/src/vstest.console/Processors/RunTestsArgumentProcessor.cs index f384f7914f..42972f46de 100644 --- a/src/vstest.console/Processors/RunTestsArgumentProcessor.cs +++ b/src/vstest.console/Processors/RunTestsArgumentProcessor.cs @@ -241,7 +241,7 @@ private void TestRunRequest_OnRunCompletion(object sender, TestRunCompleteEventA var testsFoundInAnySource = e.TestRunStatistics != null && (e.TestRunStatistics.ExecutedTests > 0); // Indicate the user to use test adapter path command if there are no tests found - if (!testsFoundInAnySource && string.IsNullOrEmpty(CommandLineOptions.Instance.TestAdapterPath) && _commandLineOptions.TestCaseFilterValue == null) + if (!testsFoundInAnySource && !CommandLineOptions.Instance.TestAdapterPathsSet && _commandLineOptions.TestCaseFilterValue == null) { _output.Warning(false, CommandLineResources.SuggestTestAdapterPathIfNoTestsIsFound); } diff --git a/src/vstest.console/Processors/TestAdapterLoadingStrategyArgumentProcessor.cs b/src/vstest.console/Processors/TestAdapterLoadingStrategyArgumentProcessor.cs new file mode 100644 index 0000000000..4785cfe395 --- /dev/null +++ b/src/vstest.console/Processors/TestAdapterLoadingStrategyArgumentProcessor.cs @@ -0,0 +1,253 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#nullable disable + +namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; + +using System; +using System.Globalization; +using System.Linq; + +using Microsoft.VisualStudio.TestPlatform.Common; +using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; +using Microsoft.VisualStudio.TestPlatform.Common.Utilities; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; + +using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; + +/// +/// Allows the user to specify a order of loading custom adapters from. +/// +internal class TestAdapterLoadingStrategyArgumentProcessor : IArgumentProcessor +{ + /// + /// The name of the command line argument that the TestAdapterLoadingStrategyArgumentProcessor handles. + /// + public const string CommandName = "/TestAdapterLoadingStrategy"; + + private Lazy _metadata; + + private Lazy _executor; + + /// + /// Gets the metadata. + /// + public Lazy Metadata + { + get + { + if (_metadata == null) + { + _metadata = new Lazy(() => new TestAdapterLoadingStrategyArgumentProcessorCapabilities()); + } + + return _metadata; + } + } + + /// + /// Gets or sets the executor. + /// + public Lazy Executor + { + get + { + if (_executor == null) + { + _executor = new Lazy(() => new TestAdapterLoadingStrategyArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, ConsoleOutput.Instance, new FileHelper())); + } + + return _executor; + } + + set + { + _executor = value; + } + } +} + +/// +/// The argument capabilities. +/// +internal class TestAdapterLoadingStrategyArgumentProcessorCapabilities : BaseArgumentProcessorCapabilities +{ + public override string CommandName => TestAdapterLoadingStrategyArgumentProcessor.CommandName; + + public override bool AllowMultiple => false; + + public override bool IsAction => false; + + public override bool AlwaysExecute => true; + + public override ArgumentProcessorPriority Priority => ArgumentProcessorPriority.TestAdapterLoadingStrategy; + + public override string HelpContentResourceName => CommandLineResources.TestAdapterLoadingStrategyHelp; + + public override HelpContentPriority HelpPriority => HelpContentPriority.TestAdapterLoadingStrategyArgumentProcessorHelpPriority; +} + +/// +/// The argument executor. +/// +internal class TestAdapterLoadingStrategyArgumentExecutor : IArgumentExecutor +{ + /// + /// Used for getting sources. + /// + private readonly CommandLineOptions _commandLineOptions; + + /// + /// Run settings provider. + /// + private readonly IRunSettingsProvider _runSettingsManager; + + /// + /// Used for sending output. + /// + private readonly IOutput _output; + + /// + /// For file related operation + /// + private readonly IFileHelper _fileHelper; + + public const string RunSettingsPath = "RunConfiguration.TestAdapterLoadingStrategy"; + + /// + /// Default constructor. + /// + /// The options. + /// The test platform + public TestAdapterLoadingStrategyArgumentExecutor(CommandLineOptions options!!, IRunSettingsProvider runSettingsManager!!, IOutput output!!, IFileHelper fileHelper!!) + { + _commandLineOptions = options; + _runSettingsManager = runSettingsManager; + _output = output; + _fileHelper = fileHelper; + } + + #region IArgumentExecutor + /// + /// Initializes with the argument that was provided with the command. + /// + /// Argument that was provided with the command. + public void Initialize(string argument) + { + ExtractStrategy(argument, out var strategy); + + if (strategy == TestAdapterLoadingStrategy.Recursive) + { + throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, CommandLineResources.TestAdapterLoadingStrategyValueInvalidRecursive, $"{nameof(TestAdapterLoadingStrategy.Explicit)}, {nameof(TestAdapterLoadingStrategy.NextToSource)}")); + } + + if (strategy == TestAdapterLoadingStrategy.Default) + { + InitializeDefaultStrategy(); + return; + } + + InitializeStrategy(strategy); + } + + /// + /// Executes the argument processor. + /// + /// The . + public ArgumentProcessorResult Execute() + { + // Nothing to do since we updated the parameter during initialize parameter + return ArgumentProcessorResult.Success; + } + #endregion + + private void ExtractStrategy(string value, out TestAdapterLoadingStrategy strategy) + { + value ??= _runSettingsManager.QueryRunSettingsNode(RunSettingsPath); + + if (string.IsNullOrWhiteSpace(value)) + { + strategy = TestAdapterLoadingStrategy.Default; + return; + } + + if (!Enum.TryParse(value, out strategy)) + { + throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, CommandLineResources.TestAdapterLoadingStrategyValueInvalid, value)); + } + } + + private void InitializeDefaultStrategy() + { + ValidateTestAdapterPaths(TestAdapterLoadingStrategy.Default); + + SetStrategy(TestAdapterLoadingStrategy.Default); + } + + private void InitializeStrategy(TestAdapterLoadingStrategy strategy) + { + ValidateTestAdapterPaths(strategy); + + if (!_commandLineOptions.TestAdapterPathsSet && strategy.HasFlag(TestAdapterLoadingStrategy.Explicit)) + { + throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, CommandLineResources.TestAdapterPathValueRequiredWhenStrategyXIsUsed, nameof(TestAdapterLoadingStrategy.Explicit))); + } + + SetStrategy(strategy); + } + + private void ForceIsolation() + { + if (_commandLineOptions.InIsolation) + { + return; + } + + EqtTrace.Warning( + $"{nameof(TestAdapterLoadingStrategyArgumentExecutor)}.{nameof(ForceIsolation)}: InIsolation setting is forced when {nameof(TestAdapterLoadingStrategy.Explicit)} strategy is used." + + "Tests will run in isolation." + ); + _commandLineOptions.InIsolation = true; + _runSettingsManager.UpdateRunSettingsNode(InIsolationArgumentExecutor.RunSettingsPath, "true"); + } + + private void ValidateTestAdapterPaths(TestAdapterLoadingStrategy strategy) + { + var testAdapterPaths = _commandLineOptions.TestAdapterPath ?? new string[0]; + if (!_commandLineOptions.TestAdapterPathsSet) + { + testAdapterPaths = TestAdapterPathArgumentExecutor.SplitPaths(_runSettingsManager.QueryRunSettingsNode(TestAdapterPathArgumentExecutor.RunSettingsPath)).Union(testAdapterPaths).Distinct().ToArray(); + } + + for (var i = 0; i < testAdapterPaths.Length; i++) + { + var adapterPath = testAdapterPaths[i]; + var testAdapterPath = _fileHelper.GetFullPath(Environment.ExpandEnvironmentVariables(adapterPath)); + + if (strategy == TestAdapterLoadingStrategy.Default && !_fileHelper.DirectoryExists(testAdapterPath)) + { + throw new CommandLineException( + string.Format(CultureInfo.CurrentCulture, CommandLineResources.InvalidTestAdapterPathCommand, adapterPath, CommandLineResources.TestAdapterPathDoesNotExist) + ); + } + + testAdapterPaths[i] = testAdapterPath; + } + + _runSettingsManager.UpdateRunSettingsNode(TestAdapterPathArgumentExecutor.RunSettingsPath, string.Join(";", testAdapterPaths)); + } + + private void SetStrategy(TestAdapterLoadingStrategy strategy) + { + _commandLineOptions.TestAdapterLoadingStrategy = strategy; + _runSettingsManager.UpdateRunSettingsNode(RunSettingsPath, strategy.ToString()); + if (strategy.HasFlag(TestAdapterLoadingStrategy.Explicit)) + { + ForceIsolation(); + } + } +} diff --git a/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs b/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs index 18bdefb83e..d273ec55e4 100644 --- a/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs +++ b/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs @@ -7,9 +7,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; using System.Globalization; -using System.IO; using System.Linq; using Common; @@ -101,24 +99,23 @@ internal class TestAdapterPathArgumentExecutor : IArgumentExecutor /// /// Separators for multiple paths in argument. /// - private readonly char[] _argumentSeparators = new[] { ';' }; + internal readonly static char[] ArgumentSeparators = new[] { ';' }; + + public const string RunSettingsPath = "RunConfiguration.TestAdaptersPaths"; /// /// Default constructor. /// /// The options. /// The test platform - public TestAdapterPathArgumentExecutor(CommandLineOptions options, IRunSettingsProvider runSettingsManager, IOutput output, IFileHelper fileHelper) + public TestAdapterPathArgumentExecutor(CommandLineOptions options!!, IRunSettingsProvider runSettingsManager!!, IOutput output!!, IFileHelper fileHelper!!) { - Contract.Requires(options != null); - _commandLineOptions = options; _runSettingsManager = runSettingsManager; _output = output; _fileHelper = fileHelper; } - #region IArgumentExecutor /// @@ -127,71 +124,34 @@ public TestAdapterPathArgumentExecutor(CommandLineOptions options, IRunSettingsP /// Argument that was provided with the command. public void Initialize(string argument) { - string invalidAdapterPathArgument = argument; - if (string.IsNullOrWhiteSpace(argument)) { throw new CommandLineException( string.Format(CultureInfo.CurrentCulture, CommandLineResources.TestAdapterPathValueRequired)); } - string customAdaptersPath; - - try - { - var testAdapterPaths = new List(); - var testAdapterFullPaths = new List(); - - // VSTS task add double quotes around TestAdapterpath. For example if user has given TestAdapter path C:\temp, - // Then VSTS task will add TestAdapterPath as "/TestAdapterPath:\"C:\Temp\"". - // Remove leading and trailing ' " ' chars... - argument = argument.Trim().Trim(new char[] { '\"' }); - - // Get test adapter paths from RunSettings. - var testAdapterPathsInRunSettings = _runSettingsManager.QueryRunSettingsNode("RunConfiguration.TestAdaptersPaths"); + string[] customAdaptersPath; - if (!string.IsNullOrWhiteSpace(testAdapterPathsInRunSettings)) - { - testAdapterPaths.AddRange(SplitPaths(testAdapterPathsInRunSettings)); - } + var testAdapterPaths = new List(); - testAdapterPaths.AddRange(SplitPaths(argument)); + // VSTS task add double quotes around TestAdapterpath. For example if user has given TestAdapter path C:\temp, + // Then VSTS task will add TestAdapterPath as "/TestAdapterPath:\"C:\Temp\"". + // Remove leading and trailing ' " ' chars... + argument = argument.Trim().Trim(new char[] { '\"' }); - foreach (var testAdapterPath in testAdapterPaths) - { - // TestAdaptersPaths could contain environment variables - var testAdapterFullPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(testAdapterPath)); + // Get test adapter paths from RunSettings. + var testAdapterPathsInRunSettings = _runSettingsManager.QueryRunSettingsNode(RunSettingsPath); - if (!_fileHelper.DirectoryExists(testAdapterFullPath)) - { - invalidAdapterPathArgument = testAdapterPath; - throw new DirectoryNotFoundException(CommandLineResources.TestAdapterPathDoesNotExist); - } - - testAdapterFullPaths.Add(testAdapterFullPath); - } - - customAdaptersPath = string.Join(";", testAdapterFullPaths.Distinct().ToArray()); - - _runSettingsManager.UpdateRunSettingsNode("RunConfiguration.TestAdaptersPaths", customAdaptersPath); - } - catch (Exception e) + if (!string.IsNullOrWhiteSpace(testAdapterPathsInRunSettings)) { - throw new CommandLineException( - string.Format(CultureInfo.CurrentCulture, CommandLineResources.InvalidTestAdapterPathCommand, invalidAdapterPathArgument, e.Message)); + testAdapterPaths.AddRange(SplitPaths(testAdapterPathsInRunSettings)); } - _commandLineOptions.TestAdapterPath = customAdaptersPath; - } + testAdapterPaths.AddRange(SplitPaths(argument)); + customAdaptersPath = testAdapterPaths.Distinct().ToArray(); - /// - /// Splits provided paths into array. - /// - /// Source paths joined by semicolons. - /// Paths. - private string[] SplitPaths(string paths) - { - return string.IsNullOrWhiteSpace(paths) ? (new string[] { }) : paths.Split(_argumentSeparators, StringSplitOptions.RemoveEmptyEntries); + _runSettingsManager.UpdateRunSettingsNode(RunSettingsPath, string.Join(";", customAdaptersPath)); + _commandLineOptions.TestAdapterPath = customAdaptersPath; } /// @@ -203,6 +163,15 @@ public ArgumentProcessorResult Execute() // Nothing to do since we updated the parameter during initialize parameter return ArgumentProcessorResult.Success; } - #endregion + + /// + /// Splits provided paths into array. + /// + /// Source paths joined by semicolons. + /// Paths. + internal static string[] SplitPaths(string paths) + { + return string.IsNullOrWhiteSpace(paths) ? new string[0] : paths.Split(ArgumentSeparators, StringSplitOptions.RemoveEmptyEntries); + } } diff --git a/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs b/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs index b99afa6182..085645445a 100644 --- a/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs +++ b/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs @@ -206,6 +206,7 @@ public IEnumerable GetArgumentProcessorsToAlwaysExecute() new RunTestsArgumentProcessor(), new RunSpecificTestsArgumentProcessor(), new TestAdapterPathArgumentProcessor(), + new TestAdapterLoadingStrategyArgumentProcessor(), new TestCaseFilterArgumentProcessor(), new ParentProcessIdArgumentProcessor(), new PortArgumentProcessor(), @@ -273,9 +274,7 @@ private void BuildCommandMaps() /// The lazy processor. /// The argument with which the real processor should be initialized. /// The decorated lazy processor. - private static IArgumentProcessor WrapLazyProcessorToInitializeOnInstantiation( - IArgumentProcessor processor, - string initArg = null) + public static IArgumentProcessor WrapLazyProcessorToInitializeOnInstantiation(IArgumentProcessor processor, string initArg = null) { var processorExecutor = processor.Executor; var lazyArgumentProcessor = new Lazy(() => diff --git a/src/vstest.console/Processors/Utilities/ArgumentProcessorPriority.cs b/src/vstest.console/Processors/Utilities/ArgumentProcessorPriority.cs index 318c1f7e9c..3407defb4a 100644 --- a/src/vstest.console/Processors/Utilities/ArgumentProcessorPriority.cs +++ b/src/vstest.console/Processors/Utilities/ArgumentProcessorPriority.cs @@ -45,10 +45,18 @@ internal enum ArgumentProcessorPriority /// /// Priority of TestAdapterPathArgumentProcessor. + /// /// The priority of TestAdapterPath processor is more than the logger because logger initialization /// loads the extensions which are incomplete if custom test adapter is enabled /// - TestAdapterPath = 10, + TestAdapterPath = 9, + + /// + /// Priority of TestAdapterLoadingStrategyArgumentProcessor. + /// + /// This needs to be higher than most of other arguments, because it affects where we look for test adapters. + /// + TestAdapterLoadingStrategy = 10, /// /// Priority of processors that needs to update runsettings. diff --git a/src/vstest.console/Processors/Utilities/HelpContentPriority.cs b/src/vstest.console/Processors/Utilities/HelpContentPriority.cs index 1bf11b14ba..fc7c401753 100644 --- a/src/vstest.console/Processors/Utilities/HelpContentPriority.cs +++ b/src/vstest.console/Processors/Utilities/HelpContentPriority.cs @@ -24,6 +24,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; /// --ListTests /// --Parallel /// --TestAdapterPath +/// --TestAdapterLoadingStrategy /// /// Diagnose/Report /// --Diag @@ -35,7 +36,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; /// --Port /// /// Help -/// -Help +/// --Help /// internal enum HelpContentPriority { @@ -99,6 +100,11 @@ internal enum HelpContentPriority /// TestAdapterPathArgumentProcessorHelpPriority, + /// + /// TestAdapterLoadingStrategyArgumentProcessor Help + /// + TestAdapterLoadingStrategyArgumentProcessorHelpPriority, + /// /// EnableDiagArgumentProcessor Help /// diff --git a/src/vstest.console/Resources/Resources.Designer.cs b/src/vstest.console/Resources/Resources.Designer.cs index 831dd46323..3ebb595467 100644 --- a/src/vstest.console/Resources/Resources.Designer.cs +++ b/src/vstest.console/Resources/Resources.Designer.cs @@ -1516,6 +1516,39 @@ internal static string SwitchToNoIsolation { } } + /// + /// Looks up a localized string similar to --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + /// This affects adapter loading behavior. + /// + /// Currently supported behaviours: + /// - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + /// If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + /// [rest of string was truncated]";. + /// + internal static string TestAdapterLoadingStrategyHelp { + get { + return ResourceManager.GetString("TestAdapterLoadingStrategyHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified value ({0}) for /TestAdapterLoadingStrategy is invalid!. + /// + internal static string TestAdapterLoadingStrategyValueInvalid { + get { + return ResourceManager.GetString("TestAdapterLoadingStrategyValueInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "Recursive" adapter loading strategy is cannot be used by itself. Please specify at least one of: {0}. + /// + internal static string TestAdapterLoadingStrategyValueInvalidRecursive { + get { + return ResourceManager.GetString("TestAdapterLoadingStrategyValueInvalidRecursive", resourceCulture); + } + } + /// /// Looks up a localized string similar to The custom test adapter search path provided was not found, provide a valid path and try again.. /// @@ -1546,6 +1579,15 @@ internal static string TestAdapterPathValueRequired { } } + /// + /// Looks up a localized string similar to The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified!. + /// + internal static string TestAdapterPathValueRequiredWhenStrategyXIsUsed { + get { + return ResourceManager.GetString("TestAdapterPathValueRequiredWhenStrategyXIsUsed", resourceCulture); + } + } + /// /// Looks up a localized string similar to --TestCaseFilter|/TestCaseFilter:<Expression> /// Run tests that match the given expression. diff --git a/src/vstest.console/Resources/Resources.resx b/src/vstest.console/Resources/Resources.resx index 0997bea995..a14635b564 100644 --- a/src/vstest.console/Resources/Resources.resx +++ b/src/vstest.console/Resources/Resources.resx @@ -560,6 +560,43 @@ The /TestAdapterPath parameter requires a value, which is path of a location containing custom test adapters. Example: /TestAdapterPath:c:\MyCustomAdapters + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + --TestCaseFilter|/TestCaseFilter:<Expression> Run tests that match the given expression. diff --git a/src/vstest.console/Resources/xlf/Resources.cs.xlf b/src/vstest.console/Resources/xlf/Resources.cs.xlf index 0c842e4e07..e5a20355f2 100644 --- a/src/vstest.console/Resources/xlf/Resources.cs.xlf +++ b/src/vstest.console/Resources/xlf/Resources.cs.xlf @@ -1113,6 +1113,68 @@ Neplatné testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.de.xlf b/src/vstest.console/Resources/xlf/Resources.de.xlf index ad8d11fbfe..7d2b076dae 100644 --- a/src/vstest.console/Resources/xlf/Resources.de.xlf +++ b/src/vstest.console/Resources/xlf/Resources.de.xlf @@ -1113,6 +1113,68 @@ Ungültige testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.es.xlf b/src/vstest.console/Resources/xlf/Resources.es.xlf index e6f61dacc5..fc0927358a 100644 --- a/src/vstest.console/Resources/xlf/Resources.es.xlf +++ b/src/vstest.console/Resources/xlf/Resources.es.xlf @@ -1116,6 +1116,68 @@ TestSessionCorrelationId no válido + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.fr.xlf b/src/vstest.console/Resources/xlf/Resources.fr.xlf index e337df6cce..c44ca0e4c9 100644 --- a/src/vstest.console/Resources/xlf/Resources.fr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.fr.xlf @@ -1113,6 +1113,68 @@ TestSessionCorrelationId non valide + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.it.xlf b/src/vstest.console/Resources/xlf/Resources.it.xlf index 50bc50790d..8d12dac209 100644 --- a/src/vstest.console/Resources/xlf/Resources.it.xlf +++ b/src/vstest.console/Resources/xlf/Resources.it.xlf @@ -1113,6 +1113,68 @@ TestSessionCorrelationId non valido + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ja.xlf b/src/vstest.console/Resources/xlf/Resources.ja.xlf index 2d7152bcd6..7f07227ee8 100644 --- a/src/vstest.console/Resources/xlf/Resources.ja.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ja.xlf @@ -1113,6 +1113,68 @@ 無効な testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ko.xlf b/src/vstest.console/Resources/xlf/Resources.ko.xlf index d80684ab57..cc081a02a3 100644 --- a/src/vstest.console/Resources/xlf/Resources.ko.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ko.xlf @@ -1113,6 +1113,68 @@ 잘못된 testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.pl.xlf b/src/vstest.console/Resources/xlf/Resources.pl.xlf index d038bf0b71..e21ac00015 100644 --- a/src/vstest.console/Resources/xlf/Resources.pl.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pl.xlf @@ -1113,6 +1113,68 @@ Nieprawidłowy identyfikator testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf index fb6ce74b6c..c8728ccac1 100644 --- a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf @@ -1113,6 +1113,68 @@ Altere o prefixo de nível de diagnóstico do agente de console, como mostrado a TestSessionCorrelationId inválida + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ru.xlf b/src/vstest.console/Resources/xlf/Resources.ru.xlf index 9b03339ce3..3b295594f0 100644 --- a/src/vstest.console/Resources/xlf/Resources.ru.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ru.xlf @@ -1113,6 +1113,68 @@ Недопустимый testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.tr.xlf b/src/vstest.console/Resources/xlf/Resources.tr.xlf index 5ba658aadf..b6cfd41612 100644 --- a/src/vstest.console/Resources/xlf/Resources.tr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.tr.xlf @@ -1113,6 +1113,68 @@ Günlükler için izleme düzeyini aşağıda gösterildiği gibi değiştirin testSessionCorrelationId geçersiz + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.xlf b/src/vstest.console/Resources/xlf/Resources.xlf index 123ac1b7a9..ee30d2159d 100644 --- a/src/vstest.console/Resources/xlf/Resources.xlf +++ b/src/vstest.console/Resources/xlf/Resources.xlf @@ -906,6 +906,68 @@ Format : TestRunParameters.Parameter(name="<name>", value="<value>") Invalid testSessionCorrelationId + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf index 141eefc643..2cbc8845e7 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf @@ -1113,6 +1113,68 @@ testSessionCorrelationId 无效 + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf index d91a260373..d1c7327856 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf @@ -1113,6 +1113,68 @@ testSessionCorrelationId 無效 + + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviors: + - Explicit: Test Platform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platform will load adapters is if this argument has not been specified. + It will pick up extensions from next to source, provided additional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + --TestAdapterLoadingStrategy|/TestAdapterLoadingStrategy:<strategy> + This affects adapter loading behavior. + + Currently supported behaviours: + - Explicit: Test Plarform will only load adapters specified by /TestAdapterPath (or RunConfiguration.TestAdaptersPaths node). + If a specific adapter path is provided, adapter will be loaded; if a directory path is provided adapters directly in that folder will be loaded, unless Recursive option is also specified. + If no adapter path is specified, test run will fail. + This will imply /InIsolation switch and force the tests to be run in an isolated process. + + - Default: Test Platfrom will load adapters is if this argument has not beed specified. + It will pick up extensions from next to source, provided aditional adapter paths and from the default directory. + + - DefaultRuntimeProviders: Load default runtime providers shipped with Test Platform. + If this is not specified when "Explicit" option is set, a test host provider need to be specified explicitly. + + - ExtensionsDirectory: Load adapters inside Extensions folder. + + - NextToSource: Load adapters next to source. + + - Recursive: Recursively search folders when loading adapters. This requires "Explicit" or "NextToSource" to be specified too. + + Do not translate "Default", "DefaultRuntimeProviders", "ExtensionsDirectory", "NextToSource" or "Recursive". + + + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + Specified value ({0}) for /TestAdapterLoadingStrategy is invalid! + + + + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + Recursive adapter loading strategy is cannot be used by itself. Please combine with one or more of: {0} + + - Do not translate "Recursive", + - {0} is the strategy names, seperated by comma: for example "Explicit, NextToSource" + + + + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + The /TestAdapterPath parameter needs to be provided when "{0}" test adapter loading strategy is specified! + {0} is the strategy name, "Explicit" for example. + \ No newline at end of file diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs index 0f43f0924b..4cc7076745 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs @@ -31,7 +31,7 @@ public TestExtensionManagerTests() { TestPluginCacheHelper.SetupMockExtensions(typeof(TestExtensionManagerTests)); _messageLogger = TestSessionMessageLogger.Instance; - TestPluginManager.Instance.GetSpecificTestExtensions + TestPluginManager.GetSpecificTestExtensions (TestPlatformConstants.TestLoggerEndsWithPattern, out _unfilteredTestExtensions, out _filteredTestExtensions); } diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs index 7f010866ac..63b9f5af12 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs @@ -74,7 +74,7 @@ public void GetTestExtensionsShouldReturnTestDiscovererExtensions() { TestPluginCacheHelper.SetupMockExtensions(typeof(TestPluginManagerTests)); - TestPluginManager.Instance.GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out var unfilteredTestExtensions, out var testExtensions); @@ -90,13 +90,13 @@ public void GetTestExtensionsShouldDiscoverExtensionsOnlyOnce() var discoveryCount = 0; TestPluginCacheHelper.SetupMockExtensions(typeof(TestPluginManagerTests), () => discoveryCount++); - TestPluginManager.Instance.GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out var unfilteredTestExtensions, out var testExtensions); // Call this again to verify that discovery is not called again. - TestPluginManager.Instance.GetSpecificTestExtensions( + TestPluginManager.GetSpecificTestExtensions( TestPlatformConstants.TestAdapterEndsWithPattern, out unfilteredTestExtensions, out testExtensions); @@ -110,8 +110,7 @@ public void GetTestExtensionsShouldDiscoverExtensionsOnlyOnce() [TestMethod] public void GetTestExtensionsForAnExtensionAssemblyShouldReturnExtensionsInThatAssembly() { - TestPluginManager.Instance - .GetTestExtensions( + TestPluginManager.GetTestExtensions( typeof(TestPluginManagerTests).GetTypeInfo().Assembly.Location, out _, out var testExtensions); diff --git a/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs index 0bf445effc..bfa9894723 100644 --- a/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/RunSpecificTestsArgumentProcessorTests.cs @@ -360,7 +360,7 @@ public void ExecutorExecuteShouldForValidSourcesAndNoTestsDiscoveredShouldLogWar ResetAndAddSourceToCommandLineOptions(); // Setting some test adapter path - CommandLineOptions.Instance.TestAdapterPath = @"C:\Foo"; + CommandLineOptions.Instance.TestAdapterPath = new[] { @"C:\Foo" }; mockDiscoveryRequest.Setup(dr => dr.DiscoverAsync()).Raises(dr => dr.OnDiscoveredTests += null, new DiscoveredTestsEventArgs(new List())); mockTestPlatform.Setup(tp => tp.CreateDiscoveryRequest(It.IsAny(), It.IsAny(), It.IsAny())).Returns(mockDiscoveryRequest.Object); diff --git a/test/vstest.console.UnitTests/Processors/TestAdapterLoadingStrategyArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/TestAdapterLoadingStrategyArgumentProcessorTests.cs new file mode 100644 index 0000000000..4cb6f103ef --- /dev/null +++ b/test/vstest.console.UnitTests/Processors/TestAdapterLoadingStrategyArgumentProcessorTests.cs @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#nullable disable + +namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors; + +using System; +using System.IO; + +using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; +using Microsoft.VisualStudio.TestPlatform.Common; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Moq; + +[TestClass] +public class TestAdapterLoadingStrategyArgumentProcessorTests +{ + private RunSettings _currentActiveSetting; + + [TestInitialize] + public void TestInit() + { + _currentActiveSetting = RunSettingsManager.Instance.ActiveRunSettings; + } + + [TestCleanup] + public void TestClean() + { + RunSettingsManager.Instance.SetActiveRunSettings(_currentActiveSetting); + } + + [TestMethod] + [TestCategory("Windows")] + public void InitializeShouldHonorEnvironmentVariablesInTestAdapterPaths() + { + var runSettingsXml = "%temp%\\adapters1;%temp%\\adapters2"; + var runSettings = new RunSettings(); + runSettings.LoadSettingsXml(runSettingsXml); + RunSettingsManager.Instance.SetActiveRunSettings(runSettings); + var mockFileHelper = new Mock(); + var mockOutput = new Mock(); + + mockFileHelper.Setup(x => x.DirectoryExists(It.IsAny())).Returns(true); + mockFileHelper.Setup(x => x.GetFullPath(It.IsAny())).Returns((Func)(s => Path.GetFullPath(s))); + + var executor = new TestAdapterLoadingStrategyArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); + + executor.Initialize(nameof(TestAdapterLoadingStrategy.Default)); + var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); + + var tempPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables("%temp%")); + Assert.AreEqual(string.Format("{0}\\adapters1;{0}\\adapters2", tempPath), runConfiguration.TestAdaptersPaths); + } + + [TestMethod] + [TestCategory("Windows")] + public void InitializeShouldAddRightAdapterPathInErrorMessage() + { + var runSettingsXml = "d:\\users"; + var runSettings = new RunSettings(); + runSettings.LoadSettingsXml(runSettingsXml); + RunSettingsManager.Instance.SetActiveRunSettings(runSettings); + var mockFileHelper = new Mock(); + var mockOutput = new Mock(); + + mockFileHelper.Setup(x => x.DirectoryExists("d:\\users")).Returns(false); + mockFileHelper.Setup(x => x.DirectoryExists("c:\\users")).Returns(true); + var executor = new TestAdapterLoadingStrategyArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); + + var message = string.Format( + @"The path '{0}' specified in the 'TestAdapterPath' is invalid. Error: {1}", + "d:\\users", + "The custom test adapter search path provided was not found, provide a valid path and try again."); + + var isExceptionThrown = false; + try + { + executor.Initialize(nameof(TestAdapterLoadingStrategy.Default)); + } + catch (Exception ex) + { + isExceptionThrown = true; + Assert.IsTrue(ex is CommandLineException); + Assert.AreEqual(message, ex.Message); + } + + Assert.IsTrue(isExceptionThrown); + } + + + [TestMethod] + public void InitializeShouldThrowIfPathDoesNotExist() + { + var folder = "C:\\temp\\thisfolderdoesnotexist"; + var runSettingsXml = "" + folder + ""; + var runSettings = new RunSettings(); + + runSettings.LoadSettingsXml(runSettingsXml); + RunSettingsManager.Instance.SetActiveRunSettings(runSettings); + + var mockOutput = new Mock(); + var executor = new TestAdapterLoadingStrategyArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, new FileHelper()); + + var message = string.Format( + @"The path '{0}' specified in the 'TestAdapterPath' is invalid. Error: {1}", + folder, + "The custom test adapter search path provided was not found, provide a valid path and try again."); + + var isExceptionThrown = false; + + try + { + executor.Initialize(nameof(TestAdapterLoadingStrategy.Default)); + } + catch (Exception ex) + { + isExceptionThrown = true; + Assert.IsTrue(ex is CommandLineException); + Assert.AreEqual(message, ex.Message); + } + + Assert.IsTrue(isExceptionThrown); + } +} diff --git a/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs index 0a43616288..4098db52cf 100644 --- a/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs @@ -129,36 +129,6 @@ public void InitializeShouldThrowIfArgumentIsAWhiteSpace() Assert.IsTrue(isExceptionThrown); } - [TestMethod] - public void InitializeShouldThrowIfPathDoesNotExist() - { - var mockRunSettingsProvider = new Mock(); - var mockOutput = new Mock(); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockRunSettingsProvider.Object, mockOutput.Object, new FileHelper()); - - var folder = "C:\\temp\\thisfolderdoesnotexist"; - - var message = string.Format( - @"The path '{0}' specified in the 'TestAdapterPath' is invalid. Error: {1}", - folder, - "The custom test adapter search path provided was not found, provide a valid path and try again."); - - var isExceptionThrown = false; - - try - { - executor.Initialize(folder); - } - catch (Exception ex) - { - isExceptionThrown = true; - Assert.IsTrue(ex is CommandLineException); - Assert.AreEqual(message, ex.Message); - } - - Assert.IsTrue(isExceptionThrown); - } - [TestMethod] public void InitializeShouldUpdateTestAdapterPathInRunSettings() { @@ -194,100 +164,6 @@ public void InitializeShouldMergeTestAdapterPathsInRunSettings() Assert.AreEqual("d:\\users;f:\\users;c:\\users", runConfiguration.TestAdaptersPaths); } - [TestMethod] - [TestCategory("Windows")] - public void InitializeShouldMergeTestAdapterPathsInRunSettingsIgnoringDuplicatePaths() - { - var runSettingsXml = "d:\\users;c:\\users"; - var runSettings = new RunSettings(); - runSettings.LoadSettingsXml(runSettingsXml); - RunSettingsManager.Instance.SetActiveRunSettings(runSettings); - var mockFileHelper = new Mock(); - var mockOutput = new Mock(); - - mockFileHelper.Setup(x => x.DirectoryExists(It.IsAny())).Returns(true); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); - - executor.Initialize("c:\\users"); - var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); - Assert.AreEqual("d:\\users;c:\\users", runConfiguration.TestAdaptersPaths); - } - - [TestMethod] - [TestCategory("Windows")] - public void InitializeShouldMergeMultipleTestAdapterPathsWithPathsInRunSettings() - { - var runSettingsXml = "d:\\users;f:\\users"; - var runSettings = new RunSettings(); - runSettings.LoadSettingsXml(runSettingsXml); - RunSettingsManager.Instance.SetActiveRunSettings(runSettings); - var mockFileHelper = new Mock(); - var mockOutput = new Mock(); - - mockFileHelper.Setup(x => x.DirectoryExists(It.IsAny())).Returns(true); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); - - executor.Initialize("c:\\users;e:\\users"); - var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); - Assert.AreEqual("d:\\users;f:\\users;c:\\users;e:\\users", runConfiguration.TestAdaptersPaths); - } - - [TestMethod] - [TestCategory("Windows")] - public void InitializeShouldHonorEnvironmentVariablesInTestAdapterPaths() - { - var runSettingsXml = "%temp%\\adapters1"; - var runSettings = new RunSettings(); - runSettings.LoadSettingsXml(runSettingsXml); - RunSettingsManager.Instance.SetActiveRunSettings(runSettings); - var mockFileHelper = new Mock(); - var mockOutput = new Mock(); - - mockFileHelper.Setup(x => x.DirectoryExists(It.IsAny())).Returns(true); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); - - executor.Initialize("%temp%\\adapters2"); - var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); - - var tempPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables("%temp%")); - Assert.AreEqual(string.Format("{0}\\adapters1;{0}\\adapters2", tempPath), runConfiguration.TestAdaptersPaths); - } - - [TestMethod] - [TestCategory("Windows")] - public void InitializeShouldAddRightAdapterPathInErrorMessage() - { - var runSettingsXml = "d:\\users"; - var runSettings = new RunSettings(); - runSettings.LoadSettingsXml(runSettingsXml); - RunSettingsManager.Instance.SetActiveRunSettings(runSettings); - var mockFileHelper = new Mock(); - var mockOutput = new Mock(); - - mockFileHelper.Setup(x => x.DirectoryExists("d:\\users")).Returns(false); - mockFileHelper.Setup(x => x.DirectoryExists("c:\\users")).Returns(true); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); - - var message = string.Format( - @"The path '{0}' specified in the 'TestAdapterPath' is invalid. Error: {1}", - "d:\\users", - "The custom test adapter search path provided was not found, provide a valid path and try again."); - - var isExceptionThrown = false; - try - { - executor.Initialize("c:\\users"); - } - catch (Exception ex) - { - isExceptionThrown = true; - Assert.IsTrue(ex is CommandLineException); - Assert.AreEqual(message, ex.Message); - } - - Assert.IsTrue(isExceptionThrown); - } - [TestMethod] [TestCategory("Windows")] public void InitializeShouldTrimTrailingAndLeadingDoubleQuotes()