diff --git a/src/Microsoft.TestPlatform.Build/ArgumentEscaper.cs b/src/Microsoft.TestPlatform.Build/ArgumentEscaper.cs
deleted file mode 100644
index 704dc54703..0000000000
--- a/src/Microsoft.TestPlatform.Build/ArgumentEscaper.cs
+++ /dev/null
@@ -1,102 +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;
-
-#nullable disable
-
-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..bb54a8496a 100644
--- a/src/Microsoft.TestPlatform.Build/Microsoft.TestPlatform.targets
+++ b/src/Microsoft.TestPlatform.Build/Microsoft.TestPlatform.targets
@@ -12,10 +12,14 @@ Copyright (c) .NET Foundation. All rights reserved.
- Microsoft.TestPlatform.Build.dll
- $([System.IO.Path]::Combine($(MSBuildThisFileDirectory),"vstest.console.dll"))
+ Microsoft.TestPlatform.Build.dll
+ $([System.IO.Path]::Combine($(MSBuildThisFileDirectory),"vstest.console.dll"))
+ False
+ False
+ <_VSTestMSBuildDependsOn Condition="$(_VSTestMSBuildDependsOn) == '' And !$(VSTestNoBuild)">$(MSBuildProjectDefaultTargets)
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
@@ -70,37 +122,36 @@ Copyright (c) .NET Foundation. All rights reserved.
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
diff --git a/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Shipped.txt b/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Shipped.txt
index 9cd80864ae..dc99f77016 100644
--- a/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Shipped.txt
+++ b/src/Microsoft.TestPlatform.Build/PublicAPI/PublicAPI.Shipped.txt
@@ -1,7 +1,56 @@
-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.VSTestForwardingTask
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.Cancel() -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.TestFileFullPath.get -> Microsoft.Build.Framework.ITaskItem
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.TestFileFullPath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlame.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlame.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameCrash.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameCrash.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameCrashCollectAlways.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameCrashCollectAlways.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameCrashDumpType.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameCrashDumpType.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameHang.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameHang.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameHangDumpType.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameHangDumpType.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameHangTimeout.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestBlameHangTimeout.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestCLIRunSettings.get -> string[]
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestCLIRunSettings.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestCollect.get -> string[]
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestCollect.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestConsolePath.get -> Microsoft.Build.Framework.ITaskItem
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestConsolePath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestDiag.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestDiag.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestFramework.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestFramework.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestListTests.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestListTests.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestLogger.get -> string[]
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestLogger.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestNoLogo.get -> bool
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestNoLogo.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestArtifactsProcessingMode.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestArtifactsProcessingMode.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestSessionCorrelationId.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestSessionCorrelationId.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestPlatform.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestPlatform.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestResultsDirectory.get -> Microsoft.Build.Framework.ITaskItem
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestResultsDirectory.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestSetting.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestSetting.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestForwardingTask() -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestTestAdapterPath.get -> Microsoft.Build.Framework.ITaskItem[]
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestTestAdapterPath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestTestCaseFilter.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestTestCaseFilter.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestTraceDataCollectorDirectoryPath.get -> Microsoft.Build.Framework.ITaskItem
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestTraceDataCollectorDirectoryPath.set -> void
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestVerbosity.get -> string
+Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.VSTestVerbosity.set -> void
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.LogType.get -> string
Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.LogType.set -> void
@@ -9,18 +58,17 @@ Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.ProjectFilePath.get -> string
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.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
@@ -30,17 +78,17 @@ 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.VSTestArtifactsProcessingMode.get -> string
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestArtifactsProcessingMode.set -> void
@@ -48,23 +96,24 @@ Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestSessionCorrelationId.get ->
Microsoft.TestPlatform.Build.Tasks.VSTestTask.VSTestSessionCorrelationId.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.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.Trace.Tracing
-Microsoft.TestPlatform.Build.Utils.ArgumentEscaper
+override Microsoft.TestPlatform.Build.Tasks.VSTestForwardingTask.Execute() -> bool
override Microsoft.TestPlatform.Build.Tasks.VSTestLogsTask.Execute() -> bool
-override Microsoft.TestPlatform.Build.Tasks.VSTestTask.Execute() -> bool
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask.GenerateCommandLineCommands() -> string
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask.GenerateFullPathToTool() -> string
+override Microsoft.TestPlatform.Build.Tasks.VSTestTask.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/Tasks/ITestTask.cs b/src/Microsoft.TestPlatform.Build/Tasks/ITestTask.cs
new file mode 100644
index 0000000000..866729357f
--- /dev/null
+++ b/src/Microsoft.TestPlatform.Build/Tasks/ITestTask.cs
@@ -0,0 +1,43 @@
+// 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;
+
+#nullable disable
+
+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/TestTaskExtensions.cs b/src/Microsoft.TestPlatform.Build/Tasks/TestTaskExtensions.cs
new file mode 100644
index 0000000000..f40c676a5a
--- /dev/null
+++ b/src/Microsoft.TestPlatform.Build/Tasks/TestTaskExtensions.cs
@@ -0,0 +1,228 @@
+// 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.Linq;
+
+using Microsoft.Build.Utilities;
+
+#nullable disable
+
+namespace Microsoft.TestPlatform.Build.Tasks;
+
+internal static class TestTaskExtensions
+{
+
+ public static string CreateCommandLineArguments(this ITestTask task)
+ {
+ var isConsoleLoggerSpecifiedByUser = false;
+ var isCollectCodeCoverageEnabled = false;
+ var isRunSettingsEnabled = false;
+
+ var builder = new CommandLineBuilder();
+ builder.AppendSwitch("exec");
+ if (task.VSTestConsolePath != null && !string.IsNullOrEmpty(task.VSTestConsolePath.ItemSpec))
+ {
+ builder.AppendSwitchIfNotNull("", task.VSTestConsolePath);
+ }
+ else
+ {
+ builder.AppendSwitch("vstest.console.dll");
+ }
+
+ // TODO log arguments in task
+ if (!string.IsNullOrEmpty(task.VSTestSetting))
+ {
+ isRunSettingsEnabled = true;
+ builder.AppendSwitchIfNotNull("--settings:", task.VSTestSetting);
+ }
+
+ if (task.VSTestTestAdapterPath != null && task.VSTestTestAdapterPath.Any())
+ {
+ foreach (var arg in task.VSTestTestAdapterPath)
+ {
+ builder.AppendSwitchIfNotNull("--testAdapterPath:", arg);
+ }
+ }
+
+ if (!string.IsNullOrEmpty(task.VSTestFramework))
+ {
+ builder.AppendSwitchIfNotNull("--framework:", task.VSTestFramework);
+ }
+
+ // vstest.console only support x86 and x64 for argument platform
+ if (!string.IsNullOrEmpty(task.VSTestPlatform) && !task.VSTestPlatform.Contains("AnyCPU"))
+ {
+ builder.AppendSwitchIfNotNull("--platform:", task.VSTestPlatform);
+ }
+
+ if (!string.IsNullOrEmpty(task.VSTestTestCaseFilter))
+ {
+ builder.AppendSwitchIfNotNull("--testCaseFilter:", task.VSTestTestCaseFilter);
+ }
+
+ if (task.VSTestLogger != null && task.VSTestLogger.Any())
+ {
+ foreach (var arg in task.VSTestLogger)
+ {
+ builder.AppendSwitchIfNotNull("--logger:", arg);
+
+ if (arg.StartsWith("console", StringComparison.OrdinalIgnoreCase))
+ {
+ isConsoleLoggerSpecifiedByUser = true;
+ }
+ }
+ }
+
+ if (task.VSTestResultsDirectory != null && !string.IsNullOrEmpty(task.VSTestResultsDirectory.ItemSpec))
+ {
+ builder.AppendSwitchIfNotNull("--resultsDirectory:", task.VSTestResultsDirectory);
+ }
+
+ if (task.VSTestListTests)
+ {
+ builder.AppendSwitch("--listTests");
+ }
+
+ if (!string.IsNullOrEmpty(task.VSTestDiag))
+ {
+ builder.AppendSwitchIfNotNull("--Diag:", task.VSTestDiag);
+ }
+
+ if (task.TestFileFullPath != null)
+ {
+ builder.AppendFileNameIfNotNull(task.TestFileFullPath);
+ }
+
+ // Console logger was not specified by user, but verbosity was, hence add default console logger with verbosity as specified
+ if (!string.IsNullOrWhiteSpace(task.VSTestVerbosity) && !isConsoleLoggerSpecifiedByUser)
+ {
+ var normalTestLogging = new List() { "n", "normal", "d", "detailed", "diag", "diagnostic" };
+ var quietTestLogging = new List() { "q", "quiet" };
+
+ string vsTestVerbosity = "minimal";
+ if (normalTestLogging.Contains(task.VSTestVerbosity, StringComparer.InvariantCultureIgnoreCase))
+ {
+ vsTestVerbosity = "normal";
+ }
+ else if (quietTestLogging.Contains(task.VSTestVerbosity, StringComparer.InvariantCultureIgnoreCase))
+ {
+ vsTestVerbosity = "quiet";
+ }
+
+ builder.AppendSwitchUnquotedIfNotNull("--logger:", $"Console;Verbosity={vsTestVerbosity}");
+ }
+
+ if (task.VSTestBlame)
+ {
+ var dumpArgs = new List();
+ if (task.VSTestBlameCrash || task.VSTestBlameHang)
+ {
+ if (task.VSTestBlameCrash)
+ {
+ dumpArgs.Add("CollectDump");
+
+ if (task.VSTestBlameCrashCollectAlways)
+ {
+ dumpArgs.Add($"CollectAlways={task.VSTestBlameCrashCollectAlways}");
+ }
+
+ if (!string.IsNullOrEmpty(task.VSTestBlameCrashDumpType))
+ {
+ dumpArgs.Add($"DumpType={task.VSTestBlameCrashDumpType}");
+ }
+ }
+
+ if (task.VSTestBlameHang)
+ {
+ dumpArgs.Add("CollectHangDump");
+
+ if (!string.IsNullOrEmpty(task.VSTestBlameHangDumpType))
+ {
+ dumpArgs.Add($"HangDumpType={task.VSTestBlameHangDumpType}");
+ }
+
+ if (!string.IsNullOrEmpty(task.VSTestBlameHangTimeout))
+ {
+ dumpArgs.Add($"TestTimeout={task.VSTestBlameHangTimeout}");
+ }
+ }
+ }
+
+ if (dumpArgs.Any())
+ {
+ builder.AppendSwitchIfNotNull("--Blame:", string.Join(";", dumpArgs));
+ }
+ else
+ {
+ builder.AppendSwitch("--Blame");
+ }
+ }
+
+ if (task.VSTestCollect != null && task.VSTestCollect.Any())
+ {
+ foreach (var arg in task.VSTestCollect)
+ {
+ if (arg.Equals("Code Coverage", 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 && !string.IsNullOrEmpty(task.VSTestTraceDataCollectorDirectoryPath.ItemSpec))
+ {
+ 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.IsNullOrEmpty(task.VSTestArtifactsProcessingMode) && task.VSTestArtifactsProcessingMode.Equals("collect", StringComparison.OrdinalIgnoreCase))
+ {
+ builder.AppendSwitch("--artifactsProcessingMode-collect");
+ }
+
+ if (!string.IsNullOrEmpty(task.VSTestSessionCorrelationId))
+ {
+ builder.AppendSwitchIfNotNull("--testSessionCorrelationId:", task.VSTestSessionCorrelationId);
+ }
+
+ // VSTestCLIRunSettings should be last argument as vstest.console ignore options after "--"(CLIRunSettings option).
+ if (task.VSTestCLIRunSettings != null && task.VSTestCLIRunSettings.Any())
+ {
+ 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 46da877e92..0000000000
--- a/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingApp.cs
+++ /dev/null
@@ -1,64 +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;
-
-#nullable disable
-
-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(string.Format("VSTest: Killing process throws ArgumentException with the following message {0}. It may be that process is not running", ex));
- }
- }
-}
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingTask.cs b/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingTask.cs
new file mode 100644
index 0000000000..1625f04b85
--- /dev/null
+++ b/src/Microsoft.TestPlatform.Build/Tasks/VSTestForwardingTask.cs
@@ -0,0 +1,110 @@
+// 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.Diagnostics;
+using System.Threading;
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.TestPlatform.Build.Trace;
+
+#nullable disable
+
+namespace Microsoft.TestPlatform.Build.Tasks;
+
+public class VSTestForwardingTask : Task, ITestTask
+{
+ private const string ToolExe = "dotnet";
+ private int _activeProcessId;
+
+ 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; }
+
+ public override bool Execute()
+ {
+ var traceEnabledValue = Environment.GetEnvironmentVariable("VSTEST_BUILD_TRACE");
+ Tracing.traceEnabled = !string.IsNullOrEmpty(traceEnabledValue) && traceEnabledValue.Equals("1", StringComparison.OrdinalIgnoreCase);
+
+ var debugEnabled = Environment.GetEnvironmentVariable("VSTEST_BUILD_DEBUG");
+ if (!string.IsNullOrEmpty(debugEnabled) && debugEnabled.Equals("1", StringComparison.Ordinal))
+ {
+ Console.WriteLine("Waiting for debugger attach...");
+
+ var currentProcess = Process.GetCurrentProcess();
+ Console.WriteLine(string.Format("Process Id: {0}, Name: {1}", currentProcess.Id, currentProcess.ProcessName));
+
+ while (!Debugger.IsAttached)
+ {
+ Thread.Sleep(1000);
+ }
+
+ Debugger.Break();
+ }
+
+ // 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 processInfo = new ProcessStartInfo
+ {
+ FileName = ToolExe,
+ Arguments = this.CreateCommandLineArguments(),
+ UseShellExecute = false,
+ };
+
+ if (!string.IsNullOrEmpty(VSTestFramework))
+ {
+ Console.WriteLine(Resources.Resources.TestRunningSummary, TestFileFullPath, VSTestFramework);
+ }
+
+ 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 == 0;
+ }
+
+ public void Cancel()
+ {
+ Tracing.Trace("VSTest: Killing the process...");
+ try
+ {
+ Process.GetProcessById(_activeProcessId).Kill();
+ }
+ catch (ArgumentException ex)
+ {
+ Tracing.Trace(string.Format("VSTest: Killing process throws ArgumentException with the following message {0}. It may be that process is not running", ex));
+ }
+ }
+}
diff --git a/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs b/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
index 6364c8cc31..dcc8ac1435 100644
--- a/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
+++ b/src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
@@ -2,442 +2,100 @@
// 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.Linq;
-using System.Threading;
+using System.IO;
+using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
-using Microsoft.TestPlatform.Build.Trace;
-using Microsoft.TestPlatform.Build.Utils;
#nullable disable
namespace Microsoft.TestPlatform.Build.Tasks;
-public class VSTestTask : Task, ICancelableTask
+public class VSTestTask : ToolTask, ITestTask
{
- // The process which is invoking vstest.console
- private VSTestForwardingApp _vsTestForwardingApp;
-
- private const string VsTestAppName = "vstest.console.dll";
- private const string CodeCovergaeString = "Code Coverage";
-
- public string TestFileFullPath
- {
- get;
- set;
- }
-
- public string VSTestSetting
- {
- get;
- set;
- }
-
- public string[] 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 string VSTestDiag
- {
- get;
- set;
- }
-
- public string[] VSTestCLIRunSettings
- {
- get;
- set;
- }
+ 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 string VSTestConsolePath
- {
- get;
- set;
- }
-
- public string VSTestResultsDirectory
- {
- get;
- set;
- }
-
- public string VSTestVerbosity
- {
- get;
- set;
- }
-
- public string[] VSTestCollect
- {
- get;
- set;
- }
-
- public string VSTestBlame
- {
- get;
- set;
- }
-
- public string VSTestBlameCrash
- {
- get;
- set;
- }
-
- public string VSTestBlameCrashDumpType
- {
- get;
- set;
- }
-
- public string VSTestBlameCrashCollectAlways
- {
- get;
- set;
- }
-
- public string VSTestBlameHang
- {
- get;
- set;
- }
-
- public string VSTestBlameHangDumpType
- {
- get;
- set;
- }
- public string VSTestBlameHangTimeout
- {
- get;
- set;
- }
-
- public string VSTestTraceDataCollectorDirectoryPath
- {
- get;
- set;
- }
-
- public string 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 = !string.IsNullOrEmpty(traceEnabledValue) && traceEnabledValue.Equals("1", StringComparison.OrdinalIgnoreCase);
-
- var debugEnabled = Environment.GetEnvironmentVariable("VSTEST_BUILD_DEBUG");
- if (!string.IsNullOrEmpty(debugEnabled) && debugEnabled.Equals("1", StringComparison.Ordinal))
- {
- Console.WriteLine("Waiting for debugger attach...");
-
- var currentProcess = Process.GetCurrentProcess();
- Console.WriteLine(string.Format("Process Id: {0}, Name: {1}", currentProcess.Id, currentProcess.ProcessName));
-
- while (!Debugger.IsAttached)
- {
- Thread.Sleep(1000);
- }
-
- Debugger.Break();
- }
-
- // 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);
-
- _vsTestForwardingApp = new VSTestForwardingApp(VSTestConsolePath, CreateArgument());
- if (!string.IsNullOrEmpty(VSTestFramework))
- {
- Console.WriteLine(Resources.Resources.TestRunningSummary, TestFileFullPath, VSTestFramework);
+ 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; }
+
+ protected override string ToolName
+ {
+ get
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ return "dotnet.exe";
+ else
+ return "dotnet";
}
-
- return _vsTestForwardingApp.Execute() == 0;
}
- public void Cancel()
+ public VSTestTask()
{
- Tracing.Trace("VSTest: Killing the process...");
- _vsTestForwardingApp.Cancel();
+ LogStandardErrorAsError = true;
+ StandardOutputImportance = "Normal";
}
- internal IEnumerable CreateArgument()
+ protected override string GenerateCommandLineCommands()
{
- var allArgs = AddArgs();
-
- // VSTestCLIRunSettings should be last argument in allArgs as vstest.console ignore options after "--"(CLIRunSettings option).
- AddCliRunSettingsArgs(allArgs);
-
- return allArgs;
+ return this.CreateCommandLineArguments();
}
- private void AddCliRunSettingsArgs(List allArgs)
+ protected override string GenerateFullPathToTool()
{
- if (VSTestCLIRunSettings != null && VSTestCLIRunSettings.Length > 0)
- {
- allArgs.Add("--");
- foreach (var arg in VSTestCLIRunSettings)
- {
- allArgs.Add(ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(arg));
- }
- }
- }
-
- private List AddArgs()
- {
- var isConsoleLoggerSpecifiedByUser = false;
- var isCollectCodeCoverageEnabled = false;
- var isRunSettingsEnabled = false;
- var allArgs = new List();
-
- // TODO log arguments in task
- if (!string.IsNullOrEmpty(VSTestSetting))
- {
- 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 (!string.IsNullOrEmpty(VSTestFramework))
- {
- allArgs.Add("--framework:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestFramework));
- }
-
- // vstest.console only support x86 and x64 for argument platform
- if (!string.IsNullOrEmpty(VSTestPlatform) && !VSTestPlatform.Contains("AnyCPU"))
- {
- allArgs.Add("--platform:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestPlatform));
- }
-
- if (!string.IsNullOrEmpty(VSTestTestCaseFilter))
- {
- 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 (!string.IsNullOrEmpty(VSTestResultsDirectory))
- {
- allArgs.Add("--resultsDirectory:" +
- ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestResultsDirectory));
- }
-
- if (!string.IsNullOrEmpty(VSTestListTests))
+ if (!string.IsNullOrEmpty(ToolPath))
{
- allArgs.Add("--listTests");
+ return Path.Combine(Path.GetDirectoryName(Path.GetFullPath(ToolPath)), ToolExe);
}
- if (!string.IsNullOrEmpty(VSTestDiag))
- {
- allArgs.Add("--Diag:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestDiag));
- }
+ //TODO: https://github.com/dotnet/sdk/issues/20 Need to get the dotnet path from MSBuild?
- if (string.IsNullOrEmpty(TestFileFullPath))
- {
- Log.LogError("Test file path cannot be empty or null.");
- }
- else
+ var dhp = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH");
+ if (!string.IsNullOrEmpty(dhp))
{
- 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 (!string.IsNullOrWhiteSpace(VSTestVerbosity) && !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()))
+ var path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(dhp)), ToolExe);
+ if (File.Exists(path))
{
- vsTestVerbosity = "normal";
+ return path;
}
- else if (quietTestLogging.Contains(VSTestVerbosity.ToLowerInvariant()))
- {
- vsTestVerbosity = "quiet";
- }
-
- allArgs.Add("--logger:Console;Verbosity=" + vsTestVerbosity);
- }
-
- var blameCrash = !string.IsNullOrEmpty(VSTestBlameCrash);
- var blameHang = !string.IsNullOrEmpty(VSTestBlameHang);
- if (!string.IsNullOrEmpty(VSTestBlame) || blameCrash || blameHang)
- {
- var blameArgs = "--Blame";
-
- var dumpArgs = new List();
- if (blameCrash || blameHang)
- {
- if (blameCrash)
- {
- dumpArgs.Add("CollectDump");
- if (!string.IsNullOrEmpty(VSTestBlameCrashCollectAlways))
- {
- dumpArgs.Add($"CollectAlways={VSTestBlameCrashCollectAlways}");
- }
-
- if (!string.IsNullOrEmpty(VSTestBlameCrashDumpType))
- {
- dumpArgs.Add($"DumpType={VSTestBlameCrashDumpType}");
- }
- }
-
- if (blameHang)
- {
- dumpArgs.Add("CollectHangDump");
-
- if (!string.IsNullOrEmpty(VSTestBlameHangDumpType))
- {
- dumpArgs.Add($"HangDumpType={VSTestBlameHangDumpType}");
- }
-
- if (!string.IsNullOrEmpty(VSTestBlameHangTimeout))
- {
- dumpArgs.Add($"TestTimeout={VSTestBlameHangTimeout}");
- }
- }
-
- if (dumpArgs.Any())
- {
- 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(CodeCovergaeString, StringComparison.OrdinalIgnoreCase) ||
- tokens[0].Equals(CodeCovergaeString, 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 (!string.IsNullOrEmpty(VSTestTraceDataCollectorDirectoryPath))
- {
- 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 (!string.IsNullOrWhiteSpace(VSTestNoLogo))
- {
- allArgs.Add("--nologo");
}
- if (!string.IsNullOrEmpty(VSTestArtifactsProcessingMode) && VSTestArtifactsProcessingMode.Equals("collect", StringComparison.OrdinalIgnoreCase))
+ if (File.Exists(ToolExe))
{
- allArgs.Add("--artifactsProcessingMode-collect");
+ return Path.GetFullPath(ToolExe);
}
- if (!string.IsNullOrEmpty(VSTestSessionCorrelationId))
+ var values = Environment.GetEnvironmentVariable("PATH");
+ foreach (var p in values.Split(Path.PathSeparator))
{
- allArgs.Add("--testSessionCorrelationId:" + ArgumentEscaper.HandleEscapeSequenceInArgForProcessStart(VSTestSessionCorrelationId));
+ var fullPath = Path.Combine(p, ToolExe);
+ if (File.Exists(fullPath))
+ return fullPath;
}
- return allArgs;
+ return null;
}
}
diff --git a/test/Microsoft.TestPlatform.Build.UnitTests/ArgumentEscaperTests.cs b/test/Microsoft.TestPlatform.Build.UnitTests/ArgumentEscaperTests.cs
deleted file mode 100644
index 1508f313e6..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 IsSurroundedWithQuotesShouldReturnTrueIfStringIsSurrondedByQuotes()
- {
- string stringSurroundWithQuotes = "\"some string\"";
-
- Assert.IsTrue(ArgumentEscaper.IsSurroundedWithQuotes(stringSurroundWithQuotes));
- }
-
- [TestMethod]
- public void IsSurroundedWithQuotesShouldReturnFalseIfStringIsNotSurrondedByQuotes()
- {
- 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/VsTestTaskTests.cs b/test/Microsoft.TestPlatform.Build.UnitTests/VsTestTaskTests.cs
index b8884568ba..ca4c3074bd 100644
--- a/test/Microsoft.TestPlatform.Build.UnitTests/VsTestTaskTests.cs
+++ b/test/Microsoft.TestPlatform.Build.UnitTests/VsTestTaskTests.cs
@@ -1,25 +1,26 @@
// 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 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 VsTestTaskTests
+public class VSTestTaskTests
{
private readonly VSTestTask _vsTestTask;
- public VsTestTaskTests()
+ public VSTestTaskTests()
{
_vsTestTask = new VSTestTask
{
- TestFileFullPath = @"C:\path\to\test-assembly.dll",
+ BuildEngine = new FakeBuildEngine(),
+ TestFileFullPath = new TaskItem(@"C:\path\to\test-assembly.dll"),
VSTestFramework = ".NETCoreapp,Version2.0"
};
}
@@ -34,22 +35,20 @@ public void CreateArgumentShouldAddOneEntryForCLIRunSettings()
_vsTestTask.VSTestCLIRunSettings[0] = arg1;
_vsTestTask.VSTestCLIRunSettings[1] = arg2;
- var result = _vsTestTask.CreateArgument().ToArray();
-
- Assert.AreEqual(5, result.Length);
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- // First, second and third args would be framework:".NETCoreapp,Version2.0", testfilepath and -- respectively.
- Assert.AreEqual($"\"{arg1}\"", result[3]);
- Assert.AreEqual($"{arg2}", result[4]);
+ StringAssert.Contains(commandline, " -- ");
+ StringAssert.Contains(commandline, $"\"{arg1}\"");
+ StringAssert.Contains(commandline, $"{arg2}");
}
[TestMethod]
- public void CreateArgumentShouldAddCliRunSettingsArgAtEnd()
+ public void CreateArgumentShouldAddCLIRunSettingsArgAtEnd()
{
const string codeCoverageOption = "Code Coverage";
_vsTestTask.VSTestCollect = new string[] { codeCoverageOption };
- _vsTestTask.VSTestBlame = "Blame";
+ _vsTestTask.VSTestBlame = true;
const string arg1 = "RunConfiguration.ResultsDirectory=Path having Space";
const string arg2 = "MSTest.DeploymentEnabled";
@@ -58,24 +57,22 @@ public void CreateArgumentShouldAddCliRunSettingsArgAtEnd()
_vsTestTask.VSTestCLIRunSettings[0] = arg1;
_vsTestTask.VSTestCLIRunSettings[1] = arg2;
- var result = _vsTestTask.CreateArgument().ToArray();
-
- Assert.AreEqual(7, result.Length);
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- // Following are expected --framework:".NETCoreapp,Version2.0", testfilepath, blame, collect:"Code coverage" -- respectively.
- Assert.AreEqual($"\"{arg1}\"", result[5]);
- Assert.AreEqual($"{arg2}", result[6]);
+ StringAssert.Contains(commandline, " -- ");
+ StringAssert.Contains(commandline, $"\"{arg1}\"");
+ StringAssert.Contains(commandline, $"{arg2}");
}
[TestMethod]
public void CreateArgumentShouldPassResultsDirectoryCorrectly()
{
const string resultsDirectoryValue = @"C:\tmp\Results Directory";
- _vsTestTask.VSTestResultsDirectory = resultsDirectoryValue;
+ _vsTestTask.VSTestResultsDirectory = new TaskItem(resultsDirectoryValue);
- var result = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.AreEqual($"--resultsDirectory:\"{resultsDirectoryValue}\"", result[1]);
+ StringAssert.Contains(commandline, $"--resultsDirectory:\"{_vsTestTask.VSTestResultsDirectory.ItemSpec}\"");
}
[TestMethod]
@@ -84,10 +81,10 @@ public void CreateArgumentShouldNotSetConsoleLoggerVerbosityIfConsoleLoggerIsGiv
_vsTestTask.VSTestVerbosity = "diag";
_vsTestTask.VSTestLogger = new string[] { "Console;Verbosity=quiet" };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
+ StringAssert.DoesNotMatch(commandline, new Regex("(--logger:\"Console;Verbosity=normal\")"));
+ StringAssert.Contains(commandline, "--logger:\"Console;Verbosity=quiet\"");
}
[TestMethod]
@@ -95,9 +92,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "n";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -105,9 +102,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "normal";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -115,9 +112,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "d";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -125,9 +122,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "detailed";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -135,9 +132,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "diag";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -145,9 +142,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "diagnostic";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -155,9 +152,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerI
{
_vsTestTask.VSTestVerbosity = "q";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=quiet");
}
[TestMethod]
@@ -165,9 +162,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerI
{
_vsTestTask.VSTestVerbosity = "quiet";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=quiet");
}
[TestMethod]
@@ -175,9 +172,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToMinimalIfConsoleLogge
{
_vsTestTask.VSTestVerbosity = "m";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=minimal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=minimal");
}
[TestMethod]
@@ -185,9 +182,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToMinimalIfConsoleLogge
{
_vsTestTask.VSTestVerbosity = "minimal";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=minimal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=minimal");
}
[TestMethod]
@@ -195,9 +192,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToNormalIfConsoleLogger
{
_vsTestTask.VSTestVerbosity = "Normal";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=normal")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=normal");
}
[TestMethod]
@@ -205,9 +202,9 @@ public void CreateArgumentShouldSetConsoleLoggerVerbosityToQuietIfConsoleLoggerI
{
_vsTestTask.VSTestVerbosity = "Quiet";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:Console;Verbosity=quiet")));
+ StringAssert.Contains(commandline, "--logger:Console;Verbosity=quiet");
}
[TestMethod]
@@ -215,9 +212,9 @@ public void CreateArgumentShouldPreserveWhiteSpaceInLogger()
{
_vsTestTask.VSTestLogger = new string[] { "trx;LogFileName=foo bar.trx" };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:\"trx;LogFileName=foo bar.trx\"")));
+ StringAssert.Contains(commandline, "--logger:\"trx;LogFileName=foo bar.trx\"");
}
[TestMethod]
@@ -228,103 +225,91 @@ public void CreateArgumentShouldAddOneCollectArgumentForEachCollect()
_vsTestTask.VSTestCollect[0] = "name1";
_vsTestTask.VSTestCollect[1] = "name 2";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--collect:name1")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--collect:\"name 2\"")));
+ StringAssert.Contains(commandline, "--collect:name1");
+ StringAssert.Contains(commandline, "--collect:\"name 2\"");
}
[TestMethod]
public void CreateArgumentShouldAddMultipleTestAdapterPaths()
{
- _vsTestTask.VSTestTestAdapterPath = new string[] { "path1", "path2" };
+ _vsTestTask.VSTestTestAdapterPath = new ITaskItem[] { new TaskItem("path1"), new TaskItem("path2") };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--testAdapterPath:path1")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--testAdapterPath:path2")));
+ 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 allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:\"trx;LogFileName=foo bar.trx\"")));
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--logger:console")));
+ 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 = traceDataCollectorDirectoryPath;
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = new TaskItem(traceDataCollectorDirectoryPath);
_vsTestTask.VSTestCollect = new string[] { "code coverage" };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- 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)}]");
+ string expectedArg = $"--testAdapterPath:\"{_vsTestTask.VSTestTraceDataCollectorDirectoryPath.ItemSpec}\"";
+ StringAssert.Contains(commandline, expectedArg);
}
[TestMethod]
public void CreateArgumentShouldNotAddTraceCollectorDirectoryPathAsTestAdapterForNonCodeCoverageCollect()
{
const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedata collector";
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = traceDataCollectorDirectoryPath;
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = new TaskItem(traceDataCollectorDirectoryPath);
_vsTestTask.VSTestCollect = new string[] { "not code coverage" };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- const string notExpectedArg = "--testAdapterPath:\"c:\\path\\to\\tracedata collector\"";
- CollectionAssert.DoesNotContain(allArguments, notExpectedArg, $"Not expected argument: '''{notExpectedArg}''' present in [{string.Join(", ", allArguments)}]");
+ string notExpectedArg = $"--testAdapterPath:\"{this._vsTestTask.VSTestTraceDataCollectorDirectoryPath.ItemSpec}\"";
+ StringAssert.DoesNotMatch(commandline, new Regex(Regex.Escape(notExpectedArg)));
}
[TestMethod]
public void CreateArgumentShouldAddTraceCollectorDirectoryPathAsTestAdapterIfSettingsGiven()
{
const string traceDataCollectorDirectoryPath = @"c:\path\to\tracedatacollector\";
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = traceDataCollectorDirectoryPath;
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = new TaskItem(traceDataCollectorDirectoryPath);
_vsTestTask.VSTestSetting = @"c:\path\to\sample.runsettings";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- const string expectedArg = "--testAdapterPath:c:\\path\\to\\tracedatacollector\\";
- CollectionAssert.Contains(allArguments, expectedArg, $"Expected argument: '''{expectedArg}''' not present in [{string.Join(", ", allArguments)}]");
+ string expectedArg = $"--testAdapterPath:{_vsTestTask.VSTestTraceDataCollectorDirectoryPath.ItemSpec}";
+ StringAssert.Contains(commandline, expectedArg);
}
[TestMethod]
- public void CreateArgumentShouldNotAddTestAdapterPathIfVsTestTraceDataCollectorDirectoryPathIsEmpty()
+ public void CreateArgumentShouldNotAddTestAdapterPathIfVSTestTraceDataCollectorDirectoryPathIsEmpty()
{
- _vsTestTask.VSTestTraceDataCollectorDirectoryPath = string.Empty;
+ _vsTestTask.VSTestTraceDataCollectorDirectoryPath = null;
_vsTestTask.VSTestSetting = @"c:\path\to\sample.runsettings";
_vsTestTask.VSTestCollect = new string[] { "code coverage" };
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNull(Array.Find(allArguments, arg => arg.Contains("--testAdapterPath:")));
+ StringAssert.DoesNotMatch(commandline, new Regex(@"(--testAdapterPath:)"));
}
[TestMethod]
public void CreateArgumentShouldAddNoLogoOptionIfSpecifiedByUser()
{
- _vsTestTask.VSTestNoLogo = "--nologo";
- var allArguments = _vsTestTask.CreateArgument().ToArray();
+ _vsTestTask.VSTestNoLogo = true;
+
+ var commandline = _vsTestTask.CreateCommandLineArguments();
- Assert.IsNotNull(Array.Find(allArguments, arg => arg.Contains("--nologo")));
+ StringAssert.Contains(commandline, "--nologo");
}
}