/// <summary> /// Runs the class cleanup method. /// It returns any error information during the execution of the cleanup method /// </summary> /// <returns> The <see cref="RunCleanupResult"/>. </returns> internal RunCleanupResult RunCleanup() { // No cleanup methods to execute, then return. var assemblyInfoCache = this.typeCache.AssemblyInfoListWithExecutableCleanupMethods; var classInfoCache = this.typeCache.ClassInfoListWithExecutableCleanupMethods; if (!assemblyInfoCache.Any() && !classInfoCache.Any()) { return(null); } var result = new RunCleanupResult { Warnings = new List <string>() }; using (var redirector = new LogMessageListener(MSTestSettings.CurrentSettings.CaptureDebugTraces)) { try { this.RunClassCleanupMethods(classInfoCache, result.Warnings); this.RunAssemblyCleanup(assemblyInfoCache, result.Warnings); } finally { // Replacing the null character with a string.replace should work. // If this does not work for a specific dotnet version a custom function doing the same needs to be put in place. result.StandardOut = redirector.GetAndClearStandardOutput()?.Replace("\0", "\\0"); result.StandardError = redirector.GetAndClearStandardError()?.Replace("\0", "\\0"); result.DebugTrace = redirector.GetAndClearDebugTrace()?.Replace("\0", "\\0"); } } return(result); }
/// <summary> /// Execute test method. Capture failures, handle async and return result. /// </summary> /// <param name="arguments"> /// Arguments to pass to test method. (E.g. For data driven) /// </param> /// <returns>Result of test method invocation.</returns> public virtual TestResult Invoke(object[] arguments) { Stopwatch watch = new Stopwatch(); TestResult result = null; // check if arguments are set for data driven tests if (arguments == null) { arguments = this.Arguments; } using (LogMessageListener listener = new LogMessageListener(this.TestMethodOptions.CaptureDebugTraces)) { watch.Start(); try { if (this.IsTimeoutSet) { result = this.ExecuteInternalWithTimeout(arguments); } else { result = this.ExecuteInternal(arguments); } } finally { // Handle logs & debug traces. watch.Stop(); if (result != null) { result.Duration = watch.Elapsed; result.DebugTrace = listener.GetAndClearDebugTrace(); result.LogOutput = listener.GetAndClearStandardOutput(); result.LogError = listener.GetAndClearStandardError(); result.TestContextMessages = this.TestMethodOptions.TestContext.GetAndClearDiagnosticMessages(); result.ResultFiles = this.TestMethodOptions.TestContext.GetResultFiles(); } } } return(result); }
/// <summary> /// Executes a test /// </summary> /// <returns>The test results.</returns> internal UnitTestResult[] Execute() { string initLogs = string.Empty; string initTrace = string.Empty; string initErrorLogs = string.Empty; string inittestContextMessages = string.Empty; UnitTestResult[] result = null; try { using (LogMessageListener logListener = new LogMessageListener(this.captureDebugTraces)) { try { // Run the assembly and class Initialize methods if required. // Assembly or class initialize can throw exceptions in which case we need to ensure that we fail the test. this.testMethodInfo.Parent.Parent.RunAssemblyInitialize(this.testContext.Context); this.testMethodInfo.Parent.RunClassInitialize(this.testContext.Context); } finally { initLogs = logListener.GetAndClearStandardOutput(); initTrace = logListener.GetAndClearDebugTrace(); initErrorLogs = logListener.GetAndClearStandardError(); inittestContextMessages = this.testContext.GetAndClearDiagnosticMessages(); } } // Listening to log messages when running the test method with its Test Initialize and cleanup later on in the stack. // This allows us to differentiate logging when data driven methods are used. result = this.RunTestMethod(); } catch (TestFailedException ex) { result = new[] { new UnitTestResult(ex) }; } catch (Exception ex) { if (result == null || result.Length == 0) { result = new[] { new UnitTestResult() }; } var newResult = new UnitTestResult(new TestFailedException(UnitTestOutcome.Error, ex.TryGetMessage(), ex.TryGetStackTraceInformation())) { StandardOut = result[result.Length - 1].StandardOut, StandardError = result[result.Length - 1].StandardError, DebugTrace = result[result.Length - 1].DebugTrace, TestContextMessages = result[result.Length - 1].TestContextMessages, Duration = result[result.Length - 1].Duration }; result[result.Length - 1] = newResult; } finally { var firstResult = result[0]; firstResult.StandardOut = initLogs + firstResult.StandardOut; firstResult.StandardError = initErrorLogs + firstResult.StandardError; firstResult.DebugTrace = initTrace + firstResult.DebugTrace; firstResult.TestContextMessages = inittestContextMessages + firstResult.TestContextMessages; } return(result); }