internal static int RunArtifactPostProcessingIfNeeded(string testSessionCorrelationId, ParseResult parseResult, FeatureFlag featureFlag) { if (!featureFlag.IsEnabled(FeatureFlag.ARTIFACTS_POSTPROCESSING)) { return(0); } // VSTest runner will save artifacts inside a temp folder if needed. string expectedArtifactDirectory = Path.Combine(Path.GetTempPath(), testSessionCorrelationId); if (!Directory.Exists(expectedArtifactDirectory)) { VSTestTrace.SafeWriteTrace(() => "No artifact found, post-processing won't run."); return(0); } VSTestTrace.SafeWriteTrace(() => $"Artifacts directory found '{expectedArtifactDirectory}', running post-processing."); var artifactsPostProcessArgs = new List <string> { "--artifactsProcessingMode-postprocess", $"--testSessionCorrelationId:{testSessionCorrelationId}" }; if (parseResult.HasOption(TestCommandParser.DiagOption)) { artifactsPostProcessArgs.Add($"--diag:{parseResult.GetValueForOption(TestCommandParser.DiagOption)}"); } try { return(new VSTestForwardingApp(artifactsPostProcessArgs).Execute()); } finally { if (Directory.Exists(expectedArtifactDirectory)) { VSTestTrace.SafeWriteTrace(() => $"Cleaning artifact directory '{expectedArtifactDirectory}'."); try { Directory.Delete(expectedArtifactDirectory, true); } catch (Exception ex) { VSTestTrace.SafeWriteTrace(() => $"Exception during artifact cleanup: \n{ex}"); } } } }
public static int Run(ParseResult parseResult) { parseResult.HandleDebugSwitch(); FeatureFlag.Default.PrintFlagFeatureState(); // We use also current process id for the correlation id for possible future usage in case we need to know the parent process // from the VSTest side. string testSessionCorrelationId = $"{Environment.ProcessId}_{Guid.NewGuid()}"; string[] args = parseResult.GetArguments(); if (VSTestTrace.TraceEnabled) { string commandLineParameters = ""; if (args?.Length > 0) { commandLineParameters = args.Aggregate((a, b) => $"{a} | {b}"); } VSTestTrace.SafeWriteTrace(() => $"Argument list: '{commandLineParameters}'"); } // settings parameters are after -- (including --), these should not be considered by the parser string[] settings = args.SkipWhile(a => a != "--").ToArray(); // all parameters before -- args = args.TakeWhile(a => a != "--").ToArray(); // Fix for https://github.com/Microsoft/vstest/issues/1453 // Run dll/exe directly using the VSTestForwardingApp if (ContainsBuiltTestSources(args)) { return(ForwardToVSTestConsole(parseResult, args, settings, testSessionCorrelationId)); } return(ForwardToMsbuild(parseResult, settings, testSessionCorrelationId)); }
private static TestCommand FromParseResult(ParseResult result, string[] settings, string testSessionCorrelationId, string msbuildPath = null) { result.ShowHelpOrErrorIfAppropriate(); var msbuildArgs = new List <string>() { "-target:VSTest", "-nodereuse:false", // workaround for https://github.com/Microsoft/vstest/issues/1503 "-nologo" }; msbuildArgs.AddRange(result.OptionValuesToBeForwarded(TestCommandParser.GetCommand())); msbuildArgs.AddRange(result.GetValueForArgument(TestCommandParser.SlnOrProjectArgument) ?? Array.Empty <string>()); if (settings.Any()) { // skip '--' and escape every \ to be \\ and every " to be \" to survive the next hop string[] escaped = settings.Skip(1).Select(s => s.Replace("\\", "\\\\").Replace("\"", "\\\"")).ToArray(); string runSettingsArg = string.Join(";", escaped); msbuildArgs.Add($"-property:VSTestCLIRunSettings=\"{runSettingsArg}\""); } string verbosityArg = result.ForwardedOptionValues <IReadOnlyCollection <string> >(TestCommandParser.GetCommand(), "verbosity")?.SingleOrDefault() ?? null; if (verbosityArg != null) { string[] verbosity = verbosityArg.Split(':', 2); if (verbosity.Length == 2) { msbuildArgs.Add($"-property:VSTestVerbosity={verbosity[1]}"); } } if (FeatureFlag.Default.IsEnabled(FeatureFlag.ARTIFACTS_POSTPROCESSING)) { // Add artifacts processing mode and test session id for the artifact post-processing msbuildArgs.Add("-property:VSTestArtifactsProcessingMode=collect"); msbuildArgs.Add($"-property:VSTestSessionCorrelationId={testSessionCorrelationId}"); } bool noRestore = result.HasOption(TestCommandParser.NoRestoreOption) || result.HasOption(TestCommandParser.NoBuildOption); TestCommand testCommand = new( msbuildArgs, noRestore, msbuildPath); // Apply environment variables provided by the user via --environment (-e) parameter, if present SetEnvironmentVariablesFromParameters(testCommand, result); // Set DOTNET_PATH if it isn't already set in the environment as it is required // by the testhost which uses the apphost feature (Windows only). (bool hasRootVariable, string rootVariableName, string rootValue) = VSTestForwardingApp.GetRootVariable(); if (!hasRootVariable) { testCommand.EnvironmentVariable(rootVariableName, rootValue); VSTestTrace.SafeWriteTrace(() => $"Root variable set {rootVariableName}:{rootValue}"); } VSTestTrace.SafeWriteTrace(() => $"Starting test using MSBuild with arguments '{testCommand.GetArgumentsToMSBuild()}' custom MSBuild path '{msbuildPath}' norestore '{noRestore}'"); return(testCommand); }