diff --git a/src/Cli/dotnet/SlnFileExtensions.cs b/src/Cli/dotnet/SlnFileExtensions.cs
index 0a981b9e2429..22b5cc48c5a8 100644
--- a/src/Cli/dotnet/SlnFileExtensions.cs
+++ b/src/Cli/dotnet/SlnFileExtensions.cs
@@ -6,7 +6,6 @@
using Microsoft.Build.Execution;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
-using System.Collections.Generic;
namespace Microsoft.DotNet.Tools.Common
{
@@ -271,7 +270,7 @@ private static void AddSolutionFolders(this SlnFile slnFile, SlnProject slnProje
else
{
- if(HasDuplicateNameForSameValueOfNestedProjects(nestedProjectsSection, dir, parentDirGuid, slnFile.Projects))
+ if (HasDuplicateNameForSameValueOfNestedProjects(nestedProjectsSection, dir, parentDirGuid, slnFile.Projects))
{
throw new GracefulException(CommonLocalizableStrings.SolutionFolderAlreadyContainsProject, slnFile.FullPath, slnProject.Name, slnFile.Projects.FirstOrDefault(p => p.Id == parentDirGuid).Name);
}
diff --git a/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs b/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs
index 08ba9c16b3dc..8b8c4a33838c 100644
--- a/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/CliConstants.cs
@@ -15,6 +15,13 @@ internal static class CliConstants
public const string MSBuildExeName = "MSBuild.dll";
public const string ParametersSeparator = "--";
+
+ public const string VSTest = "VSTest";
+ public const string MicrosoftTestingPlatform = "MicrosoftTestingPlatform";
+
+ public const string TestSectionKey = "test";
+
+ public const string RestoreCommand = "restore";
}
internal static class TestStates
@@ -50,4 +57,15 @@ internal static class ProtocolConstants
{
internal const string Version = "1.0.0";
}
+
+ internal static class ProjectProperties
+ {
+ internal const string IsTestingPlatformApplication = "IsTestingPlatformApplication";
+ internal const string IsTestProject = "IsTestProject";
+ internal const string TargetFramework = "TargetFramework";
+ internal const string TargetFrameworks = "TargetFrameworks";
+ internal const string TargetPath = "TargetPath";
+ internal const string ProjectFullPath = "MSBuildProjectFullPath";
+ internal const string RunSettingsFilePath = "RunSettingsFilePath";
+ }
}
diff --git a/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx
index 2a6adfc6f413..92aaef39fd5c 100644
--- a/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx
+++ b/src/Cli/dotnet/commands/dotnet-test/LocalizableStrings.resx
@@ -326,4 +326,19 @@ Examples:
Test application(s) that support VSTest are not supported.
+
+ Test runner not supported: {0}.
+
+
+ The provided project file path does not exist: {0}.
+
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
diff --git a/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs b/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs
deleted file mode 100644
index e8e38728b825..000000000000
--- a/src/Cli/dotnet/commands/dotnet-test/MSBuildConnectionHandler.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Concurrent;
-using System.CommandLine;
-using System.IO.Pipes;
-using Microsoft.DotNet.Cli.Utils;
-using Microsoft.DotNet.Tools.Test;
-
-namespace Microsoft.DotNet.Cli
-{
- internal sealed class MSBuildConnectionHandler : IDisposable
- {
- private List _args;
- private readonly TestApplicationActionQueue _actionQueue;
-
- private readonly PipeNameDescription _pipeNameDescription = NamedPipeServer.GetPipeName(Guid.NewGuid().ToString("N"));
- private readonly List _namedPipeConnections = new();
- private readonly ConcurrentBag _testApplications = new();
- private bool _areTestingPlatformApplications = true;
-
- public MSBuildConnectionHandler(List args, TestApplicationActionQueue actionQueue)
- {
- _args = args;
- _actionQueue = actionQueue;
- }
-
- public async Task WaitConnectionAsync(CancellationToken token)
- {
- VSTestTrace.SafeWriteTrace(() => $"Waiting for connection(s) on pipe = {_pipeNameDescription.Name}");
-
- try
- {
- while (!token.IsCancellationRequested)
- {
- NamedPipeServer pipeConnection = new(_pipeNameDescription, OnRequest, NamedPipeServerStream.MaxAllowedServerInstances, token, skipUnknownMessages: true);
- pipeConnection.RegisterAllSerializers();
-
- await pipeConnection.WaitConnectionAsync(token);
-
- _namedPipeConnections.Add(pipeConnection);
- }
- }
- catch (OperationCanceledException ex) when (ex.CancellationToken == token)
- {
- // We are exiting
- }
- catch (Exception ex)
- {
- if (VSTestTrace.TraceEnabled)
- {
- VSTestTrace.SafeWriteTrace(() => ex.ToString());
- }
-
- Environment.FailFast(ex.ToString());
- }
- }
-
- private Task OnRequest(IRequest request)
- {
- try
- {
- if (request is not ModuleMessage module)
- {
- throw new NotSupportedException($"Request '{request.GetType()}' is unsupported.");
- }
-
- // Check if the test app has IsTestingPlatformApplication property set to true
- if (bool.TryParse(module.IsTestingPlatformApplication, out bool isTestingPlatformApplication) && isTestingPlatformApplication)
- {
- var testApp = new TestApplication(new Module(module.DllOrExePath, module.ProjectPath, module.TargetFramework, module.RunSettingsFilePath), _args);
- _testApplications.Add(testApp);
- }
- else // If one test app has IsTestingPlatformApplication set to false, then we will not run any of the test apps
- {
- _areTestingPlatformApplications = false;
- }
- }
- catch (Exception ex)
- {
- if (VSTestTrace.TraceEnabled)
- {
- VSTestTrace.SafeWriteTrace(() => ex.ToString());
- }
-
- Environment.FailFast(ex.ToString());
- }
-
- return Task.FromResult((IResponse)VoidResponse.CachedInstance);
- }
-
- public bool EnqueueTestApplications()
- {
- if (!_areTestingPlatformApplications)
- {
- return false;
- }
-
- foreach (var testApp in _testApplications)
- {
- _actionQueue.Enqueue(testApp);
- }
- return true;
- }
-
- public int RunWithMSBuild(ParseResult parseResult)
- {
- List msbuildCommandLineArgs =
- [
- parseResult.GetValue(TestingPlatformOptions.ProjectOption) ?? string.Empty,
- "-t:Restore;_GetTestsProject",
- $"-p:GetTestsProjectPipeName={_pipeNameDescription.Name}",
- "-verbosity:q",
- "-nologo",
- ];
-
- AddBinLogParameterIfExists(msbuildCommandLineArgs, _args);
- AddAdditionalMSBuildParametersIfExist(parseResult, msbuildCommandLineArgs);
-
- if (VSTestTrace.TraceEnabled)
- {
- VSTestTrace.SafeWriteTrace(() => $"MSBuild command line arguments: {string.Join(" ", msbuildCommandLineArgs)}");
- }
-
- ForwardingAppImplementation msBuildForwardingApp = new(GetMSBuildExePath(), msbuildCommandLineArgs);
- return msBuildForwardingApp.Execute();
- }
-
- private static void AddBinLogParameterIfExists(List msbuildCommandLineArgs, List args)
- {
- var binLog = args.FirstOrDefault(arg => arg.StartsWith("-bl", StringComparison.OrdinalIgnoreCase));
-
- if (!string.IsNullOrEmpty(binLog))
- {
- msbuildCommandLineArgs.Add(binLog);
-
- // We remove it from the args list so that it is not passed to the test application
- args.Remove(binLog);
- }
- }
-
- private static void AddAdditionalMSBuildParametersIfExist(ParseResult parseResult, List parameters)
- {
- string msBuildParameters = parseResult.GetValue(TestingPlatformOptions.AdditionalMSBuildParametersOption);
-
- if (!string.IsNullOrEmpty(msBuildParameters))
- {
- parameters.AddRange(msBuildParameters.Split(" ", StringSplitOptions.RemoveEmptyEntries));
- }
- }
-
- private static string GetMSBuildExePath()
- {
- return Path.Combine(
- AppContext.BaseDirectory,
- CliConstants.MSBuildExeName);
- }
-
- public void Dispose()
- {
- foreach (var namedPipeServer in _namedPipeConnections)
- {
- namedPipeServer.Dispose();
- }
-
- foreach (var testApplication in _testApplications)
- {
- testApplication.Dispose();
- }
- }
- }
-}
diff --git a/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs b/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs
new file mode 100644
index 000000000000..40c2e4639cae
--- /dev/null
+++ b/src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs
@@ -0,0 +1,269 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Concurrent;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Logging;
+
+namespace Microsoft.DotNet.Cli
+{
+ internal sealed class MSBuildHandler : IDisposable
+ {
+ private readonly List _args;
+ private readonly TestApplicationActionQueue _actionQueue;
+ private readonly int _degreeOfParallelism;
+
+ private readonly ConcurrentBag _testApplications = new();
+ private bool _areTestingPlatformApplications = true;
+
+ private const string BinLogFileName = "msbuild.binlog";
+ private const string Separator = ";";
+ private static readonly Lock buildLock = new();
+
+ public MSBuildHandler(List args, TestApplicationActionQueue actionQueue, int degreeOfParallelism)
+ {
+ _args = args;
+ _actionQueue = actionQueue;
+ _degreeOfParallelism = degreeOfParallelism;
+ }
+
+ public async Task RunWithMSBuild()
+ {
+ bool solutionOrProjectFileFound = SolutionAndProjectUtility.TryGetProjectOrSolutionFilePath(Directory.GetCurrentDirectory(), out string projectOrSolutionFilePath, out bool isSolution);
+
+ if (!solutionOrProjectFileFound)
+ {
+ return ExitCodes.GenericFailure;
+ }
+
+ (IEnumerable modules, bool restored) = await GetProjectsProperties(projectOrSolutionFilePath, isSolution);
+
+ InitializeTestApplications(modules);
+
+ return restored ? ExitCodes.Success : ExitCodes.GenericFailure;
+ }
+
+ public async Task RunWithMSBuild(string filePath)
+ {
+ (IEnumerable modules, bool restored) = await GetProjectsProperties(filePath, false);
+
+ InitializeTestApplications(modules);
+
+ return restored ? ExitCodes.Success : ExitCodes.GenericFailure;
+ }
+
+ private void InitializeTestApplications(IEnumerable modules)
+ {
+ foreach (Module module in modules)
+ {
+ if (module.IsTestProject && module.IsTestingPlatformApplication)
+ {
+ var testApp = new TestApplication(module, _args);
+ _testApplications.Add(testApp);
+ }
+ else // If one test app has IsTestingPlatformApplication set to false, then we will not run any of the test apps
+ {
+ _areTestingPlatformApplications = false;
+ return;
+ }
+ }
+ }
+
+ public bool EnqueueTestApplications()
+ {
+ if (!_areTestingPlatformApplications)
+ {
+ return false;
+ }
+
+ foreach (var testApp in _testApplications)
+ {
+ _actionQueue.Enqueue(testApp);
+ }
+ return true;
+ }
+
+ private async Task<(IEnumerable, bool Restored)> GetProjectsProperties(string solutionOrProjectFilePath, bool isSolution)
+ {
+ var allProjects = new ConcurrentBag();
+ bool restored = true;
+
+ if (isSolution)
+ {
+ var projects = await SolutionAndProjectUtility.ParseSolution(solutionOrProjectFilePath);
+ ProcessProjectsInParallel(projects, allProjects, ref restored);
+ }
+ else
+ {
+ bool allowBinLog = IsBinaryLoggerEnabled(_args, out string binLogFileName);
+
+ var (relatedProjects, isProjectBuilt) = GetProjectPropertiesInternal(solutionOrProjectFilePath, allowBinLog, binLogFileName);
+ foreach (var relatedProject in relatedProjects)
+ {
+ allProjects.Add(relatedProject);
+ }
+
+ if (!isProjectBuilt)
+ {
+ restored = false;
+ }
+ }
+ return (allProjects, restored);
+ }
+
+ private void ProcessProjectsInParallel(IEnumerable projects, ConcurrentBag allProjects, ref bool restored)
+ {
+ bool allProjectsRestored = true;
+ bool allowBinLog = IsBinaryLoggerEnabled(_args, out string binLogFileName);
+
+ Parallel.ForEach(
+ projects,
+ new ParallelOptions { MaxDegreeOfParallelism = _degreeOfParallelism },
+ () => true,
+ (project, state, localRestored) =>
+ {
+ var (relatedProjects, isRestored) = GetProjectPropertiesInternal(project, allowBinLog, binLogFileName);
+ foreach (var relatedProject in relatedProjects)
+ {
+ allProjects.Add(relatedProject);
+ }
+
+ return localRestored && isRestored;
+ },
+ localRestored =>
+ {
+ if (!localRestored)
+ {
+ allProjectsRestored = false;
+ }
+ });
+
+ restored = allProjectsRestored;
+ }
+
+ private static (IEnumerable Modules, bool Restored) GetProjectPropertiesInternal(string projectFilePath, bool allowBinLog, string binLogFileName)
+ {
+ var projectCollection = new ProjectCollection();
+ var project = projectCollection.LoadProject(projectFilePath);
+ var buildResult = RestoreProject(projectFilePath, projectCollection, allowBinLog, binLogFileName);
+
+ bool restored = buildResult.OverallResult == BuildResultCode.Success;
+
+ if (!restored)
+ {
+ return (Array.Empty(), restored);
+ }
+
+ return (ExtractModulesFromProject(project), restored);
+ }
+
+ private static IEnumerable ExtractModulesFromProject(Project project)
+ {
+ _ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestingPlatformApplication), out bool isTestingPlatformApplication);
+ _ = bool.TryParse(project.GetPropertyValue(ProjectProperties.IsTestProject), out bool isTestProject);
+
+ string targetFramework = project.GetPropertyValue(ProjectProperties.TargetFramework);
+ string targetFrameworks = project.GetPropertyValue(ProjectProperties.TargetFrameworks);
+ string targetPath = project.GetPropertyValue(ProjectProperties.TargetPath);
+ string projectFullPath = project.GetPropertyValue(ProjectProperties.ProjectFullPath);
+ string runSettingsFilePath = project.GetPropertyValue(ProjectProperties.RunSettingsFilePath);
+
+ var projects = new List();
+
+ if (string.IsNullOrEmpty(targetFrameworks))
+ {
+ projects.Add(new Module(targetPath, projectFullPath, targetFramework, runSettingsFilePath, isTestingPlatformApplication, isTestProject));
+ }
+ else
+ {
+ var frameworks = targetFrameworks.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var framework in frameworks)
+ {
+ project.SetProperty(ProjectProperties.TargetFramework, framework);
+ project.ReevaluateIfNecessary();
+
+ projects.Add(new Module(project.GetPropertyValue(ProjectProperties.TargetPath),
+ projectFullPath,
+ framework,
+ runSettingsFilePath,
+ isTestingPlatformApplication,
+ isTestProject));
+ }
+ }
+
+ return projects;
+ }
+
+ private static BuildResult RestoreProject(string projectFilePath, ProjectCollection projectCollection, bool allowBinLog, string binLogFileName)
+ {
+ BuildParameters parameters = new(projectCollection)
+ {
+ Loggers = [new ConsoleLogger(LoggerVerbosity.Quiet)]
+ };
+
+ if (allowBinLog)
+ {
+ parameters.Loggers = parameters.Loggers.Concat([
+ new BinaryLogger
+ {
+ Parameters = binLogFileName
+ }
+ ]);
+ }
+
+ var buildRequestData = new BuildRequestData(projectFilePath, new Dictionary(), null, [CliConstants.RestoreCommand], null);
+ BuildResult buildResult;
+ lock (buildLock)
+ {
+ buildResult = BuildManager.DefaultBuildManager.Build(parameters, buildRequestData);
+ }
+
+ return buildResult;
+ }
+
+ private static bool IsBinaryLoggerEnabled(List args, out string binLogFileName)
+ {
+ binLogFileName = BinLogFileName;
+
+ var binLogArgs = new List();
+
+ foreach (var arg in args)
+ {
+ if (arg.StartsWith("/bl:") || arg.Equals("/bl")
+ || arg.StartsWith("--binaryLogger:") || arg.Equals("--binaryLogger")
+ || arg.StartsWith("-bl:") || arg.Equals("-bl"))
+ {
+ binLogArgs.Add(arg);
+
+ }
+ }
+
+ if (binLogArgs.Count > 0)
+ {
+ // Remove all BinLog args from the list of args
+ args.RemoveAll(arg => binLogArgs.Contains(arg));
+
+ // Get BinLog filename
+ var binLogArg = binLogArgs.LastOrDefault();
+
+ if (binLogArg.Contains(':'))
+ {
+ binLogFileName = binLogArg.Split(':')[1];
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ public void Dispose()
+ {
+ foreach (var testApplication in _testApplications)
+ {
+ testApplication.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/Cli/dotnet/commands/dotnet-test/Models.cs b/src/Cli/dotnet/commands/dotnet-test/Models.cs
index 8484f819f38d..9f18391810c6 100644
--- a/src/Cli/dotnet/commands/dotnet-test/Models.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/Models.cs
@@ -3,7 +3,7 @@
namespace Microsoft.DotNet.Cli
{
- internal sealed record Module(string? DllOrExePath, string? ProjectPath, string? TargetFramework, string? RunSettingsFilePath);
+ internal sealed record Module(string? DllOrExePath, string? ProjectPath, string? TargetFramework, string? RunSettingsFilePath, bool IsTestingPlatformApplication, bool IsTestProject);
internal sealed record Handshake(Dictionary? Properties);
diff --git a/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs b/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs
new file mode 100644
index 000000000000..f050f135fcf8
--- /dev/null
+++ b/src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.DotNet.Tools;
+using Microsoft.DotNet.Tools.Test;
+using Microsoft.VisualStudio.SolutionPersistence;
+using Microsoft.VisualStudio.SolutionPersistence.Model;
+using Microsoft.VisualStudio.SolutionPersistence.Serializer;
+
+namespace Microsoft.DotNet.Cli
+{
+ internal static class SolutionAndProjectUtility
+ {
+ public static bool TryGetProjectOrSolutionFilePath(string directory, out string projectOrSolutionFilePath, out bool isSolution)
+ {
+ projectOrSolutionFilePath = string.Empty;
+ isSolution = false;
+
+ if (!Directory.Exists(directory))
+ {
+ return false;
+ }
+
+ string[] possibleSolutionPaths = [
+ ..Directory.GetFiles(directory, "*.sln", SearchOption.TopDirectoryOnly),
+ ..Directory.GetFiles(directory, "*.slnx", SearchOption.TopDirectoryOnly)];
+
+ // If more than a single sln file is found, an error is thrown since we can't determine which one to choose.
+ if (possibleSolutionPaths.Length > 1)
+ {
+ VSTestTrace.SafeWriteTrace(() => string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory));
+ return false;
+ }
+ // If a single solution is found, use it.
+ else if (possibleSolutionPaths.Length == 1)
+ {
+ // Get project file paths to check if there are any projects in the directory
+ string[] possibleProjectPaths = GetProjectFilePaths(directory);
+
+ if (possibleProjectPaths.Length == 0)
+ {
+ projectOrSolutionFilePath = possibleSolutionPaths[0];
+ isSolution = true;
+ return true;
+ }
+ else // If both solution and project files are found, return false
+ {
+ VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorMessage);
+ return false;
+ }
+ }
+ // If no solutions are found, look for a project file
+ else
+ {
+ string[] possibleProjectPath = GetProjectFilePaths(directory);
+
+ // No projects found throws an error that no sln nor projects were found
+ if (possibleProjectPath.Length == 0)
+ {
+ VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdNoProjectOrSolutionFileErrorMessage);
+ return false;
+ }
+ // A single project found, use it
+ else if (possibleProjectPath.Length == 1)
+ {
+ projectOrSolutionFilePath = possibleProjectPath[0];
+ return true;
+ }
+ // More than one project found. Not sure which one to choose
+ else
+ {
+ VSTestTrace.SafeWriteTrace(() => string.Format(CommonLocalizableStrings.MoreThanOneProjectInDirectory, directory));
+ return false;
+ }
+ }
+ }
+
+
+ private static string[] GetProjectFilePaths(string directory)
+ {
+ var projectFiles = Directory.EnumerateFiles(directory, "*.*proj", SearchOption.TopDirectoryOnly)
+ .Where(IsProjectFile)
+ .ToArray();
+
+ return projectFiles;
+ }
+
+ private static bool IsProjectFile(string filePath)
+ {
+ var extension = Path.GetExtension(filePath);
+ return extension.Equals(".csproj", StringComparison.OrdinalIgnoreCase) ||
+ extension.Equals(".vbproj", StringComparison.OrdinalIgnoreCase) ||
+ extension.Equals(".fsproj", StringComparison.OrdinalIgnoreCase) ||
+ extension.Equals(".proj", StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static async Task> ParseSolution(string solutionFilePath)
+ {
+ if (string.IsNullOrEmpty(solutionFilePath))
+ {
+ VSTestTrace.SafeWriteTrace(() => $"Solution file path cannot be null or empty: {solutionFilePath}");
+ return [];
+ }
+
+ var projectsPaths = new List();
+ SolutionModel solution = null;
+
+ try
+ {
+ solution = SolutionSerializers.GetSerializerByMoniker(solutionFilePath) is ISolutionSerializer serializer
+ ? await serializer.OpenAsync(solutionFilePath, CancellationToken.None)
+ : null;
+ }
+ catch (Exception ex)
+ {
+ VSTestTrace.SafeWriteTrace(() => $"Failed to parse solution file '{solutionFilePath}': {ex.Message}");
+ return [];
+ }
+
+ if (solution is not null)
+ {
+ projectsPaths = [.. solution.SolutionProjects.Select(project => Path.GetFullPath(project.FilePath))];
+ }
+
+ return projectsPaths;
+ }
+ }
+}
diff --git a/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs b/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs
index c727ffd4fe3b..1c448328323c 100644
--- a/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/TestApplication.cs
@@ -4,6 +4,7 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO.Pipes;
+using Microsoft.DotNet.Tools.Common;
using Microsoft.DotNet.Tools.Test;
namespace Microsoft.DotNet.Cli
@@ -33,6 +34,9 @@ internal sealed class TestApplication : IDisposable
public event EventHandler Run;
public event EventHandler ExecutionIdReceived;
+ private const string TestingPlatformVsTestBridgeRunSettingsFileEnvVar = "TESTINGPLATFORM_VSTESTBRIDGE_RUNSETTINGS_FILE";
+ private const string DLLExtension = "dll";
+
public Module Module => _module;
public TestApplication(Module module, List args)
@@ -55,7 +59,7 @@ public async Task RunAsync(bool isFilterMode, bool enableHelp, BuiltInOptio
return 1;
}
- bool isDll = _module.DllOrExePath.EndsWith(".dll");
+ bool isDll = _module.DllOrExePath.HasExtension(DLLExtension);
ProcessStartInfo processStartInfo = new()
{
@@ -67,7 +71,7 @@ public async Task RunAsync(bool isFilterMode, bool enableHelp, BuiltInOptio
if (!string.IsNullOrEmpty(_module.RunSettingsFilePath))
{
- processStartInfo.EnvironmentVariables.Add("TESTINGPLATFORM_VSTESTBRIDGE_RUNSETTINGS_FILE", _module.RunSettingsFilePath);
+ processStartInfo.EnvironmentVariables.Add(TestingPlatformVsTestBridgeRunSettingsFileEnvVar, _module.RunSettingsFilePath);
}
_testAppPipeConnectionLoop = Task.Run(async () => await WaitConnectionAsync(_cancellationToken.Token), _cancellationToken.Token);
diff --git a/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs b/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs
index 5196981af9ae..9c26e21111e2 100644
--- a/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs
@@ -190,7 +190,7 @@ private static CliCommand ConstructCommand()
private static CliCommand GetTestingPlatformCliCommand()
{
var command = new TestingPlatformCommand("test");
- command.SetAction((parseResult) => command.Run(parseResult));
+ command.SetAction(async (parseResult) => await command.Run(parseResult));
command.Options.Add(TestingPlatformOptions.MaxParallelTestModulesOption);
command.Options.Add(TestingPlatformOptions.AdditionalMSBuildParametersOption);
command.Options.Add(TestingPlatformOptions.TestModulesFilterOption);
diff --git a/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs b/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs
index 7562e0225296..80179fbf5732 100644
--- a/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/TestModulesFilterHandler.cs
@@ -50,7 +50,7 @@ public bool RunWithTestModulesFilter(ParseResult parseResult)
foreach (string testModule in testModulePaths)
{
- var testApp = new TestApplication(new Module(testModule, null, null, null), _args);
+ var testApp = new TestApplication(new Module(testModule, null, null, null, true, true), _args);
// Write the test application to the channel
_actionQueue.Enqueue(testApp);
}
diff --git a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs
index 6499eb074933..838a74530384 100644
--- a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.Help.cs
@@ -14,11 +14,11 @@ internal partial class TestingPlatformCommand
public IEnumerable> CustomHelpLayout()
{
- yield return (context) =>
+ yield return async (context) =>
{
Console.WriteLine("Waiting for options and extensions...");
- Run(context.ParseResult);
+ await Run(context.ParseResult);
if (_commandLineOptionNameToModuleNames.IsEmpty)
{
diff --git a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs
index b947031fdca2..e51f8da017d7 100644
--- a/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs
+++ b/src/Cli/dotnet/commands/dotnet-test/TestingPlatformCommand.cs
@@ -11,12 +11,10 @@ namespace Microsoft.DotNet.Cli
internal partial class TestingPlatformCommand : CliCommand, ICustomHelp
{
private readonly ConcurrentBag _testApplications = [];
- private readonly CancellationTokenSource _cancellationToken = new();
- private MSBuildConnectionHandler _msBuildConnectionHandler;
+ private MSBuildHandler _msBuildHandler;
private TestModulesFilterHandler _testModulesFilterHandler;
private TestApplicationActionQueue _actionQueue;
- private Task _namedPipeConnectionLoop;
private List _args;
public TestingPlatformCommand(string name, string description = null) : base(name, description)
@@ -24,7 +22,7 @@ public TestingPlatformCommand(string name, string description = null) : base(nam
TreatUnmatchedTokensAsErrors = false;
}
- public int Run(ParseResult parseResult)
+ public async Task Run(ParseResult parseResult)
{
bool hasFailed = false;
try
@@ -78,10 +76,9 @@ public int Run(ParseResult parseResult)
});
}
- _args = new List(parseResult.UnmatchedTokens);
- _msBuildConnectionHandler = new(_args, _actionQueue);
+ _args = [.. parseResult.UnmatchedTokens];
+ _msBuildHandler = new(_args, _actionQueue, degreeOfParallelism);
_testModulesFilterHandler = new(_args, _actionQueue);
- _namedPipeConnectionLoop = Task.Run(async () => await _msBuildConnectionHandler.WaitConnectionAsync(_cancellationToken.Token));
if (parseResult.HasOption(TestingPlatformOptions.TestModulesFilterOption))
{
@@ -92,16 +89,13 @@ public int Run(ParseResult parseResult)
}
else
{
- // If no filter was provided, MSBuild will get the test project paths
- var msbuildResult = _msBuildConnectionHandler.RunWithMSBuild(parseResult);
- if (msbuildResult != 0)
+ if (!await RunMSBuild(parseResult))
{
- VSTestTrace.SafeWriteTrace(() => $"MSBuild task _GetTestsProject didn't execute properly with exit code: {msbuildResult}.");
return ExitCodes.GenericFailure;
}
- // If not all test projects have IsTestingPlatformApplication set to true, we will simply return
- if (!_msBuildConnectionHandler.EnqueueTestApplications())
+ // If not all test projects have IsTestProject and IsTestingPlatformApplication properties set to true, we will simply return
+ if (!_msBuildHandler.EnqueueTestApplications())
{
VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdUnsupportedVSTestTestApplicationsDescription);
return ExitCodes.GenericFailure;
@@ -111,8 +105,6 @@ public int Run(ParseResult parseResult)
_actionQueue.EnqueueCompleted();
hasFailed = _actionQueue.WaitAllActions();
// Above line will block till we have all connections and all GetTestsProject msbuild task complete.
-
- WaitOnMSBuildHandlerPipeConnectionLoop();
}
finally
{
@@ -123,15 +115,41 @@ public int Run(ParseResult parseResult)
return hasFailed ? ExitCodes.GenericFailure : ExitCodes.Success;
}
- private void WaitOnMSBuildHandlerPipeConnectionLoop()
+ private async Task RunMSBuild(ParseResult parseResult)
{
- _cancellationToken.Cancel();
- _namedPipeConnectionLoop.Wait((int)TimeSpan.FromSeconds(30).TotalMilliseconds);
+ int msbuildExitCode;
+
+ if (parseResult.HasOption(TestingPlatformOptions.ProjectOption))
+ {
+ string filePath = parseResult.GetValue(TestingPlatformOptions.ProjectOption);
+
+ if (!File.Exists(filePath))
+ {
+ VSTestTrace.SafeWriteTrace(() => string.Format(LocalizableStrings.CmdNonExistentProjectFilePathDescription, filePath));
+ return false;
+ }
+
+ msbuildExitCode = await _msBuildHandler.RunWithMSBuild(filePath);
+ }
+ else
+ {
+ // If no filter was provided neither the project using --project,
+ // MSBuild will get the test project paths in the current directory
+ msbuildExitCode = await _msBuildHandler.RunWithMSBuild();
+ }
+
+ if (msbuildExitCode != ExitCodes.Success)
+ {
+ VSTestTrace.SafeWriteTrace(() => string.Format(LocalizableStrings.CmdMSBuildProjectsPropertiesErrorMessage, msbuildExitCode));
+ return false;
+ }
+
+ return true;
}
private void CleanUp()
{
- _msBuildConnectionHandler.Dispose();
+ _msBuildHandler.Dispose();
foreach (var testApplication in _testApplications)
{
testApplication.Dispose();
@@ -238,7 +256,7 @@ private void OnTestProcessExited(object sender, TestProcessExitEventArgs args)
return;
}
- if (args.ExitCode != 0)
+ if (args.ExitCode != ExitCodes.Success)
{
VSTestTrace.SafeWriteTrace(() => $"Test Process exited with non-zero exit code: {args.ExitCode}");
}
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf
index 2ad19fb0b1b8..293bf2f6c922 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.cs.xlf
@@ -118,21 +118,41 @@ Příklady:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Maximální počet testovacích modulů, které je možné spustit paralelně.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerSpustit testy bez zobrazení nápisu Microsoft Testplatform
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ Pokud zadaný adresář neexistuje, bude vytvořen.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf
index 230a26c4cdf8..ffdc27dd1298 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.de.xlf
@@ -118,21 +118,41 @@ Beispiele:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Die maximale Anzahl von Testmodulen, die parallel ausgeführt werden können.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerTest(s) ohne Anzeige des Microsoft-Testplattformbanners ausführen
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ Das angegebene Verzeichnis wird erstellt, wenn es nicht vorhanden ist.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf
index b4504cd41ca0..880eb9ad38b6 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.es.xlf
@@ -120,21 +120,41 @@ Ejemplos:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Número máximo de módulos de prueba que se pueden ejecutar en paralelo.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerEjecutar pruebas, sin mostrar la pancarta de Microsoft Testplatform
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -257,6 +277,11 @@ Si no existe, se creará el directorio especificado.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf
index 080d51785fda..809445d7303c 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.fr.xlf
@@ -118,21 +118,41 @@ Exemples :
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Nombre maximal de modules de test qui peuvent s’exécuter en parallèle.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerExécute le ou les tests, sans afficher la bannière Microsoft Testplatform
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ Le répertoire spécifié est créé, s'il n'existe pas déjà.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf
index 31ea56d050fe..497ec27cbeb3 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.it.xlf
@@ -118,21 +118,41 @@ Esempi:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Numero massimo di moduli di test che possono essere eseguiti in parallelo.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerEsegui test senza visualizzare il banner di Microsoft Testplatform
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ Se non esiste, la directory specificata verrà creata.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf
index cc1420582f48..e569010555c7 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ja.xlf
@@ -118,21 +118,41 @@ Examples:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.並列で実行できるテスト モジュールの最大数。
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerMicrosoft Testplatform バナーを表示せずにテストを実行する
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ The specified directory will be created if it does not exist.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf
index 37bb82ef49af..79a632e40db1 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ko.xlf
@@ -118,21 +118,41 @@ Examples:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.병렬로 실행할 수 있는 최대 테스트 모듈 수입니다.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerMicrosoft Testplatform 배너를 표시하지 않고 테스트 실행
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ The specified directory will be created if it does not exist.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf
index 8d40d724227b..2d5a55fa0b94 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pl.xlf
@@ -118,21 +118,41 @@ Przykłady:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Maksymalna liczba modułów testowych, które mogą być uruchamiane równolegle.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerUruchom testy bez wyświetlania baneru platformy testowej firmy Microsoft
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ Jeśli określony katalog nie istnieje, zostanie utworzony.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf
index 5eaa4668710e..d693799cad63 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.pt-BR.xlf
@@ -118,21 +118,41 @@ Exemplos:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.O número máximo de módulos de teste que podem ser executados em paralelo.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerExecutar testes, sem exibir a faixa do Microsoft Testplatform
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ O diretório especificado será criado se ele ainda não existir.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf
index a9669d9915c4..c1d07c22765b 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.ru.xlf
@@ -118,21 +118,41 @@ Examples:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Максимальное число тестовых модулей, которые могут выполняться параллельно.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerЗапуск тестов без отображения баннера Testplatform Майкрософт
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ The specified directory will be created if it does not exist.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf
index 68bcd480e31b..24501aa00de8 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.tr.xlf
@@ -118,21 +118,41 @@ Bu bağımsız değişken, birden çok değişken sağlamak için birden çok ke
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.Paralel olarak çalıştırılabilecek test modüllerinin maksimum sayısı.
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform bannerTestleri Microsoft Testplatform bandını görüntülemeden çalıştır
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ Belirtilen dizin yoksa oluşturulur.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf
index e7ac40be829b..379e4b89db5f 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hans.xlf
@@ -118,21 +118,41 @@ Examples:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.可并行运行的测试模块的最大数目。
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform banner运行测试,而不显示 Microsoft Testplatform 版权标志
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ The specified directory will be created if it does not exist.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.
diff --git a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf
index 222eb321c2c4..c6c681e48c47 100644
--- a/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/commands/dotnet-test/xlf/LocalizableStrings.zh-Hant.xlf
@@ -118,21 +118,41 @@ Examples:
Invalid test message state '{0}'{0} - test message state
+
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+ Get projects properties with MSBuild didn't execute properly with exit code: {0}.
+
+ The max number of test modules that can run in parallel.可平行執行的測試模組數目上限。
+
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+ Specify which project or solution file to use because this folder contains more than one project or solution file.
+
+ Run test(s), without displaying Microsoft Testplatform banner執行測試,但不顯示 Microsoft Testplatform 橫幅
+
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+ Specify a project or solution file. The current working directory does not contain a project or solution file.
+
+ Do not execute an implicit restore.Do not execute an implicit restore.
+
+ The provided project file path does not exist: {0}.
+ The provided project file path does not exist: {0}.
+
+ Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.Defines the path of the project file to run (folder name or full path). If not specified, it defaults to the current directory.
@@ -255,6 +275,11 @@ The specified directory will be created if it does not exist.
Message Request type '{0}' is unsupported.{0} - message request type
+
+ Test runner not supported: {0}.
+ Test runner not supported: {0}.
+
+ Test application(s) that support VSTest are not supported.Test application(s) that support VSTest are not supported.