diff --git a/src/Microsoft.TestPlatform.Build/ArgumentEscaper.cs b/src/Microsoft.TestPlatform.Build/ArgumentEscaper.cs
deleted file mode 100644
index 8d9f22b6b5..0000000000
--- a/src/Microsoft.TestPlatform.Build/ArgumentEscaper.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Text;
-
-namespace Microsoft.TestPlatform.Build.Utils;
-
-public static class ArgumentEscaper
-{
- ///
- /// Undo the processing which took place to create string[] args in Main,
- /// so that the next process will receive the same string[] args
- ///
- /// See here for more info:
- /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
- ///
- ///
- /// Return original string passed by client
- public static string HandleEscapeSequenceInArgForProcessStart(string arg)
- {
- var sb = new StringBuilder();
-
- var needsQuotes = ShouldSurroundWithQuotes(arg);
- var isQuoted = needsQuotes || IsSurroundedWithQuotes(arg);
-
- if (needsQuotes)
- {
- sb.Append('\"');
- }
-
- for (int i = 0; i < arg.Length; ++i)
- {
- var backslashCount = 0;
-
- // Consume All Backslashes
- while (i < arg.Length && arg[i] == '\\')
- {
- backslashCount++;
- i++;
- }
-
- // Escape any backslashes at the end of the arg
- // when the argument is also quoted.
- // This ensures the outside quote is interpreted as
- // an argument delimiter
- if (i == arg.Length && isQuoted)
- {
- sb.Append('\\', 2 * backslashCount);
- }
-
- // At then end of the arg, which isn't quoted,
- // just add the backslashes, no need to escape
- else if (i == arg.Length)
- {
- sb.Append('\\', backslashCount);
- }
-
- // Escape any preceding backslashes and the quote
- else if (arg[i] == '"')
- {
- sb.Append('\\', (2 * backslashCount) + 1);
- sb.Append('"');
- }
-
- // Output any consumed backslashes and the character
- else
- {
- sb.Append('\\', backslashCount);
- sb.Append(arg[i]);
- }
- }
-
- if (needsQuotes)
- {
- sb.Append('\"');
- }
-
- return sb.ToString();
- }
-
- internal static bool ShouldSurroundWithQuotes(string argument)
- {
- // Don't quote already quoted strings
- if (IsSurroundedWithQuotes(argument))
- {
- return false;
- }
-
- // Only quote if whitespace exists in the string
- return ArgumentContainsWhitespace(argument);
- }
-
- internal static bool IsSurroundedWithQuotes(string argument)
- => argument.StartsWith("\"", StringComparison.Ordinal)
- && argument.EndsWith("\"", StringComparison.Ordinal);
-
- internal static bool ArgumentContainsWhitespace(string argument)
- => argument.Contains(" ") || argument.Contains("\t") || argument.Contains("\n");
-}
diff --git a/src/Microsoft.TestPlatform.Build/Microsoft.TestPlatform.targets b/src/Microsoft.TestPlatform.Build/Microsoft.TestPlatform.targets
index 7329157c46..6e639a1731 100644
--- a/src/Microsoft.TestPlatform.Build/Microsoft.TestPlatform.targets
+++ b/src/Microsoft.TestPlatform.Build/Microsoft.TestPlatform.targets
@@ -14,9 +14,12 @@ Copyright (c) .NET Foundation. All rights reserved.
Microsoft.TestPlatform.Build.dll
$([System.IO.Path]::Combine($(MSBuildThisFileDirectory),"vstest.console.dll"))
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Unshipped.txt b/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Unshipped.txt
index 7c0e9679c9..5d3611c8d9 100644
--- a/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Unshipped.txt
@@ -1,8 +1,4 @@
#nullable enable
-Microsoft.TestPlatform.Build.Tasks.VSTestForwardingApp
-Microsoft.TestPlatform.Build.Tasks.VSTestForwardingApp.Cancel() -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestForwardingApp.Execute() -> int
-Microsoft.TestPlatform.Build.Tasks.VSTestForwardingApp.VSTestForwardingApp(string! vsTestExePath, System.Collections.Generic.IEnumerable! argsToForward) -> void
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.LogType.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.LogType.set -> void
@@ -11,19 +7,19 @@ Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.ProjectFilePath.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.VSTestLogsTask() -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask
Microsoft.TestPlatform.Build.Tasks.VSTestTask.Cancel() -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.TestFileFullPath.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.TestFileFullPath.get -> Microsoft.Build.Framework.ITaskItem?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.TestFileFullPath.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestArtifactsProcessingMode.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestArtifactsProcessingMode.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlame.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlame.get -> bool
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlame.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrash.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrash.get -> bool
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrash.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrashCollectAlways.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrashCollectAlways.get -> bool
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrashCollectAlways.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrashDumpType.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameCrashDumpType.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameHang.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameHang.get -> bool
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameHang.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameHangDumpType.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestBlameHangDumpType.set -> void
@@ -33,39 +29,93 @@ Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestCLIRunSettings.get -> string
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestCLIRunSettings.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestCollect.get -> string![]?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestCollect.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestConsolePath.get -> string!
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestConsolePath.get -> Microsoft.Build.Framework.ITaskItem?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestConsolePath.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestDiag.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestDiag.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestFramework.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestFramework.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestListTests.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestListTests.get -> bool
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestListTests.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestLogger.get -> string![]?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestLogger.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestNoLogo.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestNoLogo.get -> bool
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestNoLogo.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestPlatform.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestPlatform.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestResultsDirectory.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestResultsDirectory.get -> Microsoft.Build.Framework.ITaskItem?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestResultsDirectory.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestSessionCorrelationId.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestSessionCorrelationId.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestSetting.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestSetting.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTask() -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTestAdapterPath.get -> string![]?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTestAdapterPath.get -> Microsoft.Build.Framework.ITaskItem![]?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTestAdapterPath.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTestCaseFilter.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTestCaseFilter.set -> void
-Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTraceDataCollectorDirectoryPath.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTraceDataCollectorDirectoryPath.get -> Microsoft.Build.Framework.ITaskItem?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestTraceDataCollectorDirectoryPath.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestVerbosity.get -> string?
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestVerbosity.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.TestFileFullPath.get -> Microsoft.Build.Framework.ITaskItem?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.TestFileFullPath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestArtifactsProcessingMode.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestArtifactsProcessingMode.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlame.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlame.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameCrash.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameCrash.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameCrashCollectAlways.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameCrashCollectAlways.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameCrashDumpType.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameCrashDumpType.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameHang.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameHang.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameHangDumpType.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameHangDumpType.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameHangTimeout.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestBlameHangTimeout.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestCLIRunSettings.get -> string![]?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestCLIRunSettings.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestCollect.get -> string![]?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestCollect.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestConsolePath.get -> Microsoft.Build.Framework.ITaskItem?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestConsolePath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestDiag.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestDiag.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestFramework.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestFramework.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestListTests.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestListTests.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestLogger.get -> string![]?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestLogger.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestNoLogo.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestNoLogo.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestPlatform.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestPlatform.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestResultsDirectory.get -> Microsoft.Build.Framework.ITaskItem?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestResultsDirectory.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestSessionCorrelationId.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestSessionCorrelationId.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestSetting.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestSetting.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTask2() -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTestAdapterPath.get -> Microsoft.Build.Framework.ITaskItem![]?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTestAdapterPath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTestCaseFilter.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTestCaseFilter.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTraceDataCollectorDirectoryPath.get -> Microsoft.Build.Framework.ITaskItem?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestTraceDataCollectorDirectoryPath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestVerbosity.get -> string?
+Microsoft.TestPlatform.Build.Tasks.VSTestTask2.VSTestVerbosity.set -> void
Microsoft.TestPlatform.Build.Trace.Tracing
-Microsoft.TestPlatform.Build.Utils.ArgumentEscaper
override Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.Execute() -> bool
override Microsoft.TestPlatform.Build.Tasks.VSTestTask.Execute() -> bool
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask2.GenerateCommandLineCommands() -> string?
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask2.GenerateFullPathToTool() -> string?
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask2.LogEventsFromTextOutput(string! singleLine, Microsoft.Build.Framework.MessageImportance messageImportance) -> void
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask2.ToolName.get -> string?
static Microsoft.TestPlatform.Build.Trace.Tracing.Trace(string! message) -> void
static Microsoft.TestPlatform.Build.Trace.Tracing.traceEnabled -> bool
-static Microsoft.TestPlatform.Build.Utils.ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(string! arg) -> string!
diff --git a/src/Microsoft.TestPlatform.Build/Resources/Resources.Designer.cs b/src/Microsoft.TestPlatform.Build/Resources/Resources.Designer.cs
index 689e046619..6800dc697a 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/Resources.Designer.cs
+++ b/src/Microsoft.TestPlatform.Build/Resources/Resources.Designer.cs
@@ -10,7 +10,6 @@
namespace Microsoft.TestPlatform.Build.Resources {
using System;
- using System.Reflection;
///
@@ -20,7 +19,7 @@ namespace Microsoft.TestPlatform.Build.Resources {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -40,7 +39,7 @@ internal Resources() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TestPlatform.Build.Resources.Resources", typeof(Resources).GetTypeInfo().Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TestPlatform.Build.Resources.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -89,7 +88,16 @@ internal static string NoIsTestProjectProperty {
}
///
- /// Looks up a localized string similar to Test run for {0}({1}).
+ /// Looks up a localized string similar to Test file path cannot be empty or null..
+ ///
+ internal static string TestFilePathCannotBeEmptyOrNull {
+ get {
+ return ResourceManager.GetString("TestFilePathCannotBeEmptyOrNull", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Test run for {0} ({1}).
///
internal static string TestRunningSummary {
get {
diff --git a/src/Microsoft.TestPlatform.Build/Resources/Resources.resx b/src/Microsoft.TestPlatform.Build/Resources/Resources.resx
index e3277bc036..ff08e2a3bf 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/Resources.resx
+++ b/src/Microsoft.TestPlatform.Build/Resources/Resources.resx
@@ -126,6 +126,9 @@
Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+
+ Test file path cannot be empty or null.
+
Test run for {0} ({1})
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.cs.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.cs.xlf
index b74c6a609b..879716f63d 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.cs.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.cs.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Sestavení bylo dokončeno.
-
-
-
- Build started, please wait...
- Začalo sestavování. Počkejte prosím...
-
-
-
- Test run for {0} ({1})
- Testovací běh pro {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Upozornění: Aktualizujte odkaz na balíček Microsoft.NET.Test.Sdk na verzi 15.8.0 nebo novější, aby se získalo pokrytí kódu.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Přeskakuje se spuštění testu pro projekt {0}. Pokud chcete spustit testy pomocí příkazu dotnet test, přidejte do souboru projektu vlastnost <IsTestProject>true</IsTestProject>.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Sestavení bylo dokončeno.
+
+
+
+ Build started, please wait...
+ Začalo sestavování. Počkejte prosím...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Testovací běh pro {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Upozornění: Aktualizujte odkaz na balíček Microsoft.NET.Test.Sdk na verzi 15.8.0 nebo novější, aby se získalo pokrytí kódu.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Přeskakuje se spuštění testu pro projekt {0}. Pokud chcete spustit testy pomocí příkazu dotnet test, přidejte do souboru projektu vlastnost <IsTestProject>true</IsTestProject>.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.de.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.de.xlf
index 097000b274..0ca2507fb9 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.de.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.de.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Buildvorgang abgeschlossen.
-
-
-
- Build started, please wait...
- Buildvorgang gestartet, bitte warten...
-
-
-
- Test run for {0} ({1})
- Testlauf für "{0}" ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Warnung: Aktualisieren Sie die Microsoft.NET.Test.Sdk-Paketreferenz auf Version 15.8.0 oder höher, um von Code Coverage zu profitieren.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Die Ausführung des Tests für das Projekt "{0}" wird übersprungen. Um Tests mit "dotnet test" auszuführen, fügen Sie der Projektdatei die Eigenschaft <IsTestProject>true</IsTestProject> hinzu.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Buildvorgang abgeschlossen.
+
+
+
+ Build started, please wait...
+ Buildvorgang gestartet, bitte warten...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Testlauf für "{0}" ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Warnung: Aktualisieren Sie die Microsoft.NET.Test.Sdk-Paketreferenz auf Version 15.8.0 oder höher, um von Code Coverage zu profitieren.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Die Ausführung des Tests für das Projekt "{0}" wird übersprungen. Um Tests mit "dotnet test" auszuführen, fügen Sie der Projektdatei die Eigenschaft <IsTestProject>true</IsTestProject> hinzu.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.es.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.es.xlf
index 663b65b466..c9cea130b0 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.es.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.es.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Se completó la compilación.
-
-
-
- Build started, please wait...
- Compilación iniciada, espere...
-
-
-
- Test run for {0} ({1})
- Serie de pruebas para {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Advertencia: Actualice la referencia del paquete Microsoft.NET.Test.Sdk a la versión 15.8.0 o posterior para recopilar la cobertura de código.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Omitiendo la ejecución de la prueba para el proyecto {0}. Para ejecutar pruebas con dotnet test, agregue la propiedad "<IsTestProject>true</IsTestProject>" al archivo del proyecto.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Se completó la compilación.
+
+
+
+ Build started, please wait...
+ Compilación iniciada, espere...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Serie de pruebas para {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Advertencia: Actualice la referencia del paquete Microsoft.NET.Test.Sdk a la versión 15.8.0 o posterior para recopilar la cobertura de código.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Omitiendo la ejecución de la prueba para el proyecto {0}. Para ejecutar pruebas con dotnet test, agregue la propiedad "<IsTestProject>true</IsTestProject>" al archivo del proyecto.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.fr.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.fr.xlf
index b8f5761abf..74d554987b 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.fr.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.fr.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Fin de la build.
-
-
-
- Build started, please wait...
- La build a démarré. Patientez…
-
-
-
- Test run for {0} ({1})
- Série de tests pour {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Avertissement : mettez à jour la référence de package Microsoft.NET.Test.Sdk vers la version 15.8.0 ou ultérieure pour collecter la couverture du code.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Le test en cours d'exécution est ignoré pour le projet {0}. Pour exécuter des tests avec dotnet test, ajoutez la propriété "<IsTestProject>true</IsTestProject>" au fichier projet.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Fin de la build.
+
+
+
+ Build started, please wait...
+ La build a démarré. Patientez…
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Série de tests pour {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Avertissement : mettez à jour la référence de package Microsoft.NET.Test.Sdk vers la version 15.8.0 ou ultérieure pour collecter la couverture du code.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Le test en cours d'exécution est ignoré pour le projet {0}. Pour exécuter des tests avec dotnet test, ajoutez la propriété "<IsTestProject>true</IsTestProject>" au fichier projet.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.it.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.it.xlf
index 6c707ff8d9..f4ce72fd43 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.it.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.it.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Compilazione completata.
-
-
-
- Build started, please wait...
- Compilazione avviata. Attendere...
-
-
-
- Test run for {0} ({1})
- Esecuzione dei test per {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Avviso: per raccogliere i dati di code coverage, aggiornare il riferimento al pacchetto Microsoft.NET.Test.Sdk alla versione 15.8.0 o successiva.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- L'esecuzione del test per il progetto {0} verrà ignorata. Per eseguire test con dotnet test, aggiungere la proprietà "<IsTestProject>true</IsTestProject>" al file di progetto.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Compilazione completata.
+
+
+
+ Build started, please wait...
+ Compilazione avviata. Attendere...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Esecuzione dei test per {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Avviso: per raccogliere i dati di code coverage, aggiornare il riferimento al pacchetto Microsoft.NET.Test.Sdk alla versione 15.8.0 o successiva.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ L'esecuzione del test per il progetto {0} verrà ignorata. Per eseguire test con dotnet test, aggiungere la proprietà "<IsTestProject>true</IsTestProject>" al file di progetto.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ja.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ja.xlf
index 17beb21646..dd12070d45 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ja.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ja.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- ビルドが完了しました。
-
-
-
- Build started, please wait...
- ビルドが開始されました。しばらくお待ちください...
-
-
-
- Test run for {0} ({1})
- {0} ({1}) のテスト実行
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- 警告: コード カバレッジを収集するには、Microsoft.NET.Test.Sdk パッケージ参照をバージョン 15.8.0 以降に更新してください。
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- プロジェクト {0} へのテストの実行をスキップしています。dotnet テストでテストを実行するには、"<IsTestProject>true</IsTestProject>" プロパティをプロジェクト ファイルに追加します。
-
-
-
-
+
+
+
+
+
+ Build completed.
+ ビルドが完了しました。
+
+
+
+ Build started, please wait...
+ ビルドが開始されました。しばらくお待ちください...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ {0} ({1}) のテスト実行
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ 警告: コード カバレッジを収集するには、Microsoft.NET.Test.Sdk パッケージ参照をバージョン 15.8.0 以降に更新してください。
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ プロジェクト {0} へのテストの実行をスキップしています。dotnet テストでテストを実行するには、"<IsTestProject>true</IsTestProject>" プロパティをプロジェクト ファイルに追加します。
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ko.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ko.xlf
index 83ae74691e..9068a8fc2b 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ko.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ko.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- 빌드가 완료되었습니다.
-
-
-
- Build started, please wait...
- 빌드가 시작되었습니다. 잠시 기다려 주세요.
-
-
-
- Test run for {0} ({1})
- {0}({1})에 대한 테스트 실행
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- 경고: 코드 검사를 수집하려면 Microsoft.NET.Test.Sdk 패키지 참조를 버전 15.8.0 이상으로 업데이트하세요.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- 프로젝트 {0}에 대한 테스트 실행을 건너뜁니다. dotnet 테스트와 함께 테스트를 실행하려면 "<IsTestProject>true</IsTestProject>" 속성을 프로젝트 파일에 추가합니다.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ 빌드가 완료되었습니다.
+
+
+
+ Build started, please wait...
+ 빌드가 시작되었습니다. 잠시 기다려 주세요.
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ {0}({1})에 대한 테스트 실행
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ 경고: 코드 검사를 수집하려면 Microsoft.NET.Test.Sdk 패키지 참조를 버전 15.8.0 이상으로 업데이트하세요.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ 프로젝트 {0}에 대한 테스트 실행을 건너뜁니다. dotnet 테스트와 함께 테스트를 실행하려면 "<IsTestProject>true</IsTestProject>" 속성을 프로젝트 파일에 추가합니다.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pl.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pl.xlf
index 48f474faf4..37c042f7eb 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pl.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pl.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Kompilacja zakończona.
-
-
-
- Build started, please wait...
- Kompilacja została rozpoczęta, czekaj...
-
-
-
- Test run for {0} ({1})
- Przebieg testu dla: {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Ostrzeżenie: zaktualizuj odwołanie do pakietu Microsoft.NET.Test.Sdk do wersji 15.8.0 lub nowszej w celu zbierania danych dotyczących pokrycia kodu.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Pomijanie uruchamiania testu dla projektu {0}. Aby uruchomić testy za pomocą polecenia dotnet test, dodaj właściwość „<IsTestProject>true</IsTestProject>” do pliku projektu.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Kompilacja zakończona.
+
+
+
+ Build started, please wait...
+ Kompilacja została rozpoczęta, czekaj...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Przebieg testu dla: {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Ostrzeżenie: zaktualizuj odwołanie do pakietu Microsoft.NET.Test.Sdk do wersji 15.8.0 lub nowszej w celu zbierania danych dotyczących pokrycia kodu.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Pomijanie uruchamiania testu dla projektu {0}. Aby uruchomić testy za pomocą polecenia dotnet test, dodaj właściwość „<IsTestProject>true</IsTestProject>” do pliku projektu.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pt-BR.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pt-BR.xlf
index 1fbecc2281..2756f1e9e1 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pt-BR.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.pt-BR.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Build concluído.
-
-
-
- Build started, please wait...
- Build iniciada, aguarde...
-
-
-
- Test run for {0} ({1})
- Execução de teste para {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Aviso: Atualize a referência do pacote Microsoft.NET.Test.Sdk para a versão 15.8.0 ou posterior para coletar a cobertura do código.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Ignorando a execução de teste do projeto {0}. Para executar testes com dotnet test, adicione a propriedade "<IsTestProject>true</IsTestProject>" ao arquivo de projeto.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Build concluído.
+
+
+
+ Build started, please wait...
+ Build iniciada, aguarde...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Execução de teste para {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Aviso: Atualize a referência do pacote Microsoft.NET.Test.Sdk para a versão 15.8.0 ou posterior para coletar a cobertura do código.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Ignorando a execução de teste do projeto {0}. Para executar testes com dotnet test, adicione a propriedade "<IsTestProject>true</IsTestProject>" ao arquivo de projeto.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ru.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ru.xlf
index 754035a805..81366e3f52 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ru.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.ru.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Сборка выполнена.
-
-
-
- Build started, please wait...
- Сборка начата, подождите...
-
-
-
- Test run for {0} ({1})
- Тестовый запуск для {0} ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Внимание. Для сбора данных об объеме протестированного кода обновите пакет Microsoft.NET.Test.Sdk по ссылке как минимум до версии 15.8.0.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- Пропуск выполнения теста для проекта {0}. Чтобы выполнить тесты с помощью теста dotnet, добавьте свойство "<IsTestProject>true</IsTestProject>" в файл проекта.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Сборка выполнена.
+
+
+
+ Build started, please wait...
+ Сборка начата, подождите...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ Тестовый запуск для {0} ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Внимание. Для сбора данных об объеме протестированного кода обновите пакет Microsoft.NET.Test.Sdk по ссылке как минимум до версии 15.8.0.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ Пропуск выполнения теста для проекта {0}. Чтобы выполнить тесты с помощью теста dotnet, добавьте свойство "<IsTestProject>true</IsTestProject>" в файл проекта.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.tr.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.tr.xlf
index 497bf2b840..413bcec06e 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.tr.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.tr.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- Derleme tamamlandı.
-
-
-
- Build started, please wait...
- Derleme başlatıldı. Lütfen bekleyin...
-
-
-
- Test run for {0} ({1})
- {0} ({1}) için test çalıştırması
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- Uyarı: Kod kapsamını toplamak için Microsoft.NET.Test.Sdk paketinin başvurusunu 15.8.0 veya üzeri bir sürüme güncelleştirin.
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- {0} projesi için test çalıştırma atlanıyor. Testleri dotnet test ile çalıştırmak için proje dosyasına "<IsTestProject>true</IsTestProject>" özelliğini ekleyin.
-
-
-
-
+
+
+
+
+
+ Build completed.
+ Derleme tamamlandı.
+
+
+
+ Build started, please wait...
+ Derleme başlatıldı. Lütfen bekleyin...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ {0} ({1}) için test çalıştırması
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ Uyarı: Kod kapsamını toplamak için Microsoft.NET.Test.Sdk paketinin başvurusunu 15.8.0 veya üzeri bir sürüme güncelleştirin.
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ {0} projesi için test çalıştırma atlanıyor. Testleri dotnet test ile çalıştırmak için proje dosyasına "<IsTestProject>true</IsTestProject>" özelliğini ekleyin.
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hans.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hans.xlf
index f853215269..924e973105 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hans.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hans.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- 完成的生成。
-
-
-
- Build started, please wait...
- 已开始生成,请等待...
-
-
-
- Test run for {0} ({1})
- {0} ({1})的测试运行
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- 警告: 将 Microsoft.NET.Test.Sdk 包引用更新为版本 15.8.0 或更高版本,以便收集代码覆盖率。
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- 正在跳过项目 {0} 的运行测试。若要使用 dotnet test 运行 dotnet 测试,请向项目文件添加 "<IsTestProject>true</IsTestProject>" 属性。
-
-
-
-
+
+
+
+
+
+ Build completed.
+ 完成的生成。
+
+
+
+ Build started, please wait...
+ 已开始生成,请等待...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ {0} ({1})的测试运行
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ 警告: 将 Microsoft.NET.Test.Sdk 包引用更新为版本 15.8.0 或更高版本,以便收集代码覆盖率。
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ 正在跳过项目 {0} 的运行测试。若要使用 dotnet test 运行 dotnet 测试,请向项目文件添加 "<IsTestProject>true</IsTestProject>" 属性。
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hant.xlf b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hant.xlf
index 250f0e4166..73db576be3 100644
--- a/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hant.xlf
+++ b/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.zh-Hant.xlf
@@ -1,32 +1,37 @@
-
-
-
-
-
- Build completed.
- 建置完成。
-
-
-
- Build started, please wait...
- 已開始建置,請稍候...
-
-
-
- Test run for {0} ({1})
- {0} 的測試回合 ({1})
-
-
-
- Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
- 警告: 將 Microsoft.NET.Test.Sdk 套件參考更新至版本 15.8.0 或更新版本,才可收集程式碼涵蓋範圍。
-
-
-
- Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
- 跳過專案 {0} 目前正在執行中的測試。若要執行有 dotnet 測試的測試項目,請對專案檔新增 "<IsTestProject>true</IsTestProject>" 屬性。
-
-
-
-
+
+
+
+
+
+ Build completed.
+ 建置完成。
+
+
+
+ Build started, please wait...
+ 已開始建置,請稍候...
+
+
+
+ Test file path cannot be empty or null.
+ Test file path cannot be empty or null.
+
+
+
+ Test run for {0} ({1})
+ {0} 的測試回合 ({1})
+
+
+
+ Warning: Update the Microsoft.NET.Test.Sdk package reference to version 15.8.0 or later to collect code coverage.
+ 警告: 將 Microsoft.NET.Test.Sdk 套件參考更新至版本 15.8.0 或更新版本,才可收集程式碼涵蓋範圍。
+
+
+
+ Skipping running test for project {0}. To run tests with dotnet test add "<IsTestProject>true</IsTestProject>" property to project file.
+ 跳過專案 {0} 目前正在執行中的測試。若要執行有 dotnet 測試的測試項目,請對專案檔新增 "<IsTestProject>true</IsTestProject>" 屬性。
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/ITestTask.cs b/src/Microsoft.TestPlatform.Build/Tasks/ITestTask.cs
new file mode 100644
index 0000000000..ecd6ec5848
--- /dev/null
+++ b/src/Microsoft.TestPlatform.Build/Tasks/ITestTask.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.TestPlatform.Build.Tasks;
+
+internal interface ITestTask : ITask, ICancelableTask
+{
+ ITaskItem? TestFileFullPath { get; set; }
+ string? VSTestSetting { get; set; }
+ ITaskItem[]? VSTestTestAdapterPath { get; set; }
+ string? VSTestFramework { get; set; }
+ string? VSTestPlatform { get; set; }
+ string? VSTestTestCaseFilter { get; set; }
+ string[]? VSTestLogger { get; set; }
+ bool VSTestListTests { get; set; }
+ string? VSTestDiag { get; set; }
+ string[]? VSTestCLIRunSettings { get; set; }
+ ITaskItem? VSTestConsolePath { get; set; }
+ ITaskItem? VSTestResultsDirectory { get; set; }
+ string? VSTestVerbosity { get; set; }
+ string[]? VSTestCollect { get; set; }
+ bool VSTestBlame { get; set; }
+ bool VSTestBlameCrash { get; set; }
+ string? VSTestBlameCrashDumpType { get; set; }
+ bool VSTestBlameCrashCollectAlways { get; set; }
+ bool VSTestBlameHang { get; set; }
+ string? VSTestBlameHangDumpType { get; set; }
+ string? VSTestBlameHangTimeout { get; set; }
+ ITaskItem? VSTestTraceDataCollectorDirectoryPath { get; set; }
+ bool VSTestNoLogo { get; set; }
+ string? VSTestArtifactsProcessingMode { get; set; }
+ string? VSTestSessionCorrelationId { get; set; }
+
+ TaskLoggingHelper Log { get; }
+}
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/TestTaskUtils.cs b/src/Microsoft.TestPlatform.Build/Tasks/TestTaskUtils.cs
new file mode 100644
index 0000000000..97b6fe4ec9
--- /dev/null
+++ b/src/Microsoft.TestPlatform.Build/Tasks/TestTaskUtils.cs
@@ -0,0 +1,239 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.TestPlatform.Build.Tasks;
+
+internal static class TestTaskUtils
+{
+ public static string CreateCommandLineArguments(ITestTask task)
+ {
+ const string codeCoverageString = "Code Coverage";
+ const string vsTestAppName = "vstest.console.dll";
+
+ // We have 2 tasks:
+ // VSTestTask that writes directly to console output and does not write via msbuild
+ // and VSTestTask2 that uses msbuild tools task to capture standard output and translates
+ // all output to Error to msbuild errors.
+ //
+ // Here we are choosing a vstest.console logger to use. Those loggers both write to standard output
+ // and error output in vstest.console process, but MSBuild task is not focusing on writing with nice colors
+ // but instead on writing cohesive messages in one go, so MSBuild can capture them as single message, and not
+ // as 20 different messages for 20 lines.
+ var loggerToUse = task is VSTestTask ? "Console" : "Microsoft.TestPlatform.MSBuildLogger";
+ // User is free to override the logging using the standard vstest.parameters
+ // otherwise we just add the appropriate logger and use the msbuild verbosity
+ // to forward it to the vstest.console logger.
+ var isLoggerSpecifiedByUser = false;
+ var isCollectCodeCoverageEnabled = false;
+ var isRunSettingsEnabled = false;
+
+ var builder = new CommandLineBuilder();
+ builder.AppendSwitch("exec");
+ if (task.VSTestConsolePath != null && !task.VSTestConsolePath.ItemSpec.IsNullOrEmpty())
+ {
+ builder.AppendFileNameIfNotNull(task.VSTestConsolePath);
+ }
+ else
+ {
+ builder.AppendFileNameIfNotNull(vsTestAppName);
+ }
+
+ // TODO log arguments in task
+ if (!task.VSTestSetting.IsNullOrEmpty())
+ {
+ isRunSettingsEnabled = true;
+ builder.AppendSwitchIfNotNull("--settings:", task.VSTestSetting);
+ }
+
+ if (task.VSTestTestAdapterPath != null)
+ {
+ foreach (var arg in task.VSTestTestAdapterPath)
+ {
+ builder.AppendSwitchIfNotNull("--testAdapterPath:", arg);
+ }
+ }
+
+ builder.AppendSwitchIfNotNull("--framework:", task.VSTestFramework);
+
+ // vstest.console only support x86 and x64 for argument platform
+ if (!task.VSTestPlatform.IsNullOrEmpty() && !task.VSTestPlatform.Contains("AnyCPU"))
+ {
+ builder.AppendSwitchIfNotNull("--platform:", task.VSTestPlatform);
+ }
+
+ builder.AppendSwitchIfNotNull("--testCaseFilter:", task.VSTestTestCaseFilter);
+
+ if (task.VSTestLogger != null)
+ {
+ foreach (var arg in task.VSTestLogger)
+ {
+ builder.AppendSwitchIfNotNull("--logger:", arg);
+
+ if (arg != null && arg.StartsWith(loggerToUse, StringComparison.OrdinalIgnoreCase))
+ {
+ System.Diagnostics.Trace.WriteLine($">>>> : User specified logger: {arg}");
+ isLoggerSpecifiedByUser = true;
+ }
+ }
+ }
+
+ builder.AppendSwitchIfNotNull("--resultsDirectory:", task.VSTestResultsDirectory);
+
+ if (task.VSTestListTests)
+ {
+ builder.AppendSwitch("--listTests");
+ }
+
+ builder.AppendSwitchIfNotNull("--diag:", task.VSTestDiag);
+
+ if (task.TestFileFullPath == null || task.TestFileFullPath.ItemSpec.IsNullOrEmpty())
+ {
+ task.Log.LogError(Resources.Resources.TestFilePathCannotBeEmptyOrNull);
+ }
+ else
+ {
+ builder.AppendFileNameIfNotNull(task.TestFileFullPath);
+ }
+
+ // The logger to use (console or msbuild) logger was not specified by user,
+ // add the logger and verbosity, so we know what to use in vstest.console.
+ if (!isLoggerSpecifiedByUser)
+ {
+ string vsTestVerbosity = "minimal";
+ if (!task.VSTestVerbosity.IsNullOrWhiteSpace())
+ {
+ var normalTestLogging = new List() { "n", "normal", "d", "detailed", "diag", "diagnostic" };
+ var quietTestLogging = new List() { "q", "quiet" };
+
+ string taskVsTestVerbosity = task.VSTestVerbosity.ToLowerInvariant();
+ if (normalTestLogging.Contains(taskVsTestVerbosity))
+ {
+ vsTestVerbosity = "normal";
+ }
+ else if (quietTestLogging.Contains(taskVsTestVerbosity))
+ {
+ vsTestVerbosity = "quiet";
+ }
+ }
+
+ builder.AppendSwitchUnquotedIfNotNull("--logger:", $"{loggerToUse};Verbosity={vsTestVerbosity}");
+ }
+
+ if (task.VSTestBlame || task.VSTestBlameCrash || task.VSTestBlameHang)
+ {
+ var dumpArgs = new List();
+ if (task.VSTestBlameCrash || task.VSTestBlameHang)
+ {
+ if (task.VSTestBlameCrash)
+ {
+ dumpArgs.Add("CollectDump");
+ if (task.VSTestBlameCrashCollectAlways)
+ {
+ dumpArgs.Add($"CollectAlways={task.VSTestBlameCrashCollectAlways}");
+ }
+
+ if (!task.VSTestBlameCrashDumpType.IsNullOrEmpty())
+ {
+ dumpArgs.Add($"DumpType={task.VSTestBlameCrashDumpType}");
+ }
+ }
+
+ if (task.VSTestBlameHang)
+ {
+ dumpArgs.Add("CollectHangDump");
+
+ if (!task.VSTestBlameHangDumpType.IsNullOrEmpty())
+ {
+ dumpArgs.Add($"HangDumpType={task.VSTestBlameHangDumpType}");
+ }
+
+ if (!task.VSTestBlameHangTimeout.IsNullOrEmpty())
+ {
+ dumpArgs.Add($"TestTimeout={task.VSTestBlameHangTimeout}");
+ }
+ }
+ }
+
+ if (dumpArgs.Count != 0)
+ {
+ builder.AppendSwitchIfNotNull("--Blame:", string.Join(";", dumpArgs));
+ }
+ else
+ {
+ builder.AppendSwitch("--Blame");
+ }
+ }
+
+ if (task.VSTestCollect != null)
+ {
+ foreach (var arg in task.VSTestCollect)
+ {
+ if (arg == null)
+ {
+ continue;
+ }
+
+ // For collecting code coverage, argument value can be either "Code Coverage" or "Code Coverage;a=b;c=d".
+ // Split the argument with ';' and compare first token value.
+ var tokens = arg.Split(';');
+ if (arg.Equals(codeCoverageString, StringComparison.OrdinalIgnoreCase) ||
+ tokens[0].Equals(codeCoverageString, StringComparison.OrdinalIgnoreCase))
+ {
+ isCollectCodeCoverageEnabled = true;
+ }
+
+ builder.AppendSwitchIfNotNull("--collect:", arg);
+ }
+ }
+
+ if (isCollectCodeCoverageEnabled || isRunSettingsEnabled)
+ {
+ // Pass TraceDataCollector path to vstest.console as TestAdapterPath if --collect "Code Coverage"
+ // or --settings (User can enable code coverage from runsettings) option given.
+ // Not parsing the runsettings for two reason:
+ // 1. To keep no knowledge of runsettings structure in VSTestTask.
+ // 2. Impact of adding adapter path always is minimal. (worst case: loads additional data collector assembly in datacollector process.)
+ // This is required due to currently trace datacollector not ships with dotnet sdk, can be remove once we have
+ // go code coverage x-plat.
+ if (task.VSTestTraceDataCollectorDirectoryPath != null && !task.VSTestTraceDataCollectorDirectoryPath.ItemSpec.IsNullOrEmpty())
+ {
+ builder.AppendSwitchIfNotNull("--testAdapterPath:", task.VSTestTraceDataCollectorDirectoryPath);
+ }
+ else if (isCollectCodeCoverageEnabled)
+ {
+ // Not showing message in runsettings scenario, because we are not sure that code coverage is enabled.
+ // User might be using older Microsoft.NET.Test.Sdk which don't have CodeCoverage infra.
+ task.Log.LogWarning(Resources.Resources.UpdateTestSdkForCollectingCodeCoverage);
+ }
+ }
+
+ if (task.VSTestNoLogo)
+ {
+ builder.AppendSwitch("--nologo");
+ }
+
+ if (string.Equals(task.VSTestArtifactsProcessingMode, "collect", StringComparison.OrdinalIgnoreCase))
+ {
+ builder.AppendSwitch("--artifactsProcessingMode-collect");
+ }
+
+ builder.AppendSwitchIfNotNull("--testSessionCorrelationId:", task.VSTestSessionCorrelationId);
+
+ // VSTestCLIRunSettings should be last argument as vstest.console ignore options after "--" (CLIRunSettings option).
+ if (task.VSTestCLIRunSettings != null)
+ {
+ builder.AppendSwitch("--");
+ foreach (var arg in task.VSTestCLIRunSettings)
+ {
+ builder.AppendSwitchIfNotNull(string.Empty, arg);
+ }
+ }
+
+ return builder.ToString();
+ }
+}
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingApp.cs b/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingApp.cs
deleted file mode 100644
index 618cdf342c..0000000000
--- a/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingApp.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-
-using Microsoft.TestPlatform.Build.Trace;
-using Microsoft.TestPlatform.Build.Utils;
-
-namespace Microsoft.TestPlatform.Build.Tasks;
-
-public class VSTestForwardingApp
-{
- private const string HostExe = "dotnet";
- private readonly List _allArgs = new();
- private int _activeProcessId;
-
- public VSTestForwardingApp(string vsTestExePath, IEnumerable argsToForward)
- {
- _allArgs.Add("exec");
-
- // Ensure that path to vstest.console is whitespace friendly. User may install
- // dotnet-cli to any folder containing whitespace (e.g. VS installs to program files).
- // Arguments are already whitespace friendly.
- _allArgs.Add(ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(vsTestExePath));
- _allArgs.AddRange(argsToForward);
- }
-
- public int Execute()
- {
- var processInfo = new ProcessStartInfo
- {
- FileName = HostExe,
- Arguments = string.Join(" ", _allArgs),
- UseShellExecute = false,
- };
-
- Tracing.Trace("VSTest: Starting vstest.console...");
- Tracing.Trace("VSTest: Arguments: " + processInfo.FileName + " " + processInfo.Arguments);
-
- using var activeProcess = new Process { StartInfo = processInfo };
- activeProcess.Start();
- _activeProcessId = activeProcess.Id;
-
- activeProcess.WaitForExit();
- Tracing.Trace("VSTest: Exit code: " + activeProcess.ExitCode);
- return activeProcess.ExitCode;
- }
-
- public void Cancel()
- {
- try
- {
- Process.GetProcessById(_activeProcessId).Kill();
- }
- catch (ArgumentException ex)
- {
- Tracing.Trace($"VSTest: Killing process throws ArgumentException with the following message {ex}. It may be that process is not running");
- }
- }
-}
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs b/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
index 7c05e36683..413e58acad 100644
--- a/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
+++ b/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
@@ -2,84 +2,56 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.TestPlatform.Build.Trace;
-using Microsoft.TestPlatform.Build.Utils;
namespace Microsoft.TestPlatform.Build.Tasks;
-public class VSTestTask : Task, ICancelableTask
+public class VSTestTask : Task, ITestTask
{
- // The process which is invoking vstest.console
- private VSTestForwardingApp? _vsTestForwardingApp;
+ private int _activeProcessId;
- private const string CodeCoverageString = "Code Coverage";
-
- public string? TestFileFullPath { get; set; }
+ private const string DotnetExe = "dotnet";
+ [Required]
+ public ITaskItem? TestFileFullPath { get; set; }
public string? VSTestSetting { get; set; }
-
- public string[]? VSTestTestAdapterPath { get; set; }
-
+ public ITaskItem[]? VSTestTestAdapterPath { get; set; }
public string? VSTestFramework { get; set; }
-
public string? VSTestPlatform { get; set; }
-
public string? VSTestTestCaseFilter { get; set; }
-
public string[]? VSTestLogger { get; set; }
-
- public string? VSTestListTests { get; set; }
-
+ public bool VSTestListTests { get; set; }
public string? VSTestDiag { get; set; }
-
public string[]? VSTestCLIRunSettings { get; set; }
-
[Required]
- // Initialized to empty string to allow declaring as non-nullable, the property is marked as
- // required so we can ensure that the property is set to non-null before the task is executed.
- public string VSTestConsolePath { get; set; } = "";
-
- public string? VSTestResultsDirectory { get; set; }
-
+ public ITaskItem? VSTestConsolePath { get; set; }
+ public ITaskItem? VSTestResultsDirectory { get; set; }
public string? VSTestVerbosity { get; set; }
-
public string[]? VSTestCollect { get; set; }
-
- public string? VSTestBlame { get; set; }
-
- public string? VSTestBlameCrash { get; set; }
-
+ public bool VSTestBlame { get; set; }
+ public bool VSTestBlameCrash { get; set; }
public string? VSTestBlameCrashDumpType { get; set; }
-
- public string? VSTestBlameCrashCollectAlways { get; set; }
-
- public string? VSTestBlameHang { get; set; }
-
+ public bool VSTestBlameCrashCollectAlways { get; set; }
+ public bool VSTestBlameHang { get; set; }
public string? VSTestBlameHangDumpType { get; set; }
-
public string? VSTestBlameHangTimeout { get; set; }
-
- public string? VSTestTraceDataCollectorDirectoryPath { get; set; }
-
- public string? VSTestNoLogo { get; set; }
-
+ public ITaskItem? VSTestTraceDataCollectorDirectoryPath { get; set; }
+ public bool VSTestNoLogo { get; set; }
public string? VSTestArtifactsProcessingMode { get; set; }
-
public string? VSTestSessionCorrelationId { get; set; }
public override bool Execute()
{
var traceEnabledValue = Environment.GetEnvironmentVariable("VSTEST_BUILD_TRACE");
- Tracing.traceEnabled = !traceEnabledValue.IsNullOrEmpty() && traceEnabledValue.Equals("1", StringComparison.OrdinalIgnoreCase);
+ Tracing.traceEnabled = string.Equals(traceEnabledValue, "1", StringComparison.OrdinalIgnoreCase);
var debugEnabled = Environment.GetEnvironmentVariable("VSTEST_BUILD_DEBUG");
- if (!debugEnabled.IsNullOrEmpty() && debugEnabled.Equals("1", StringComparison.Ordinal))
+ if (string.Equals(debugEnabled, "1", StringComparison.Ordinal))
{
Console.WriteLine("Waiting for debugger attach...");
@@ -96,248 +68,43 @@ public override bool Execute()
// Avoid logging "Task returned false but did not log an error." on test failure, because we don't
// write MSBuild error. https://github.com/dotnet/msbuild/blob/51a1071f8871e0c93afbaf1b2ac2c9e59c7b6491/src/Framework/IBuildEngine7.cs#L12
- var allowfailureWithoutError = BuildEngine.GetType().GetProperty("AllowFailureWithoutError");
- allowfailureWithoutError?.SetValue(BuildEngine, true);
+ var allowFailureWithoutError = BuildEngine.GetType().GetProperty("AllowFailureWithoutError");
+ allowFailureWithoutError?.SetValue(BuildEngine, true);
+
+ var processInfo = new ProcessStartInfo
+ {
+ FileName = DotnetExe,
+ Arguments = TestTaskUtils.CreateCommandLineArguments(this),
+ UseShellExecute = false,
+ };
- _vsTestForwardingApp = new VSTestForwardingApp(VSTestConsolePath, CreateArgument());
if (!VSTestFramework.IsNullOrEmpty())
{
Console.WriteLine(Resources.Resources.TestRunningSummary, TestFileFullPath, VSTestFramework);
}
- return _vsTestForwardingApp.Execute() == 0;
- }
-
- public void Cancel()
- {
- Tracing.Trace("VSTest: Killing the process...");
- _vsTestForwardingApp?.Cancel();
- }
-
- internal IEnumerable CreateArgument()
- {
- var allArgs = AddArgs();
-
- // VSTestCLIRunSettings should be last argument in allArgs as vstest.console ignore options after "--"(CLIRunSettings option).
- AddCliRunSettingsArgs(allArgs);
+ Tracing.Trace("VSTest: Starting vstest.console...");
+ Tracing.Trace($"VSTest: Arguments: {processInfo.FileName} {processInfo.Arguments}");
- return allArgs;
- }
+ using var activeProcess = new Process { StartInfo = processInfo };
+ activeProcess.Start();
+ _activeProcessId = activeProcess.Id;
- private void AddCliRunSettingsArgs(List allArgs)
- {
- if (VSTestCLIRunSettings != null && VSTestCLIRunSettings.Length > 0)
- {
- allArgs.Add("--");
- foreach (var arg in VSTestCLIRunSettings)
- {
- allArgs.Add(ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(arg));
- }
- }
+ activeProcess.WaitForExit();
+ Tracing.Trace($"VSTest: Exit code: {activeProcess.ExitCode}");
+ return activeProcess.ExitCode == 0;
}
- private List AddArgs()
+ public void Cancel()
{
- var isConsoleLoggerSpecifiedByUser = false;
- var isCollectCodeCoverageEnabled = false;
- var isRunSettingsEnabled = false;
- var allArgs = new List();
-
- // TODO log arguments in task
- if (!VSTestSetting.IsNullOrEmpty())
- {
- isRunSettingsEnabled = true;
- allArgs.Add("--settings:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestSetting));
- }
-
- if (VSTestTestAdapterPath != null && VSTestTestAdapterPath.Length > 0)
- {
- foreach (var arg in VSTestTestAdapterPath)
- {
- allArgs.Add("--testAdapterPath:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(arg));
- }
- }
-
- if (!VSTestFramework.IsNullOrEmpty())
- {
- allArgs.Add("--framework:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestFramework));
- }
-
- // vstest.console only support x86 and x64 for argument platform
- if (!VSTestPlatform.IsNullOrEmpty() && !VSTestPlatform.Contains("AnyCPU"))
- {
- allArgs.Add("--platform:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestPlatform));
- }
-
- if (!VSTestTestCaseFilter.IsNullOrEmpty())
- {
- allArgs.Add("--testCaseFilter:" +
- ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestTestCaseFilter));
- }
-
- if (VSTestLogger != null && VSTestLogger.Length > 0)
- {
- foreach (var arg in VSTestLogger)
- {
- allArgs.Add("--logger:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(arg));
-
- if (arg.StartsWith("console", StringComparison.OrdinalIgnoreCase))
- {
- isConsoleLoggerSpecifiedByUser = true;
- }
- }
- }
-
- if (!VSTestResultsDirectory.IsNullOrEmpty())
- {
- allArgs.Add("--resultsDirectory:" +
- ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestResultsDirectory));
- }
-
- if (!VSTestListTests.IsNullOrEmpty())
- {
- allArgs.Add("--listTests");
- }
-
- if (!VSTestDiag.IsNullOrEmpty())
- {
- allArgs.Add("--Diag:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestDiag));
- }
-
- if (TestFileFullPath.IsNullOrEmpty())
- {
- Log.LogError("Test file path cannot be empty or null.");
- }
- else
- {
- allArgs.Add(ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(TestFileFullPath));
- }
-
- // Console logger was not specified by user, but verbosity was, hence add default console logger with verbosity as specified
- if (!VSTestVerbosity.IsNullOrWhiteSpace() && !isConsoleLoggerSpecifiedByUser)
- {
- var normalTestLogging = new List() { "n", "normal", "d", "detailed", "diag", "diagnostic" };
- var quietTestLogging = new List() { "q", "quiet" };
-
- string vsTestVerbosity = "minimal";
- if (normalTestLogging.Contains(VSTestVerbosity.ToLowerInvariant()))
- {
- vsTestVerbosity = "normal";
- }
- else if (quietTestLogging.Contains(VSTestVerbosity.ToLowerInvariant()))
- {
- vsTestVerbosity = "quiet";
- }
-
- allArgs.Add("--logger:Console;Verbosity=" + vsTestVerbosity);
- }
-
- var blameCrash = !VSTestBlameCrash.IsNullOrEmpty();
- var blameHang = !VSTestBlameHang.IsNullOrEmpty();
- if (!VSTestBlame.IsNullOrEmpty() || blameCrash || blameHang)
- {
- var blameArgs = "--Blame";
-
- var dumpArgs = new List();
- if (blameCrash || blameHang)
- {
- if (blameCrash)
- {
- dumpArgs.Add("CollectDump");
- if (!VSTestBlameCrashCollectAlways.IsNullOrEmpty())
- {
- dumpArgs.Add($"CollectAlways={VSTestBlameCrashCollectAlways}");
- }
-
- if (!VSTestBlameCrashDumpType.IsNullOrEmpty())
- {
- dumpArgs.Add($"DumpType={VSTestBlameCrashDumpType}");
- }
- }
-
- if (blameHang)
- {
- dumpArgs.Add("CollectHangDump");
-
- if (!VSTestBlameHangDumpType.IsNullOrEmpty())
- {
- dumpArgs.Add($"HangDumpType={VSTestBlameHangDumpType}");
- }
-
- if (!VSTestBlameHangTimeout.IsNullOrEmpty())
- {
- dumpArgs.Add($"TestTimeout={VSTestBlameHangTimeout}");
- }
- }
-
- if (dumpArgs.Count != 0)
- {
- blameArgs += $":\"{string.Join(";", dumpArgs)}\"";
- }
- }
-
- allArgs.Add(blameArgs);
- }
-
- if (VSTestCollect != null && VSTestCollect.Length > 0)
- {
- foreach (var arg in VSTestCollect)
- {
- // For collecting code coverage, argument value can be either "Code Coverage" or "Code Coverage;a=b;c=d".
- // Split the argument with ';' and compare first token value.
- var tokens = arg.Split(';');
-
- if (arg.Equals(CodeCoverageString, StringComparison.OrdinalIgnoreCase) ||
- tokens[0].Equals(CodeCoverageString, StringComparison.OrdinalIgnoreCase))
- {
- isCollectCodeCoverageEnabled = true;
- }
-
- allArgs.Add("--collect:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(arg));
- }
- }
-
- if (isCollectCodeCoverageEnabled || isRunSettingsEnabled)
- {
- // Pass TraceDataCollector path to vstest.console as TestAdapterPath if --collect "Code Coverage"
- // or --settings (User can enable code coverage from runsettings) option given.
- // Not parsing the runsettings for two reason:
- // 1. To keep no knowledge of runsettings structure in VSTestTask.
- // 2. Impact of adding adapter path always is minimal. (worst case: loads additional data collector assembly in datacollector process.)
- // This is required due to currently trace datacollector not ships with dotnet sdk, can be remove once we have
- // go code coverage x-plat.
- if (!VSTestTraceDataCollectorDirectoryPath.IsNullOrEmpty())
- {
- allArgs.Add("--testAdapterPath:" +
- ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(
- VSTestTraceDataCollectorDirectoryPath));
- }
- else
- {
- if (isCollectCodeCoverageEnabled)
- {
- // Not showing message in runsettings scenario, because we are not sure that code coverage is enabled.
- // User might be using older Microsoft.NET.Test.Sdk which don't have CodeCoverage infra.
- Console.WriteLine(Resources.Resources.UpdateTestSdkForCollectingCodeCoverage);
- }
- }
- }
-
- if (!VSTestNoLogo.IsNullOrWhiteSpace())
- {
- allArgs.Add("--nologo");
- }
-
- if (!VSTestArtifactsProcessingMode.IsNullOrEmpty() && VSTestArtifactsProcessingMode.Equals("collect", StringComparison.OrdinalIgnoreCase))
+ Tracing.Trace("VSTest: Killing the process...");
+ try
{
- allArgs.Add("--artifactsProcessingMode-collect");
+ Process.GetProcessById(_activeProcessId).Kill();
}
-
- if (!VSTestSessionCorrelationId.IsNullOrEmpty())
+ catch (ArgumentException ex)
{
- allArgs.Add("--testSessionCorrelationId:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestSessionCorrelationId));
+ Tracing.Trace($"VSTest: Killing process throws ArgumentException with the following message {ex}. It may be that process is not running");
}
-
- return allArgs;
}
}
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask2.cs b/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask2.cs
new file mode 100644
index 0000000000..d99c3e89d0
--- /dev/null
+++ b/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask2.cs
@@ -0,0 +1,165 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.TestPlatform.Build.Tasks;
+
+public class VSTestTask2 : ToolTask, ITestTask
+{
+ [Required]
+ public ITaskItem? TestFileFullPath { get; set; }
+ public string? VSTestSetting { get; set; }
+ public ITaskItem[]? VSTestTestAdapterPath { get; set; }
+ public string? VSTestFramework { get; set; }
+ public string? VSTestPlatform { get; set; }
+ public string? VSTestTestCaseFilter { get; set; }
+ public string[]? VSTestLogger { get; set; }
+ public bool VSTestListTests { get; set; }
+ public string? VSTestDiag { get; set; }
+ public string[]? VSTestCLIRunSettings { get; set; }
+ [Required]
+ public ITaskItem? VSTestConsolePath { get; set; }
+ public ITaskItem? VSTestResultsDirectory { get; set; }
+ public string? VSTestVerbosity { get; set; }
+ public string[]? VSTestCollect { get; set; }
+ public bool VSTestBlame { get; set; }
+ public bool VSTestBlameCrash { get; set; }
+ public string? VSTestBlameCrashDumpType { get; set; }
+ public bool VSTestBlameCrashCollectAlways { get; set; }
+ public bool VSTestBlameHang { get; set; }
+ public string? VSTestBlameHangDumpType { get; set; }
+ public string? VSTestBlameHangTimeout { get; set; }
+ public ITaskItem? VSTestTraceDataCollectorDirectoryPath { get; set; }
+ public bool VSTestNoLogo { get; set; }
+ public string? VSTestArtifactsProcessingMode { get; set; }
+ public string? VSTestSessionCorrelationId { get; set; }
+
+
+ private readonly string _errorSplitter = "||||";
+ private readonly string[] _errorSplitterArray = new[] { "||||" };
+
+ private readonly string _fullErrorSplitter = "~~~~";
+ private readonly string[] _fullErrorSplitterArray = new[] { "~~~~" };
+
+ private readonly string _fullErrorNewlineSplitter = "!!!!";
+
+ protected override string? ToolName
+ {
+ get
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ return "dotnet.exe";
+ else
+ return "dotnet";
+ }
+ }
+
+ public VSTestTask2()
+ {
+ LogStandardErrorAsError = false;
+ StandardOutputImportance = "Normal";
+ }
+
+ protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
+ {
+ if (singleLine.StartsWith(_errorSplitter))
+ {
+ var parts = singleLine.Split(_errorSplitterArray, StringSplitOptions.None);
+ if (parts.Length == 5)
+ {
+ var line = 0;
+ var file = parts[1];
+ var _ = !StringUtils.IsNullOrWhiteSpace(parts[3]) && int.TryParse(parts[2], out line);
+ var code = parts[3];
+ var message = parts[4];
+
+ // Join them with space if both are not null,
+ // otherwise use the one that is not null.
+ string? error = code != null && message != null
+ ? code + " " + message
+ : code ?? message;
+
+ file ??= string.Empty;
+
+ Log.LogError(null, "VSTEST1", null, file, line, 0, 0, 0, error, null);
+ return;
+ }
+ }
+
+ if (singleLine.StartsWith(_fullErrorSplitter))
+ {
+ var parts = singleLine.Split(_fullErrorSplitterArray, StringSplitOptions.None);
+ if (parts.Length > 1)
+ {
+ var message = parts[1];
+ if (message != null)
+ {
+ message = message.Replace(_fullErrorNewlineSplitter, Environment.NewLine);
+ }
+
+ string? stackTrace = null;
+ if (parts.Length > 2)
+ {
+ stackTrace = parts[2];
+ if (stackTrace != null)
+ {
+ stackTrace = stackTrace.Replace(_fullErrorNewlineSplitter, Environment.NewLine);
+ }
+ }
+
+ var logMessage = $"{message}{Environment.NewLine}StackTrace:{Environment.NewLine}{stackTrace}";
+
+ Log.LogMessage(MessageImportance.Low, logMessage);
+ return;
+ }
+ }
+
+ base.LogEventsFromTextOutput(singleLine, messageImportance);
+ }
+
+ protected override string? GenerateCommandLineCommands()
+ {
+ return TestTaskUtils.CreateCommandLineArguments(this);
+ }
+
+ protected override string? GenerateFullPathToTool()
+ {
+ if (!ToolPath.IsNullOrEmpty())
+ {
+ return Path.Combine(Path.GetDirectoryName(Path.GetFullPath(ToolPath))!, ToolExe);
+ }
+
+ //TODO: https://github.com/dotnet/sdk/issues/20 Need to get the dotnet path from MSBuild?
+
+ var dhp = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH");
+ if (!dhp.IsNullOrEmpty())
+ {
+ var path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(dhp))!, ToolExe);
+ if (File.Exists(path))
+ {
+ return path;
+ }
+ }
+
+ if (File.Exists(ToolExe))
+ {
+ return Path.GetFullPath(ToolExe);
+ }
+
+ var values = Environment.GetEnvironmentVariable("PATH");
+ foreach (var p in values!.Split(Path.PathSeparator))
+ {
+ var fullPath = Path.Combine(p, ToolExe);
+ if (File.Exists(fullPath))
+ return fullPath;
+ }
+
+ return null;
+ }
+}
diff --git a/src/vstest.console/Internal/MSBuildLogger.cs b/src/vstest.console/Internal/MSBuildLogger.cs
new file mode 100644
index 0000000000..9eb5a820af
--- /dev/null
+++ b/src/vstest.console/Internal/MSBuildLogger.cs
@@ -0,0 +1,223 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+using Microsoft.VisualStudio.TestPlatform.ObjectModel;
+using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
+using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
+using Microsoft.VisualStudio.TestPlatform.Utilities;
+
+using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources;
+
+namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Internal;
+
+// Not using FriendlyName because it
+[ExtensionUri(ExtensionUri)]
+[FriendlyName(FriendlyName)]
+internal class MSBuildLogger : ITestLoggerWithParameters
+{
+ public const string ExtensionUri = "logger://Microsoft/TestPlatform/MSBuildLogger/v1";
+
+ // This name is not so friendly on purpose, because MSBuild seems like a name that someone might have
+ // already claimed, and we will use this just programmatically.
+ public const string FriendlyName = "Microsoft.TestPlatform.MSBuildLogger";
+
+ ///
+ /// Gets instance of IOutput used for sending output.
+ ///
+ /// Protected so this can be detoured for testing purposes.
+ protected static IOutput? Output
+ {
+ get;
+ private set;
+ }
+
+ // Default constructor is needed for a logger to be able to activate it.
+ public MSBuildLogger() { }
+
+ ///
+ /// Constructor added for testing purpose
+ ///
+ internal MSBuildLogger(IOutput output)
+ {
+ Output = output;
+ }
+
+ [MemberNotNull(nameof(Output))]
+ public void Initialize(TestLoggerEvents events, string testRunDirectory)
+ {
+ ValidateArg.NotNull(events, nameof(events));
+
+ Output ??= ConsoleOutput.Instance;
+
+ // Register for the events.
+ // events.TestRunMessage += TestMessageHandler;
+ events.TestResult += TestResultHandler;
+ events.TestRunComplete += TestRunCompleteHandler;
+ // events.TestRunStart += TestRunStartHandler;
+
+ // Register for the discovery events.
+ // events.DiscoveryMessage += TestMessageHandler;
+ }
+
+ public void Initialize(TestLoggerEvents events, Dictionary parameters)
+ {
+ Initialize(events, string.Empty);
+ }
+
+ private void TestRunCompleteHandler(object? sender, TestRunCompleteEventArgs e)
+ {
+ TPDebug.Assert(Output != null, "Initialize should have been called");
+
+ if (e.IsCanceled)
+ {
+ Output.Error(false, CommandLineResources.TestRunCanceled);
+ }
+ else if (e.IsAborted)
+ {
+ if (e.Error == null)
+ {
+ Output.Error(false, CommandLineResources.TestRunAborted);
+ }
+ else
+ {
+ Output.Error(false, CommandLineResources.TestRunAbortedWithError, e.Error);
+ }
+ }
+ }
+
+ private void TestResultHandler(object? sender, TestResultEventArgs e)
+ {
+ ValidateArg.NotNull(sender, nameof(sender));
+ ValidateArg.NotNull(e, nameof(e));
+ TPDebug.Assert(Output != null, "Initialize should have been called.");
+ switch (e.Result.Outcome)
+ {
+ case TestOutcome.Failed:
+ {
+ var result = e.Result;
+ if (!StringUtils.IsNullOrWhiteSpace(result.ErrorStackTrace))
+ {
+ var maxLength = 1000;
+ string? error = null;
+ if (result.ErrorMessage != null)
+ {
+ var oneLineMessage = result.ErrorMessage.Replace(Environment.NewLine, " ");
+ error = oneLineMessage.Length > maxLength ? oneLineMessage.Substring(0, maxLength) : oneLineMessage;
+ }
+
+ string? stackFrame = null;
+ var stackFrames = Regex.Split(result.ErrorStackTrace, Environment.NewLine);
+ string? line = null;
+ string? file = null;
+ string? place = null;
+ if (stackFrames.Length > 0)
+ {
+ foreach (var frame in stackFrames.Take(20))
+ {
+ if (TryGetStackFrameLocation(frame, out line, out file, out place))
+ {
+ break;
+ }
+ }
+ }
+
+ // We did not find any stack frame with location in the first 20 frames.
+ // Try getting location of the test.
+ if (file == null)
+ {
+ if (!StringUtils.IsNullOrEmpty(result.TestCase.CodeFilePath))
+ {
+ // if there are no symbols but we collect source info, us the source info.
+ file = result.TestCase.CodeFilePath;
+ line = result.TestCase.LineNumber > 0 ? result.TestCase.LineNumber.ToString(CultureInfo.InvariantCulture) : null;
+ place = stackFrame;
+ }
+ else
+ {
+ // if there are no symbols and no source info use the dll
+ place = result.TestCase.DisplayName;
+ file = result.TestCase.Source;
+ }
+ }
+
+ place = $"({result.TestCase.DisplayName}) {place}";
+ var message = $"||||{ReplacePipeSeparator(file)}||||{line}||||{ReplacePipeSeparator(place)}||||{ReplacePipeSeparator(error)}";
+
+ Trace.WriteLine(">>>>MESSAGE:" + message);
+ Output.Error(false, message);
+
+ var fullError = $"~~~~{ReplaceTildaSeparator(result.ErrorMessage)}~~~~{ReplaceTildaSeparator(result.ErrorStackTrace)}";
+ Output.Information(false, fullError);
+ return;
+ }
+ else
+ {
+ Output.Error(false, result.DisplayName?.Replace(Environment.NewLine, " ") ?? string.Empty);
+ }
+
+
+ break;
+ }
+ }
+ }
+
+ private static bool TryGetStackFrameLocation(string stackFrame, out string? line, out string? file, out string? place)
+ {
+ // stack frame looks like this ' at Program.$(String[] args) in S:\t\ConsoleApp81\ConsoleApp81\Program.cs:line 9'
+ var match = Regex.Match(stackFrame, @"^\s+at (?.+) in (?.+):line (?\d+)$?");
+
+ line = null;
+ file = null;
+ place = null;
+
+ if (match.Success)
+ {
+ // get the exact info from stack frame.
+ place = match.Groups["code"].Value;
+ file = match.Groups["file"].Value;
+ line = match.Groups["line"].Value;
+ }
+
+ Trace.WriteLine($">>>> {(match.Success ? "MATCH" : "NOMATCH")} {stackFrame}");
+
+ return match.Success;
+ }
+
+
+ private static string? ReplacePipeSeparator(string? text)
+ {
+ if (text == null)
+ {
+ return null;
+ }
+
+ // Remove any occurrence of message splitter.
+ return text.Replace("||||", "____");
+ }
+
+ private static string? ReplaceTildaSeparator(string? text)
+ {
+ if (text == null)
+ {
+ return null;
+ }
+
+ // Remove any occurrence of message splitter.
+ text = text.Replace("~~~~", "____");
+ // Clean up any occurrence of newline splitter.
+ text = text.Replace("!!!!", "____");
+ // Replace newlines with newline splitter.
+ text = text.Replace(Environment.NewLine, "!!!!");
+
+ return text;
+ }
+
+}
diff --git a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
index 8bb19062b6..33d3e4d1dd 100644
--- a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
+++ b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
@@ -809,7 +809,7 @@ private bool UpdateRunSettingsIfRequired(
settingsUpdated |= UpdateDesignMode(document, runConfiguration);
settingsUpdated |= UpdateCollectSourceInformation(document, runConfiguration);
settingsUpdated |= UpdateTargetDevice(navigator, document);
- settingsUpdated |= AddOrUpdateConsoleLogger(document, runConfiguration, loggerRunSettings);
+ settingsUpdated |= AddOrUpdateBuiltInLoggers(document, runConfiguration, loggerRunSettings);
settingsUpdated |= AddOrUpdateBatchSize(document, runConfiguration, isDiscovery);
updatedRunSettingsXml = navigator.OuterXml;
@@ -892,27 +892,43 @@ private string AddFakesConfigurationToRunsettings(IList? sources, string
return runsettings;
}
- private bool AddOrUpdateConsoleLogger(
+ private bool AddOrUpdateBuiltInLoggers(
XmlDocument document,
RunConfiguration runConfiguration,
LoggerRunSettings loggerRunSettings)
{
- // Update console logger settings.
+ // Update built-in logger settings if requested by the user on command line to populate
+ // the default assembly path to those loggers so we can find them.
bool consoleLoggerUpdated = UpdateConsoleLoggerIfExists(document, loggerRunSettings);
+ bool msbuildLoggerUpdated = UpdateMSBuildLoggerIfExists(document, loggerRunSettings);
- // In case of CLI, add console logger if not already present.
bool designMode = runConfiguration.DesignModeSet
? runConfiguration.DesignMode
: _commandLineOptions.IsDesignMode;
- if (!designMode && !consoleLoggerUpdated)
+
+ // In design mode (under IDE) don't add the default logger, we are "logging"
+ // via messages to vstest console wrapper.
+ if (!designMode)
{
- AddConsoleLogger(document, loggerRunSettings);
+ // When we are not in design mode, add one of the default loggers.
+
+ // If msbuild logger was present on the command line, we are being called from
+ // dotnet sdk via vstest task, and should output to msbuild. If user additionally
+ // specified console logger it is allowed but we won't add automatically.
+ if (!msbuildLoggerUpdated) // msbuild logger is not present on command line
+ {
+ if (!consoleLoggerUpdated) // console logger is not present on commandline
+ {
+ // Add console logger because that is the default
+ AddConsoleLogger(document, loggerRunSettings);
+ }
+ }
}
// Update is required:
// 1) in case of CLI;
// 2) in case of design mode if console logger is present in runsettings.
- return !designMode || consoleLoggerUpdated;
+ return !designMode || consoleLoggerUpdated || msbuildLoggerUpdated;
}
private static bool UpdateTargetDevice(
@@ -1135,13 +1151,13 @@ private static bool UpdateConsoleLoggerIfExists(
XmlDocument document,
LoggerRunSettings loggerRunSettings)
{
- var defaultConsoleLogger = new LoggerSettings
+ var logger = new LoggerSettings
{
FriendlyName = ConsoleLogger.FriendlyName,
Uri = new Uri(ConsoleLogger.ExtensionUri)
};
- var existingLoggerIndex = loggerRunSettings.GetExistingLoggerIndex(defaultConsoleLogger);
+ var existingLoggerIndex = loggerRunSettings.GetExistingLoggerIndex(logger);
// Update assemblyQualifiedName and codeBase of existing logger.
if (existingLoggerIndex >= 0)
@@ -1160,6 +1176,41 @@ private static bool UpdateConsoleLoggerIfExists(
return false;
}
+ ///
+ /// Add MSBuild console logger in runsettings if exists.
+ ///
+ /// Runsettings document.
+ /// Logger run settings.
+ /// True if updated console logger in runsettings successfully.
+ private static bool UpdateMSBuildLoggerIfExists(
+ XmlDocument document,
+ LoggerRunSettings loggerRunSettings)
+ {
+ var logger = new LoggerSettings
+ {
+ FriendlyName = MSBuildLogger.FriendlyName,
+ Uri = new Uri(MSBuildLogger.ExtensionUri)
+ };
+
+ var existingLoggerIndex = loggerRunSettings.GetExistingLoggerIndex(logger);
+
+ // Update assemblyQualifiedName and codeBase of existing logger.
+ if (existingLoggerIndex >= 0)
+ {
+ var msBuildLogger = loggerRunSettings.LoggerSettingsList[existingLoggerIndex];
+ msBuildLogger.AssemblyQualifiedName = typeof(MSBuildLogger).AssemblyQualifiedName;
+ msBuildLogger.CodeBase = typeof(MSBuildLogger).Assembly.Location;
+ RunSettingsProviderExtensions.UpdateRunSettingsXmlDocumentInnerXml(
+ document,
+ ObjectModel.Constants.LoggerRunSettingsName,
+ loggerRunSettings.ToXml().InnerXml);
+
+ return true;
+ }
+
+ return false;
+ }
+
private void RunTests(
IRequestData requestData,
TestRunCriteria testRunCriteria,
diff --git a/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs b/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs
index 2f22dffdba..8fab97215f 100644
--- a/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs
+++ b/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/Build.cs
@@ -49,10 +49,22 @@ private static void SetDotnetEnvironment()
private static void CopyAndPatchDotnet()
{
- // TODO: patch dotnet with latest build targets
var patchedDotnetDir = Path.GetFullPath(Path.Combine(Root, "artifacts", "tmp", ".dotnet"));
+ // Copy dotnet.
DirectoryUtils.CopyDirectory(new DirectoryInfo(DotnetDir), new DirectoryInfo(patchedDotnetDir));
+
+ // Copy target file and build task dll into it.
+ var netTestSdkVersion = IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion;
+ var packageName = $"Microsoft.TestPlatform.Build.{netTestSdkVersion}.nupkg";
+ var packagePath = Path.GetFullPath(Path.Combine(IntegrationTestEnvironment.PublishDirectory, packageName));
+
+ // e.g. artifacts\tmp\.dotnet\sdk\
+ var sdkDirectory = Path.Combine(patchedDotnetDir, "sdk");
+ // e.g. artifacts\tmp\.dotnet\sdk\8.0.100-preview.6.23330.14
+ var dotnetSdkDirectory = Directory.GetDirectories(sdkDirectory).Single();
+ DirectoryUtils.CopyDirectory(Path.Combine(packagePath, "lib", "netstandard2.0"), dotnetSdkDirectory);
+ DirectoryUtils.CopyDirectory(Path.Combine(packagePath, "runtimes", "any", "native"), dotnetSdkDirectory);
}
private static void BuildTestAssetsCompatibility()
@@ -337,6 +349,7 @@ private static void BuildTestAssetsAndUnzipPackages()
{
$"Microsoft.TestPlatform.{netTestSdkVersion}.nupkg",
$"Microsoft.TestPlatform.CLI.{netTestSdkVersion}.nupkg",
+ $"Microsoft.TestPlatform.Build.{netTestSdkVersion}.nupkg",
$"Microsoft.CodeCoverage.{netTestSdkVersion}.nupkg",
$"Microsoft.TestPlatform.Portable.{netTestSdkVersion}.nupkg",
};
diff --git a/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs b/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs
new file mode 100644
index 0000000000..831356bd73
--- /dev/null
+++ b/test/Microsoft.TestPlatform.Acceptance.IntegrationTests/DotnetTestMSBuildOutputTests.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Microsoft.TestPlatform.TestUtilities;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Microsoft.TestPlatform.AcceptanceTests;
+
+///
+/// Running dotnet test + csproj and using MSBuild for the output.
+///
+[TestClass]
+public class DotnetTestMSBuildOutputTests : AcceptanceTestBase
+{
+ [TestMethod]
+ // patched dotnet is not published on non-windows systems
+ [TestCategory("Windows-Review")]
+ [NetCoreTargetFrameworkDataSource(useDesktopRunner: false)]
+ public void RunDotnetTestWithCsproj(RunnerInfo runnerInfo)
+ {
+ SetTestEnvironment(_testEnvironment, runnerInfo);
+
+ var projectPath = GetIsolatedTestAsset("SimpleTestProject.csproj");
+ InvokeDotnetTest($@"{projectPath} /p:VsTestUseMSBuildOutput=true /p:PackageVersion={IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}");
+
+ // The output:
+ // Determining projects to restore...
+ // Restored C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\SimpleTestProject.csproj (in 441 ms).
+ // SimpleTestProject -> C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\artifacts\bin\TestAssets\SimpleTestProject\Debug\net462\SimpleTestProject.dll
+ // SimpleTestProject -> C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\artifacts\bin\TestAssets\SimpleTestProject\Debug\netcoreapp3.1\SimpleTestProject.dll
+ // C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\UnitTest1.cs(41): error VSTEST1: (FailingTest) SampleUnitTestProject.UnitTest1.FailingTest() Assert.AreEqual failed. Expected:<2>. Actual:<3>. [C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\SimpleTestProject.csproj::TargetFramework=net462]
+ // C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\UnitTest1.cs(41): error VSTEST1: (FailingTest) SampleUnitTestProject.UnitTest1.FailingTest() Assert.AreEqual failed. Expected:<2>. Actual:<3>. [C:\Users\nohwnd\AppData\Local\Temp\vstest\xvoVt\SimpleTestProject.csproj::TargetFramework=netcoreapp3.1]
+
+ StdOutputContains("error VSTEST1: (FailingTest) SampleUnitTestProject.UnitTest1.FailingTest() Assert.AreEqual failed. Expected:<2>. Actual:<3>.");
+ ExitCodeEquals(1);
+ }
+}
diff --git a/test/Microsoft.TestPlatform.Build.UnitTests/ArgumentEscaperTests.cs b/test/Microsoft.TestPlatform.Build.UnitTests/ArgumentEscaperTests.cs
deleted file mode 100644
index 6b60c1e807..0000000000
--- a/test/Microsoft.TestPlatform.Build.UnitTests/ArgumentEscaperTests.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Microsoft.TestPlatform.Build.Utils.UnitTests;
-
-[TestClass]
-public class ArgumentEscaperTests
-{
- [TestMethod]
- public void EscapeArgForProcessStartShouldAddDoubleQuoteIfThereIsSpace()
- {
- string stringWithSpace = "Some string";
-
- string expected = "\"Some string\"";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithSpace);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void EscapeArgForProcessStartShouldAddDoubleQuoteIfThereIsSpaceAtEnd()
- {
- string stringWithSpaceAtEnd = "Some string ";
-
- string expected = "\"Some string \"";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithSpaceAtEnd);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void EscapeArgForProcessStartShouldHandleForwardSlash()
- {
- string stringWithForwardSlash = "Some/string";
-
- string expected = "Some/string";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithForwardSlash);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void EscapeArgForProcessStartShouldPreserveDoubleQuote()
- {
- string stringWithDoubleQuote = "Some\"string";
-
- string expected = "Some\\\"string";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithDoubleQuote);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void EscapeArgForProcessStartShouldPreserveSingleQuote()
- {
- string stringWithSingleQuote = "Some'string";
-
- string expected = "Some'string";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithSingleQuote);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void EscapeArgForProcessStartShouldPreserveBackSlash()
- {
- string stringWithBackSlash = @"Some\\string";
-
- string expected = "Some\\\\string";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithBackSlash);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void EscapeArgForProcessStartShouldPreserveBackSlashIfStringHasWhiteSpace()
- {
- string stringWithBackSlash = @"Some string With Space\\";
-
- string expected = @"""Some string With Space\\\\""";
- string result = ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(stringWithBackSlash);
-
- Assert.AreEqual(expected, result);
- }
-
- [TestMethod]
- public void ShouldSurroundWithQuotesShouldReturnFalseIfAlreadySurroundWithQuotes()
- {
- string stringSurroundWithQuotes = "\"some string\"";
-
- Assert.IsFalse(ArgumentEscaper.ShouldSurroundWithQuotes(stringSurroundWithQuotes));
- }
-
- [TestMethod]
- public void ShouldSurroundWithQuotesShouldReturnFalseIfItIsNotSurroundWithQuotesAndHasNoWhiteSpace()
- {
- string stringWithoutSpace = "someStringWithNoWhiteSpace";
-
- Assert.IsFalse(ArgumentEscaper.ShouldSurroundWithQuotes(stringWithoutSpace));
- }
-
- [TestMethod]
- public void ShouldSurroundWithQuotesShouldReturnTrueIfItIsNotSurroundWithQuotesAndHasWhiteSpace()
- {
- string stringWithSpace = "some String With WhiteSpace";
-
- Assert.IsTrue(ArgumentEscaper.ShouldSurroundWithQuotes(stringWithSpace));
- }
-
- [TestMethod]
- public void IsSurroundedWithQuotesShouldReturnTrueIfStringIsSurroundedByQuotes()
- {
- string stringSurroundWithQuotes = "\"some string\"";
-
- Assert.IsTrue(ArgumentEscaper.IsSurroundedWithQuotes(stringSurroundWithQuotes));
- }
-
- [TestMethod]
- public void IsSurroundedWithQuotesShouldReturnFalseIfStringIsNotSurroundedByQuotes()
- {
- string stringNotSurroundWithQuotes = "some string";
-
- Assert.IsFalse(ArgumentEscaper.IsSurroundedWithQuotes(stringNotSurroundWithQuotes));
- }
-}
diff --git a/test/Microsoft.TestPlatform.Build.UnitTests/FakeBuildEngine.cs b/test/Microsoft.TestPlatform.Build.UnitTests/FakeBuildEngine.cs
new file mode 100644
index 0000000000..c0d077d74e
--- /dev/null
+++ b/test/Microsoft.TestPlatform.Build.UnitTests/FakeBuildEngine.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections;
+
+using Microsoft.Build.Framework;
+
+namespace Microsoft.TestPlatform.Build.UnitTests;
+
+public class FakeBuildEngine : IBuildEngine
+{
+ public bool ContinueOnError => false;
+
+ public int LineNumberOfTaskNode => 0;
+
+ public int ColumnNumberOfTaskNode => 0;
+
+ public string ProjectFileOfTaskNode => string.Empty;
+
+ public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs)
+ {
+ return false;
+ }
+
+ public void LogCustomEvent(CustomBuildEventArgs e)
+ {
+ }
+
+ public void LogErrorEvent(BuildErrorEventArgs e)
+ {
+ }
+
+ public void LogMessageEvent(BuildMessageEventArgs e)
+ {
+ }
+
+ public void LogWarningEvent(BuildWarningEventArgs e)
+ {
+ }
+}
diff --git a/test/Microsoft.TestPlatform.Build.UnitTests/TestTaskUtilsTests.cs b/test/Microsoft.TestPlatform.Build.UnitTests/TestTaskUtilsTests.cs
new file mode 100644
index 0000000000..7c464bb381
--- /dev/null
+++ b/test/Microsoft.TestPlatform.Build.UnitTests/TestTaskUtilsTests.cs
@@ -0,0 +1,315 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Text.RegularExpressions;
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.TestPlatform.Build.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Microsoft.TestPlatform.Build.UnitTests;
+
+[TestClass]
+public class TestTaskUtilsTests
+{
+ private readonly ITestTask _vsTestTask;
+
+ public TestTaskUtilsTests()
+ {
+ _vsTestTask = new VSTestTask
+ {
+ BuildEngine = new FakeBuildEngine(),
+ TestFileFullPath = new TaskItem(@"C:\path\to\test-assembly.dll"),
+ VSTestFramework = ".NETCoreapp,Version2.0"
+ };
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddOneEntryForCLIRunSettings()
+ {
+ const string arg1 = "RunConfiguration.ResultsDirectory=Path having Space";
+ const string arg2 = "MSTest.DeploymentEnabled";
+
+ _vsTestTask.VSTestCLIRunSettings = new string[2];
+ _vsTestTask.VSTestCLIRunSettings[0] = arg1;
+ _vsTestTask.VSTestCLIRunSettings[1] = arg2;
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, " -- ");
+ StringAssert.Contains(commandline, $"\"{arg1}\"");
+ StringAssert.Contains(commandline, $"{arg2}");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddCLIRunSettingsArgAtEnd()
+ {
+ const string codeCoverageOption = "Code Coverage";
+
+ _vsTestTask.VSTestCollect = new string[] { codeCoverageOption };
+ _vsTestTask.VSTestBlame = true;
+
+ const string arg1 = "RunConfiguration.ResultsDirectory=Path having Space";
+ const string arg2 = "MSTest.DeploymentEnabled";
+
+ _vsTestTask.VSTestCLIRunSettings = new string[2];
+ _vsTestTask.VSTestCLIRunSettings[0] = arg1;
+ _vsTestTask.VSTestCLIRunSettings[1] = arg2;
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, " -- ");
+ StringAssert.Contains(commandline, $"\"{arg1}\"");
+ StringAssert.Contains(commandline, $"{arg2}");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldPassResultsDirectoryCorrectly()
+ {
+ const string resultsDirectoryValue = @"C:\tmp\Results Directory";
+ _vsTestTask.VSTestResultsDirectory = new TaskItem(resultsDirectoryValue);
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, $"--resultsDirectory:\"{_vsTestTask.VSTestResultsDirectory?.ItemSpec}\"");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldNotSetConsoleLoggerVerbosityIfConsoleLoggerIsGivenInArgs()
+ {
+ _vsTestTask.VSTestVerbosity = "diag";
+ _vsTestTask.VSTestLogger = new string[] { "Console;Verbosity=quiet" };
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.DoesNotMatch(commandline, new Regex("(--logger:\"Console;Verbosity=normal\")"));
+ StringAssert.Contains(commandline, "--logger:\"Console;Verbosity=quiet\"");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsn()
+ {
+ _vsTestTask.VSTestVerbosity = "n";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsnormal()
+ {
+ _vsTestTask.VSTestVerbosity = "normal";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsd()
+ {
+ _vsTestTask.VSTestVerbosity = "d";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsdetailed()
+ {
+ _vsTestTask.VSTestVerbosity = "detailed";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsdiag()
+ {
+ _vsTestTask.VSTestVerbosity = "diag";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsdiagnostic()
+ {
+ _vsTestTask.VSTestVerbosity = "diagnostic";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsq()
+ {
+ _vsTestTask.VSTestVerbosity = "q";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=quiet");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsquiet()
+ {
+ _vsTestTask.VSTestVerbosity = "quiet";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=quiet");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToMinimalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsm()
+ {
+ _vsTestTask.VSTestVerbosity = "m";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=minimal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToMinimalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsminimal()
+ {
+ _vsTestTask.VSTestVerbosity = "minimal";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=minimal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsNormalWithCapitalN()
+ {
+ _vsTestTask.VSTestVerbosity = "Normal";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsQuietWithCapitalQ()
+ {
+ _vsTestTask.VSTestVerbosity = "Quiet";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=quiet");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldPreserveWhiteSpaceInLogger()
+ {
+ _vsTestTask.VSTestLogger = new string[] { "trx;LogFileName=foo bar.trx" };
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:\"trx;LogFileName=foo bar.trx\"");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddOneCollectArgumentForEachCollect()
+ {
+ _vsTestTask.VSTestCollect = new string[2];
+
+ _vsTestTask.VSTestCollect[0] = "name1";
+ _vsTestTask.VSTestCollect[1] = "name 2";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--collect:name1");
+ StringAssert.Contains(commandline, "--collect:\"name 2\"");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddMultipleTestAdapterPaths()
+ {
+ _vsTestTask.VSTestTestAdapterPath = new ITaskItem[] { new TaskItem("path1"), new TaskItem("path2") };
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--testAdapterPath:path1");
+ StringAssert.Contains(commandline, "--testAdapterPath:path2");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddMultipleLoggers()
+ {
+ _vsTestTask.VSTestLogger = new string[] { "trx;LogFileName=foo bar.trx", "console" };
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--logger:\"trx;LogFileName=foo bar.trx\"");
+ StringAssert.Contains(commandline, "--logger:console");
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddTraceCollectorDirectoryPathAsTestAdapterForCodeCoverageCollect()
+ {
+ const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedata collector";
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = new TaskItem(traceDataCollectorDirectoryPath);
+ _vsTestTask.VSTestCollect = new string[] { "code coverage" };
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ string expectedArg = $"--testAdapterPath:\"{_vsTestTask.VSTestTraceDataCollectorDirectoryPath?.ItemSpec}\"";
+ StringAssert.Contains(commandline, expectedArg);
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldNotAddTraceCollectorDirectoryPathAsTestAdapterForNonCodeCoverageCollect()
+ {
+ const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedata collector";
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = new TaskItem(traceDataCollectorDirectoryPath);
+ _vsTestTask.VSTestCollect = new string[] { "not code coverage" };
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ string notExpectedArg = $"--testAdapterPath:\"{_vsTestTask.VSTestTraceDataCollectorDirectoryPath?.ItemSpec}\"";
+ StringAssert.DoesNotMatch(commandline, new Regex(Regex.Escape(notExpectedArg)));
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddTraceCollectorDirectoryPathAsTestAdapterIfSettingsGiven()
+ {
+ const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedatacollector\";
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = new TaskItem(traceDataCollectorDirectoryPath);
+ _vsTestTask.VSTestSetting = @"c:\path\to\sample.runsettings";
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ string expectedArg = $"--testAdapterPath:{_vsTestTask.VSTestTraceDataCollectorDirectoryPath?.ItemSpec}";
+ StringAssert.Contains(commandline, expectedArg);
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldNotAddTestAdapterPathIfVSTestTraceDataCollectorDirectoryPathIsEmpty()
+ {
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = null;
+ _vsTestTask.VSTestSetting = @"c:\path\to\sample.runsettings";
+ _vsTestTask.VSTestCollect = new string[] { "code coverage" };
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.DoesNotMatch(commandline, new Regex(@"(--testAdapterPath:)"));
+ }
+
+ [TestMethod]
+ public void CreateArgumentShouldAddNoLogoOptionIfSpecifiedByUser()
+ {
+ _vsTestTask.VSTestNoLogo = true;
+
+ var commandline = TestTaskUtils.CreateCommandLineArguments(_vsTestTask);
+
+ StringAssert.Contains(commandline, "--nologo");
+ }
+}
diff --git a/test/Microsoft.TestPlatform.Build.UnitTests/VsTestTaskTests.cs b/test/Microsoft.TestPlatform.Build.UnitTests/VsTestTaskTests.cs
deleted file mode 100644
index b8884568ba..0000000000
--- a/test/Microsoft.TestPlatform.Build.UnitTests/VsTestTaskTests.cs
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Linq;
-
-using Microsoft.TestPlatform.Build.Tasks;
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Microsoft.TestPlatform.Build.UnitTests;
-
-[TestClass]
-public class VsTestTaskTests
-{
- private readonly VSTestTask _vsTestTask;
-
- public VsTestTaskTests()
- {
- _vsTestTask = new VSTestTask
- {
- TestFileFullPath = @"C:\path\to\test-assembly.dll",
- VSTestFramework = ".NETCoreapp,Version2.0"
- };
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddOneEntryForCLIRunSettings()
- {
- const string arg1 = "RunConfiguration.ResultsDirectory=Path having Space";
- const string arg2 = "MSTest.DeploymentEnabled";
-
- _vsTestTask.VSTestCLIRunSettings = new string[2];
- _vsTestTask.VSTestCLIRunSettings[0] = arg1;
- _vsTestTask.VSTestCLIRunSettings[1] = arg2;
-
- var result = _vsTestTask.CreateArgument().ToArray();
-
- Assert.AreEqual(5, result.Length);
-
- // First, second and third args would be framework:".NETCoreapp,Version2.0", testfilepath and -- respectively.
- Assert.AreEqual($"\"{arg1}\"", result[3]);
- Assert.AreEqual($"{arg2}", result[4]);
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddCliRunSettingsArgAtEnd()
- {
- const string codeCoverageOption = "Code Coverage";
-
- _vsTestTask.VSTestCollect = new string[] { codeCoverageOption };
- _vsTestTask.VSTestBlame = "Blame";
-
- const string arg1 = "RunConfiguration.ResultsDirectory=Path having Space";
- const string arg2 = "MSTest.DeploymentEnabled";
-
- _vsTestTask.VSTestCLIRunSettings = new string[2];
- _vsTestTask.VSTestCLIRunSettings[0] = arg1;
- _vsTestTask.VSTestCLIRunSettings[1] = arg2;
-
- var result = _vsTestTask.CreateArgument().ToArray();
-
- Assert.AreEqual(7, result.Length);
-
- // Following are expected --framework:".NETCoreapp,Version2.0", testfilepath, blame, collect:"Code coverage" -- respectively.
- Assert.AreEqual($"\"{arg1}\"", result[5]);
- Assert.AreEqual($"{arg2}", result[6]);
- }
-
- [TestMethod]
- public void CreateArgumentShouldPassResultsDirectoryCorrectly()
- {
- const string resultsDirectoryValue = @"C:\tmp\Results Directory";
- _vsTestTask.VSTestResultsDirectory = resultsDirectoryValue;
-
- var result = _vsTestTask.CreateArgument().ToArray();
-
- Assert.AreEqual($"--resultsDirectory:\"{resultsDirectoryValue}\"", result[1]);
- }
-
- [TestMethod]
- public void CreateArgumentShouldNotSetConsoleLoggerVerbosityIfConsoleLoggerIsGivenInArgs()
- {
- _vsTestTask.VSTestVerbosity = "diag";
- _vsTestTask.VSTestLogger = new string[] { "Console;Verbosity=quiet" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsn()
- {
- _vsTestTask.VSTestVerbosity = "n";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsnormal()
- {
- _vsTestTask.VSTestVerbosity = "normal";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsd()
- {
- _vsTestTask.VSTestVerbosity = "d";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsdetailed()
- {
- _vsTestTask.VSTestVerbosity = "detailed";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsdiag()
- {
- _vsTestTask.VSTestVerbosity = "diag";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsdiagnostic()
- {
- _vsTestTask.VSTestVerbosity = "diagnostic";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsq()
- {
- _vsTestTask.VSTestVerbosity = "q";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsquiet()
- {
- _vsTestTask.VSTestVerbosity = "quiet";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToMinimalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsm()
- {
- _vsTestTask.VSTestVerbosity = "m";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=minimal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToMinimalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsminimal()
- {
- _vsTestTask.VSTestVerbosity = "minimal";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=minimal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsNormalWithCapitalN()
- {
- _vsTestTask.VSTestVerbosity = "Normal";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerIsNotGivenInArgsAndVerbosityIsQuietWithCapitalQ()
- {
- _vsTestTask.VSTestVerbosity = "Quiet";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldPreserveWhiteSpaceInLogger()
- {
- _vsTestTask.VSTestLogger = new string[] { "trx;LogFileName=foo bar.trx" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:\"trx;LogFileName=foo bar.trx\"")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddOneCollectArgumentForEachCollect()
- {
- _vsTestTask.VSTestCollect = new string[2];
-
- _vsTestTask.VSTestCollect[0] = "name1";
- _vsTestTask.VSTestCollect[1] = "name 2";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--collect:name1")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--collect:\"name 2\"")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddMultipleTestAdapterPaths()
- {
- _vsTestTask.VSTestTestAdapterPath = new string[] { "path1", "path2" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--testAdapterPath:path1")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--testAdapterPath:path2")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddMultipleLoggers()
- {
- _vsTestTask.VSTestLogger = new string[] { "trx;LogFileName=foo bar.trx", "console" };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:\"trx;LogFileName=foo bar.trx\"")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:console")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddTraceCollectorDirectoryPathAsTestAdapterForCodeCoverageCollect()
- {
- const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedata collector";
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = traceDataCollectorDirectoryPath;
- _vsTestTask.VSTestCollect = new string[] { "code coverage" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- const string expectedArg = "--testAdapterPath:\"c:\\path\\to\\tracedata collector\"";
- CollectionAssert.Contains(allArguments, expectedArg, $"Expected argument: '''{expectedArg}''' not present in [{string.Join(", ", allArguments)}]");
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddTraceCollectorDirectoryPathAsTestAdapterForCodeCoverageCollectWithExtraConfigurations()
- {
- const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedata collector";
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = traceDataCollectorDirectoryPath;
- _vsTestTask.VSTestCollect = new string[] { "code coverage;someParameter=someValue" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- const string expectedArg = "--testAdapterPath:\"c:\\path\\to\\tracedata collector\"";
- CollectionAssert.Contains(allArguments, expectedArg, $"Expected argument: '''{expectedArg}''' not present in [{string.Join(", ", allArguments)}]");
- }
-
- [TestMethod]
- public void CreateArgumentShouldNotAddTraceCollectorDirectoryPathAsTestAdapterForNonCodeCoverageCollect()
- {
- const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedata collector";
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = traceDataCollectorDirectoryPath;
- _vsTestTask.VSTestCollect = new string[] { "not code coverage" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- const string notExpectedArg = "--testAdapterPath:\"c:\\path\\to\\tracedata collector\"";
- CollectionAssert.DoesNotContain(allArguments, notExpectedArg, $"Not expected argument: '''{notExpectedArg}''' present in [{string.Join(", ", allArguments)}]");
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddTraceCollectorDirectoryPathAsTestAdapterIfSettingsGiven()
- {
- const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedatacollector\";
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = traceDataCollectorDirectoryPath;
- _vsTestTask.VSTestSetting = @"c:\path\to\sample.runsettings";
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- const string expectedArg = "--testAdapterPath:c:\\path\\to\\tracedatacollector\\";
- CollectionAssert.Contains(allArguments, expectedArg, $"Expected argument: '''{expectedArg}''' not present in [{string.Join(", ", allArguments)}]");
- }
-
- [TestMethod]
- public void CreateArgumentShouldNotAddTestAdapterPathIfVsTestTraceDataCollectorDirectoryPathIsEmpty()
- {
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = string.Empty;
- _vsTestTask.VSTestSetting = @"c:\path\to\sample.runsettings";
- _vsTestTask.VSTestCollect = new string[] { "code coverage" };
-
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNull(Array.Find(allArguments, arg => arg.Contains("--testAdapterPath:")));
- }
-
- [TestMethod]
- public void CreateArgumentShouldAddNoLogoOptionIfSpecifiedByUser()
- {
- _vsTestTask.VSTestNoLogo = "--nologo";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
-
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--nologo")));
- }
-}