diff --git a/TestFx.sln b/TestFx.sln
index 7c9375407c..bb2fbaed5b 100644
--- a/TestFx.sln
+++ b/TestFx.sln
@@ -222,6 +222,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscoverInternalsProject",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlatformServices.Desktop.Legacy", "src\Adapter\PlatformServices.Desktop.Legacy\PlatformServices.Desktop.Legacy.csproj", "{F64A748C-DDBA-4B57-99F4-D9E55684A7A4}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OutputTestProject", "test\E2ETests\TestAssets\OutputTestProject\OutputTestProject.csproj", "{66608D86-416A-49AF-A937-C47F7E4586AE}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Adapter\PlatformServices.Shared\PlatformServices.Shared.projitems*{2177c273-ae07-43b3-b87a-443e47a23c5a}*SharedItemsImports = 13
@@ -1348,6 +1350,30 @@ Global
{F64A748C-DDBA-4B57-99F4-D9E55684A7A4}.Release|x64.Build.0 = Release|Any CPU
{F64A748C-DDBA-4B57-99F4-D9E55684A7A4}.Release|x86.ActiveCfg = Release|Any CPU
{F64A748C-DDBA-4B57-99F4-D9E55684A7A4}.Release|x86.Build.0 = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|ARM.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|ARM.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|x64.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|x64.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|x86.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Code Analysis Debug|x86.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|ARM.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|x64.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Debug|x86.Build.0 = Debug|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|ARM.ActiveCfg = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|ARM.Build.0 = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|x64.ActiveCfg = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|x64.Build.0 = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|x86.ActiveCfg = Release|Any CPU
+ {66608D86-416A-49AF-A937-C47F7E4586AE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1420,6 +1446,7 @@ Global
{6B4DE65C-4162-4C52-836A-8F9FA901814A} = {D53BD452-F69F-4FB3-8B98-386EDA28A4C8}
{44A504D9-A0D6-427D-BFB2-DB144A74F0D5} = {D53BD452-F69F-4FB3-8B98-386EDA28A4C8}
{F64A748C-DDBA-4B57-99F4-D9E55684A7A4} = {24088844-2107-4DB2-8F3F-CBCA94FC4B28}
+ {66608D86-416A-49AF-A937-C47F7E4586AE} = {D53BD452-F69F-4FB3-8B98-386EDA28A4C8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {31E0F4D5-975A-41CC-933E-545B2201FAF9}
diff --git a/src/Adapter/MSTest.CoreAdapter/Execution/LogMessageListener.cs b/src/Adapter/MSTest.CoreAdapter/Execution/LogMessageListener.cs
index f012d8c802..88af97962d 100644
--- a/src/Adapter/MSTest.CoreAdapter/Execution/LogMessageListener.cs
+++ b/src/Adapter/MSTest.CoreAdapter/Execution/LogMessageListener.cs
@@ -6,6 +6,7 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution
using System;
using System.Globalization;
using System.IO;
+ using System.Threading;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface;
using Microsoft.VisualStudio.TestTools.UnitTesting.Logging;
@@ -16,21 +17,23 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution
///
public class LogMessageListener : IDisposable
{
- private static LogMessageListener activeRedirector;
- private readonly LogMessageListener previousRedirector;
- private readonly ThreadSafeStringWriter redirectLoggerOut;
- private readonly ThreadSafeStringWriter redirectStdErr;
- private readonly bool captureDebugTraces;
+ private static object traceLock = new object();
+ private static int listenerCount;
+ private static ThreadSafeStringWriter redirectedDebugTrace;
///
/// Trace listener to capture Trace.WriteLines in the test cases
///
- private ITraceListener traceListener;
+ private static ITraceListener traceListener;
+ private readonly ThreadSafeStringWriter redirectedStandardOutput;
+ private readonly ThreadSafeStringWriter redirectedStandardError;
+ private readonly bool captureDebugTraces;
///
/// Trace listener Manager to perform operation on tracelistener objects.
///
private ITraceListenerManager traceListenerManager;
+ private bool isDisposed;
///
/// Initializes a new instance of the class.
@@ -41,30 +44,43 @@ public LogMessageListener(bool captureDebugTraces)
this.captureDebugTraces = captureDebugTraces;
// Cache the original output/error streams and replace it with the own stream.
- this.redirectLoggerOut = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "out");
- this.redirectStdErr = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "err");
-
- Logger.OnLogMessage += this.redirectLoggerOut.WriteLine;
+ this.redirectedStandardOutput = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "out");
+ this.redirectedStandardError = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "err");
- // Cache the previous redirector if any and replace the trace listener.
- this.previousRedirector = activeRedirector;
+ Logger.OnLogMessage += this.redirectedStandardOutput.WriteLine;
if (this.captureDebugTraces)
{
- this.traceListener = PlatformServiceProvider.Instance.GetTraceListener(new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "trace"));
- this.traceListenerManager = PlatformServiceProvider.Instance.GetTraceListenerManager(this.redirectLoggerOut, this.redirectStdErr);
-
- // If there was a previous LogMessageListener active, remove its
- // TraceListener (it will be restored when this one is disposed).
- if (this.previousRedirector != null && this.previousRedirector.traceListener != null)
+ // This is awkward, it has a side-effect of setting up Console output redirection, but the naming is suggesting that we are
+ // just getting TraceListener manager.
+ this.traceListenerManager = PlatformServiceProvider.Instance.GetTraceListenerManager(this.redirectedStandardOutput, this.redirectedStandardError);
+
+ // The Debug listener uses Debug.WriteLine and Debug.Write to write the messages, which end up written into Trace.Listeners.
+ // These listeners are static and hence shared across the whole process. We need to capture Debug output only for the current
+ // test, which was historically done by registering a listener in constructor of this class, and by removing the listener on Dispose.
+ // The newly created listener replaced previously registered listener, which was remembered, and put back on dispose.
+ //
+ // This works well as long as there are no tests running in parallel. But as soon as there are tests running in parallel. Then all the
+ // debug output of all tests will be output into the test that was most recently created (because it registered the listener most recently).
+ //
+ // To prevent mixing of outputs, the ThreadSafeStringWriter was re-implemented for net46 and newer to leverage AsyncLocal, which allows the writer to
+ // write only to the output of the current test. This leaves the LogMessageListener with only one task. Make sure that a trace listener is registered
+ // as long as there is any active test. This is still done by constructor and Dispose, but instead of replacing the listener every time, we use listenerCount
+ // to only add the listerner when there is none, and remove it when we are the last one to dispose.
+ //
+ // This would break the behavior for net451, but that functionality was moved further into ThreadSafeStringWriter.
+ lock (traceLock)
{
- this.traceListenerManager.Remove(this.previousRedirector.traceListener);
- }
+ if (listenerCount == 0)
+ {
+ redirectedDebugTrace = new ThreadSafeStringWriter(CultureInfo.InvariantCulture, "trace");
+ traceListener = PlatformServiceProvider.Instance.GetTraceListener(redirectedDebugTrace);
+ this.traceListenerManager.Add(traceListener);
+ }
- this.traceListenerManager.Add(this.traceListener);
+ listenerCount++;
+ }
}
-
- activeRedirector = this;
}
~LogMessageListener()
@@ -75,12 +91,12 @@ public LogMessageListener(bool captureDebugTraces)
///
/// Gets logger output
///
- public string StandardOutput => this.redirectLoggerOut.ToString();
+ public string StandardOutput => this.redirectedStandardOutput.ToString();
///
/// Gets 'Error' Output from the redirected stream
///
- public string StandardError => this.redirectStdErr.ToString();
+ public string StandardError => this.redirectedStandardError.ToString();
///
/// Gets 'Trace' Output from the redirected stream
@@ -89,43 +105,31 @@ public string DebugTrace
{
get
{
- return (this.traceListener == null || this.traceListener.GetWriter() == null) ?
- string.Empty : this.traceListener.GetWriter().ToString();
+ return redirectedDebugTrace?.ToString();
}
}
public string GetAndClearStandardOutput()
{
- var output = this.redirectLoggerOut.ToString();
- this.redirectLoggerOut.Clear();
+ var output = this.redirectedStandardOutput.ToStringAndClear();
return output;
}
public string GetAndClearStandardError()
{
- var output = this.redirectStdErr.ToString();
- this.redirectStdErr.Clear();
+ var output = this.redirectedStandardError.ToStringAndClear();
return output;
}
public string GetAndClearDebugTrace()
{
- var writer = this.traceListener?.GetWriter();
- if (writer == null)
+ if (redirectedDebugTrace == null)
{
return null;
}
- if (writer is StringWriter sw)
- {
- var sb = sw.GetStringBuilder();
- var output = sb?.ToString();
- sb?.Clear();
- return output;
- }
-
- // we cannot clear it because it is just a text writer
- return writer.ToString();
+ var output = redirectedDebugTrace.ToStringAndClear();
+ return output;
}
public void Dispose()
@@ -136,47 +140,46 @@ public void Dispose()
private void Dispose(bool disposing)
{
- if (disposing)
+ if (disposing && !this.isDisposed)
{
- Logger.OnLogMessage -= this.redirectLoggerOut.WriteLine;
- Logger.OnLogMessage -= this.redirectStdErr.WriteLine;
+ this.isDisposed = true;
+ Logger.OnLogMessage -= this.redirectedStandardOutput.WriteLine;
+ Logger.OnLogMessage -= this.redirectedStandardError.WriteLine;
- this.redirectLoggerOut.Dispose();
- this.redirectStdErr.Dispose();
+ this.redirectedStandardOutput.Dispose();
+ this.redirectedStandardError.Dispose();
if (this.captureDebugTraces)
{
- try
+ lock (traceLock)
{
- if (this.traceListener != null)
- {
- this.traceListenerManager.Remove(this.traceListener);
- }
-
- // Restore the previous LogMessageListener's TraceListener (if there was one)
- if (this.previousRedirector != null && this.previousRedirector.traceListener != null)
+ if (listenerCount == 1)
{
- this.traceListenerManager.Add(this.previousRedirector.traceListener);
+ try
+ {
+ if (traceListener != null)
+ {
+ this.traceListenerManager.Remove(traceListener);
+ }
+ }
+ catch (Exception e)
+ {
+ // Catch all exceptions since Dispose should not throw.
+ PlatformServiceProvider.Instance.AdapterTraceLogger.LogError("ConsoleOutputRedirector.Dispose threw exception: {0}", e);
+ }
+
+ if (traceListener != null)
+ {
+ // Dispose trace manager and listeners
+ this.traceListenerManager.Dispose(traceListener);
+ this.traceListenerManager = null;
+ traceListener = null;
+ }
}
- }
- catch (Exception e)
- {
- // Catch all exceptions since Dispose should not throw.
- PlatformServiceProvider.Instance.AdapterTraceLogger.LogError(
- "ConsoleOutputRedirector.Dispose threw exception: {0}",
- e);
- }
- if (this.traceListener != null)
- {
- // Dispose trace manager and listeners
- this.traceListenerManager.Dispose(this.traceListener);
- this.traceListenerManager = null;
- this.traceListener = null;
+ listenerCount--;
}
}
-
- activeRedirector = this.previousRedirector;
}
}
}
diff --git a/src/Adapter/PlatformServices.Desktop/Services/DesktopTestContextImplementation.cs b/src/Adapter/PlatformServices.Desktop/Services/DesktopTestContextImplementation.cs
index 8a9481968f..a9527fd188 100644
--- a/src/Adapter/PlatformServices.Desktop/Services/DesktopTestContextImplementation.cs
+++ b/src/Adapter/PlatformServices.Desktop/Services/DesktopTestContextImplementation.cs
@@ -45,7 +45,7 @@ public class TestContextImplementation : UTF.TestContext, ITestContext
///
/// Writer on which the messages given by the user should be written
///
- private StringWriter stringWriter;
+ private ThreadSafeStringWriter threadSafeStringWriter;
///
/// Specifies whether the writer is disposed or not
@@ -80,7 +80,9 @@ public TestContextImplementation(ITestMethod testMethod, StringWriter stringWrit
Debug.Assert(properties != null, "properties is not null");
this.testMethod = testMethod;
- this.stringWriter = stringWriter;
+
+ // Cannot get this type in constructor directly, because all sigantures for all platforms need to be the same.
+ this.threadSafeStringWriter = (ThreadSafeStringWriter)stringWriter;
this.properties = new Dictionary(properties);
this.CancellationTokenSource = new CancellationTokenSource();
this.InitializeProperties();
@@ -283,7 +285,7 @@ public override void Write(string message)
try
{
var msg = message?.Replace("\0", "\\0");
- this.stringWriter.Write(msg);
+ this.threadSafeStringWriter.Write(msg);
}
catch (ObjectDisposedException)
{
@@ -307,7 +309,7 @@ public override void Write(string format, params object[] args)
try
{
string message = string.Format(CultureInfo.CurrentCulture, format?.Replace("\0", "\\0"), args);
- this.stringWriter.Write(message);
+ this.threadSafeStringWriter.Write(message);
}
catch (ObjectDisposedException)
{
@@ -330,7 +332,7 @@ public override void WriteLine(string message)
try
{
var msg = message?.Replace("\0", "\\0");
- this.stringWriter.WriteLine(msg);
+ this.threadSafeStringWriter.WriteLine(msg);
}
catch (ObjectDisposedException)
{
@@ -354,7 +356,7 @@ public override void WriteLine(string format, params object[] args)
try
{
string message = string.Format(CultureInfo.CurrentCulture, format?.Replace("\0", "\\0"), args);
- this.stringWriter.WriteLine(message);
+ this.threadSafeStringWriter.WriteLine(message);
}
catch (ObjectDisposedException)
{
@@ -446,7 +448,7 @@ public IList GetResultFiles()
/// The test context messages added so far.
public string GetDiagnosticMessages()
{
- return this.stringWriter.ToString();
+ return this.threadSafeStringWriter.ToString();
}
///
@@ -454,8 +456,7 @@ public string GetDiagnosticMessages()
///
public void ClearDiagnosticMessages()
{
- var sb = this.stringWriter.GetStringBuilder();
- sb?.Remove(0, sb.Length);
+ this.threadSafeStringWriter.ToStringAndClear();
}
#endregion
diff --git a/src/Adapter/PlatformServices.NetCore/Services/NetCoreTestContextImplementation.cs b/src/Adapter/PlatformServices.NetCore/Services/NetCoreTestContextImplementation.cs
index bcf6eca384..851fd6cd37 100644
--- a/src/Adapter/PlatformServices.NetCore/Services/NetCoreTestContextImplementation.cs
+++ b/src/Adapter/PlatformServices.NetCore/Services/NetCoreTestContextImplementation.cs
@@ -11,6 +11,7 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices
using System.Globalization;
using System.IO;
using System.Linq;
+ using System.Net.Sockets;
using System.Threading;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.ObjectModel;
@@ -51,7 +52,7 @@ public class TestContextImplementation : UTF.TestContext, ITestContext
///
private ITestMethod testMethod;
- private StringWriter stringWriter;
+ private ThreadSafeStringWriter threadSafeStringWriter;
private bool stringWriterDisposed;
///
@@ -67,7 +68,9 @@ public TestContextImplementation(ITestMethod testMethod, StringWriter writer, ID
this.testMethod = testMethod;
this.properties = new Dictionary(properties);
- this.stringWriter = writer;
+
+ // Cannot get this type in constructor directly, because all sigantures for all platforms need to be the same.
+ this.threadSafeStringWriter = (ThreadSafeStringWriter)writer;
this.InitializeProperties();
this.testResultFiles = new List();
this.CancellationTokenSource = new CancellationTokenSource();
@@ -306,7 +309,7 @@ public override void Write(string message)
try
{
var msg = message?.Replace("\0", "\\0");
- this.stringWriter.Write(msg);
+ this.threadSafeStringWriter.Write(msg);
}
catch (ObjectDisposedException)
{
@@ -330,7 +333,7 @@ public override void Write(string format, params object[] args)
try
{
string message = string.Format(CultureInfo.CurrentCulture, format?.Replace("\0", "\\0"), args);
- this.stringWriter.Write(message);
+ this.threadSafeStringWriter.Write(message);
}
catch (ObjectDisposedException)
{
@@ -353,7 +356,7 @@ public override void WriteLine(string message)
try
{
var msg = message?.Replace("\0", "\\0");
- this.stringWriter.WriteLine(msg);
+ this.threadSafeStringWriter.WriteLine(msg);
}
catch (ObjectDisposedException)
{
@@ -377,7 +380,7 @@ public override void WriteLine(string format, params object[] args)
try
{
string message = string.Format(CultureInfo.CurrentCulture, format?.Replace("\0", "\\0"), args);
- this.stringWriter.WriteLine(message);
+ this.threadSafeStringWriter.WriteLine(message);
}
catch (ObjectDisposedException)
{
@@ -391,7 +394,7 @@ public override void WriteLine(string format, params object[] args)
/// The test context messages added so far.
public string GetDiagnosticMessages()
{
- return this.stringWriter.ToString();
+ return this.threadSafeStringWriter.ToString();
}
///
@@ -399,8 +402,7 @@ public string GetDiagnosticMessages()
///
public void ClearDiagnosticMessages()
{
- var sb = this.stringWriter.GetStringBuilder();
- sb?.Remove(0, sb.Length);
+ this.threadSafeStringWriter.ToStringAndClear();
}
public void SetDataRow(object dataRow)
diff --git a/src/Adapter/PlatformServices.Shared/netstandard1.0/Services/ns10ThreadSafeStringWriter.cs b/src/Adapter/PlatformServices.Shared/netstandard1.0/Services/ns10ThreadSafeStringWriter.cs
index 8c8576a94d..4315896ec6 100644
--- a/src/Adapter/PlatformServices.Shared/netstandard1.0/Services/ns10ThreadSafeStringWriter.cs
+++ b/src/Adapter/PlatformServices.Shared/netstandard1.0/Services/ns10ThreadSafeStringWriter.cs
@@ -43,11 +43,21 @@ public override string ToString()
}
}
- public void Clear()
+ public string ToStringAndClear()
{
lock (this.lockObject)
{
- InvokeBaseClass(() => this.GetStringBuilder().Clear());
+ try
+ {
+ var sb = this.GetStringBuilder();
+ var output = sb.ToString();
+ sb.Clear();
+ return output;
+ }
+ catch (ObjectDisposedException)
+ {
+ return default(string);
+ }
}
}
diff --git a/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13ThreadSafeStringWriter.cs b/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13ThreadSafeStringWriter.cs
index cc0e17354d..a9ec8daf90 100644
--- a/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13ThreadSafeStringWriter.cs
+++ b/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13ThreadSafeStringWriter.cs
@@ -48,6 +48,11 @@ public ThreadSafeStringWriter(IFormatProvider formatProvider, string outputType)
}
}
+ public override StringBuilder GetStringBuilder()
+ {
+ throw new NotSupportedException("GetStringBuilder is not supported, because it does not allow us to clean the string builder in thread safe way.");
+ }
+
///
public override string ToString()
{
@@ -64,11 +69,27 @@ public override string ToString()
}
}
- public void Clear()
+ public string ToStringAndClear()
{
lock (this.lockObject)
{
- this.GetStringBuilderOrNull()?.Clear();
+ try
+ {
+ var sb = this.GetStringBuilderOrNull();
+
+ if (sb == null)
+ {
+ return default(string);
+ }
+
+ var output = sb.ToString();
+ sb.Clear();
+ return output;
+ }
+ catch (ObjectDisposedException)
+ {
+ return default(string);
+ }
}
}
@@ -119,12 +140,6 @@ public override void Write(char[] buffer, int index, int count)
}
}
- //
- public override StringBuilder GetStringBuilder()
- {
- return this.GetStringBuilderOrNull();
- }
-
///
protected override void Dispose(bool disposing)
{
diff --git a/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13TraceListenerManager.cs b/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13TraceListenerManager.cs
index eeecb8d7b3..d167be9a85 100644
--- a/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13TraceListenerManager.cs
+++ b/src/Adapter/PlatformServices.Shared/netstandard1.3/Services/ns13TraceListenerManager.cs
@@ -4,6 +4,7 @@
namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices
{
using System;
+ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface;
diff --git a/test/E2ETests/DiscoveryAndExecutionTests/OutputTests.cs b/test/E2ETests/DiscoveryAndExecutionTests/OutputTests.cs
new file mode 100644
index 0000000000..ee182938f1
--- /dev/null
+++ b/test/E2ETests/DiscoveryAndExecutionTests/OutputTests.cs
@@ -0,0 +1,101 @@
+// 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.Linq;
+
+namespace Microsoft.MSTestV2.Smoke.DiscoveryAndExecutionTests
+{
+ using System;
+ using System.Collections.ObjectModel;
+ using System.IO;
+ using System.Text.RegularExpressions;
+ using Microsoft.MSTestV2.CLIAutomation;
+ using Microsoft.VisualStudio.TestPlatform.ObjectModel;
+ using OM = Microsoft.VisualStudio.TestPlatform.ObjectModel;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class OutputTests : CLITestBase
+ {
+ private const string TestAssembly = "OutputTestProject.dll";
+
+ [TestMethod]
+ public void OutputIsNotMixedWhenTestsRunInParallel()
+ {
+ ValidateOutputForClass(TestAssembly, "UnitTest1");
+ }
+
+ [TestMethod]
+ public void OutputIsNotMixedWhenAsyncTestsRunInParallel()
+ {
+ ValidateOutputForClass(TestAssembly, "UnitTest2");
+ }
+
+ private void ValidateOutputForClass(string testAssembly, string className)
+ {
+ // LogMessageListener uses an implementation of a string writer that captures output per async context.
+ // This allows us to capture output from tasks even when they are running in parallel.
+
+ // Arrange
+ var assemblyPath = Path.IsPathRooted(testAssembly) ? testAssembly : this.GetAssetFullPath(testAssembly);
+
+ // Act
+ var testCases = DiscoverTests(assemblyPath).Where(tc => tc.FullyQualifiedName.Contains(className)).ToList();
+ var testResults = RunTests(assemblyPath, testCases);
+
+ // Assert
+ Assert.AreEqual(3, testResults.Count);
+
+ // Ensure that some tests are running in parallel, because otherwise the output just works correctly.
+ var firstEnd = testResults.Min(t => t.EndTime);
+ var someStartedBeforeFirstEnded = testResults.Where(t => t.EndTime != firstEnd).Any(t => firstEnd > t.StartTime);
+ Assert.IsTrue(someStartedBeforeFirstEnded, "Tests must run in parallel, but there were no other tests that started, before the first one ended.");
+
+ ValidateOutputsAreNotMixed(testResults, "TestMethod1", new[] { "TestMethod2", "TestMethod3" });
+ ValidateOutputsAreNotMixed(testResults, "TestMethod2", new[] { "TestMethod1", "TestMethod3" });
+ ValidateOutputsAreNotMixed(testResults, "TestMethod3", new[] { "TestMethod1", "TestMethod2" });
+
+ ValidateInitializationsAndCleanups(testResults);
+ }
+
+ private static Func IsDebugMessage = m => m.Category == "StdOutMsgs" && m.Text.StartsWith("\n\nDebug Trace:\n");
+ private static Func IsStandardOutputMessage = m => m.Category == "StdOutMsgs" && !m.Text.StartsWith("\n\nDebug Trace:\n");
+ private static Func IsStandardErrorMessage = m => m.Category == "StdErrMsgs";
+
+ private static void ValidateOutputsAreNotMixed(ReadOnlyCollection testResults, string methodName, string[] shouldNotContain)
+ {
+ ValidateOutputIsNotMixed(testResults, methodName, shouldNotContain, IsStandardOutputMessage);
+ ValidateOutputIsNotMixed(testResults, methodName, shouldNotContain, IsStandardErrorMessage);
+ ValidateOutputIsNotMixed(testResults, methodName, shouldNotContain, IsDebugMessage);
+ }
+
+ private static void ValidateInitializationsAndCleanups(ReadOnlyCollection testResults)
+ {
+ ValidateInitializeAndCleanup(testResults, IsStandardOutputMessage);
+ ValidateInitializeAndCleanup(testResults, IsStandardErrorMessage);
+ ValidateInitializeAndCleanup(testResults, IsDebugMessage);
+ }
+
+ private static void ValidateOutputIsNotMixed(ReadOnlyCollection testResults, string methodName, string[] shouldNotContain, Func messageFilter)
+ {
+ // Make sure that the output between methods is not mixed. And that every method has test initialize and cleanup.
+ var testMethod = testResults.Single(t => t.DisplayName == methodName);
+ Assert.IsNotNull(testMethod, $"Test method {methodName} was not found.");
+ var message = testMethod.Messages.SingleOrDefault(messageFilter);
+ Assert.IsNotNull(message, $"Message for {testMethod.DisplayName} was not found. All messages: { string.Join(Environment.NewLine, testMethod.Messages.Select(m=> $"{m.Category} - {m.Text}")) }");
+ StringAssert.Matches(message.Text, new Regex(methodName), testMethod.DisplayName);
+ StringAssert.Matches(message.Text, new Regex("TestInitialize"), testMethod.DisplayName);
+ StringAssert.Matches(message.Text, new Regex("TestCleanup"), testMethod.DisplayName);
+ StringAssert.DoesNotMatch(message.Text, new Regex(string.Join("|", shouldNotContain)), testMethod.DisplayName);
+ }
+
+ private static void ValidateInitializeAndCleanup(ReadOnlyCollection testResults, Func messageFilter)
+ {
+ // It is not deterministic where the class initialize and class cleanup will run, so we look at all tests, to make sure it is includes somewhere.
+ var output = string.Join(Environment.NewLine, testResults.SelectMany(r=>r.Messages).Where(messageFilter).Select(m=>m.Text));
+ Assert.IsNotNull(output);
+ StringAssert.Matches(output, new Regex("ClassInitialize"));
+ StringAssert.Matches(output, new Regex("ClassCleanup"));
+ }
+ }
+}
diff --git a/test/E2ETests/DiscoveryAndExecutionTests/Utilities/CLITestBase.discovery.cs b/test/E2ETests/DiscoveryAndExecutionTests/Utilities/CLITestBase.discovery.cs
index b14d2ca58d..54ed935153 100644
Binary files a/test/E2ETests/DiscoveryAndExecutionTests/Utilities/CLITestBase.discovery.cs and b/test/E2ETests/DiscoveryAndExecutionTests/Utilities/CLITestBase.discovery.cs differ
diff --git a/test/E2ETests/TestAssets/OutputTestProject/Assembly.cs b/test/E2ETests/TestAssets/OutputTestProject/Assembly.cs
new file mode 100644
index 0000000000..8578dee8d4
--- /dev/null
+++ b/test/E2ETests/TestAssets/OutputTestProject/Assembly.cs
@@ -0,0 +1,4 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+[assembly: Parallelize(Scope = ExecutionScope.MethodLevel, Workers = 0)]
+[assembly: ClassCleanupExecution(ClassCleanupBehavior.EndOfClass)]
\ No newline at end of file
diff --git a/test/E2ETests/TestAssets/OutputTestProject/OutputTestProject.csproj b/test/E2ETests/TestAssets/OutputTestProject/OutputTestProject.csproj
new file mode 100644
index 0000000000..bef06d3947
--- /dev/null
+++ b/test/E2ETests/TestAssets/OutputTestProject/OutputTestProject.csproj
@@ -0,0 +1,13 @@
+
+
+ net452
+ false
+ false
+ $(RepoRoot)artifacts\TestAssets\
+
+
+
+
+
+
+
diff --git a/test/E2ETests/TestAssets/OutputTestProject/UnitTest1.cs b/test/E2ETests/TestAssets/OutputTestProject/UnitTest1.cs
new file mode 100644
index 0000000000..eb2690117c
--- /dev/null
+++ b/test/E2ETests/TestAssets/OutputTestProject/UnitTest1.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Threading;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace OutputTestProject
+{
+
+ [TestClass]
+ public class UnitTest1
+ {
+ private static readonly Random rng = new Random();
+
+ public TestContext TestContext { get; set; }
+
+ [ClassInitialize()]
+ public static void ClassInitialize(TestContext _)
+ {
+ WriteLines("UnitTest1 - ClassInitialize");
+ }
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ WriteLines("UnitTest1 - TestInitialize");
+ }
+
+ [TestCleanup]
+ public void TestCleanup()
+ {
+ WriteLines("UnitTest1 - TestCleanup");
+ }
+
+
+ [ClassCleanup()]
+ public static void ClassCleanup()
+ {
+ WriteLines($"UnitTest1 - ClassCleanup");
+ }
+
+ [TestMethod]
+ public void TestMethod1()
+ {
+ WriteLines("UnitTest1 - TestMethod1");
+ // This makes the outputs more likely to run into each other
+ // when running in parallel.
+ // It also makes the test longer, because we check in the test
+ // that all tests started before any test finished (to make sure
+ // they actually run in parallel), and this gives us more leeway
+ // on slower machines.
+ Thread.Sleep(rng.Next(20, 50));
+ WriteLines("UnitTest1 - TestMethod1");
+ Thread.Sleep(rng.Next(20, 50));
+ WriteLines("UnitTest1 - TestMethod1");
+ }
+
+ [TestMethod]
+ public void TestMethod2()
+ {
+ WriteLines("UnitTest1 - TestMethod2");
+ Thread.Sleep(rng.Next(20, 50));
+ WriteLines("UnitTest1 - TestMethod2");
+ Thread.Sleep(rng.Next(20, 50));
+ WriteLines("UnitTest1 - TestMethod2");
+ }
+
+ [TestMethod]
+ public void TestMethod3()
+ {
+ WriteLines("UnitTest1 - TestMethod3");
+ Thread.Sleep(rng.Next(20, 50));
+ WriteLines("UnitTest1 - TestMethod3");
+ Thread.Sleep(rng.Next(20, 50));
+ WriteLines("UnitTest1 - TestMethod3");
+ }
+
+ private static void WriteLines(string message)
+ {
+ Trace.WriteLine(message);
+ Console.WriteLine(message);
+ Console.Error.WriteLine(message);
+ }
+ }
+}
diff --git a/test/E2ETests/TestAssets/OutputTestProject/UnitTest2.cs b/test/E2ETests/TestAssets/OutputTestProject/UnitTest2.cs
new file mode 100644
index 0000000000..d830c7abec
--- /dev/null
+++ b/test/E2ETests/TestAssets/OutputTestProject/UnitTest2.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace OutputTestProject
+{
+
+ [TestClass]
+ public class UnitTest2
+ {
+ private static readonly Random rng = new Random();
+
+ public TestContext TestContext { get; set; }
+
+ [ClassInitialize()]
+ public static void ClassInitialize(TestContext _)
+ {
+ WriteLines("UnitTest2 - ClassInitialize");
+ }
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ WriteLines("UnitTest2 - TestInitialize");
+ }
+
+ [TestCleanup]
+ public void TestCleanup()
+ {
+ WriteLines("UnitTest2 - TestCleanup");
+ }
+
+
+ [ClassCleanup()]
+ public static void ClassCleanup()
+ {
+ WriteLines($"UnitTest2 - ClassCleanup");
+ }
+
+ [TestMethod]
+ public async Task TestMethod1()
+ {
+ WriteLines("UnitTest2 - TestMethod1");
+ // This makes the outputs more likely to run into each other
+ // when running in parallel.
+ // It also makes the test longer, because we check in the test
+ // that all tests started before any test finished (to make sure
+ // they actually run in parallel), and this gives us more leeway
+ // on slower machines.
+ await Task.Delay(rng.Next(20, 50));
+ WriteLines("UnitTest2 - TestMethod1");
+ await Task.Delay(rng.Next(20, 50));
+ WriteLines("UnitTest2 - TestMethod1");
+ }
+
+ [TestMethod]
+ public async Task TestMethod2()
+ {
+ WriteLines("UnitTest2 - TestMethod2");
+ await Task.Delay(rng.Next(20, 50));
+ WriteLines("UnitTest2 - TestMethod2");
+ await Task.Delay(rng.Next(20, 50));
+ WriteLines("UnitTest2 - TestMethod2");
+ }
+
+ [TestMethod]
+ public async Task TestMethod3()
+ {
+ WriteLines("UnitTest2 - TestMethod3");
+ await Task.Delay(rng.Next(20, 50));
+ WriteLines("UnitTest2 - TestMethod3");
+ await Task.Delay(rng.Next(20, 50));
+ WriteLines("UnitTest2 - TestMethod3");
+ }
+
+ private static void WriteLines(string message)
+ {
+ Trace.WriteLine(message);
+ Console.WriteLine(message);
+ Console.Error.WriteLine(message);
+ }
+ }
+}
diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/LogMessageListenerTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/LogMessageListenerTests.cs
index e5130db64c..929811a608 100644
--- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/LogMessageListenerTests.cs
+++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/LogMessageListenerTests.cs
@@ -53,33 +53,30 @@ public void LogMessageListenerShouldCaptureTestFrameworkLogMessages()
[TestMethod]
public void NoTraceListenerOperationShouldBePerformedIfDebugTraceIsNotEnabled()
{
- var logMessageListener = new LogMessageListener(false);
- this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Add(It.IsAny()), Times.Never);
+ using (var logMessageListener = new LogMessageListener(false))
+ {
+ this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Add(It.IsAny()), Times.Never);
+ }
}
[TestMethod]
public void AddTraceListenerOperationShouldBePerformedIfDebugTraceIsEnabled()
{
- var logMessageListener = new LogMessageListener(true);
- this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Add(this.testablePlatformServiceProvider.MockTraceListener.Object), Times.Once);
- }
-
- [TestMethod]
- public void DebugTraceShouldReturnTraceOutput()
- {
- var logMessageListener = new LogMessageListener(true);
- StringWriter writer = new StringWriter(new StringBuilder("DummyTrace"));
- this.testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
- Assert.AreEqual("DummyTrace", logMessageListener.DebugTrace);
+ using (var logMessageListener = new LogMessageListener(true))
+ {
+ this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Add(this.testablePlatformServiceProvider.MockTraceListener.Object), Times.Once);
+ }
}
#region Dispose Tests
[TestMethod]
public void DisposeShouldNotRemoveTraceListenerIfDebugTracesIsNotEnabled()
{
- var logMessageListener = new LogMessageListener(false);
- logMessageListener.Dispose();
- this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Remove(It.IsAny()), Times.Never);
+ using (var logMessageListener = new LogMessageListener(false))
+ {
+ logMessageListener.Dispose();
+ this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Remove(It.IsAny()), Times.Never);
+ }
}
[TestMethod]
@@ -91,15 +88,17 @@ public void DisposeShouldRemoveTraceListenerIfDebugTracesIsEnabled()
}
// Once when Dispose() is called and second time when destructor is called
- this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Remove(It.IsAny()), Times.Exactly(2));
+ this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Remove(It.IsAny()), Times.Exactly(1));
}
[TestMethod]
public void DisposeShouldDisposeTraceListener()
{
- var logMessageListener = new LogMessageListener(true);
- logMessageListener.Dispose();
- this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Dispose(this.testablePlatformServiceProvider.MockTraceListener.Object), Times.Once);
+ using (var logMessageListener = new LogMessageListener(true))
+ {
+ logMessageListener.Dispose();
+ this.testablePlatformServiceProvider.MockTraceListenerManager.Verify(mtlm => mtlm.Dispose(this.testablePlatformServiceProvider.MockTraceListener.Object), Times.Once);
+ }
}
#endregion
diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodInfoTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodInfoTests.cs
index 25fa22dc53..688f5bd81d 100644
--- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodInfoTests.cs
+++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodInfoTests.cs
@@ -197,56 +197,6 @@ public void TestMethodInfoInvokeShouldHandleAssertInconclusive()
Assert.AreEqual(UTF.UnitTestOutcome.Inconclusive, result.Outcome);
}
- [TestMethodV1]
- public void TestMethodInfoInvokeShouldListenForDebugAndTraceLogsWhenEnabled()
- {
- this.testMethodOptions.CaptureDebugTraces = true;
-
- StringWriter writer = new StringWriter(new StringBuilder());
- DummyTestClass.TestMethodBody = o => { writer.Write("Trace logs"); };
-
- var method = new TestMethodInfo(
- this.methodInfo,
- this.testClassInfo,
- this.testMethodOptions);
-
- var testablePlatformServiceProvider = new TestablePlatformServiceProvider();
- this.RunWithTestablePlatformService(testablePlatformServiceProvider, () =>
- {
- testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- PlatformServiceProvider.Instance = testablePlatformServiceProvider;
- var result = method.Invoke(null);
-
- Assert.AreEqual("Trace logs", result.DebugTrace);
- });
- }
-
- [TestMethodV1]
- public void TestMethodInfoInvokeShouldNotListenForDebugAndTraceLogsWhenDisabled()
- {
- this.testMethodOptions.CaptureDebugTraces = false;
-
- var method = new TestMethodInfo(
- this.methodInfo,
- this.testClassInfo,
- this.testMethodOptions);
- StringWriter writer = new StringWriter(new StringBuilder());
-
- DummyTestClass.TestMethodBody = o => { writer.Write("Trace logs"); };
-
- var testablePlatformServiceProvider = new TestablePlatformServiceProvider();
- this.RunWithTestablePlatformService(testablePlatformServiceProvider, () =>
- {
- testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- PlatformServiceProvider.Instance = testablePlatformServiceProvider;
- var result = method.Invoke(null);
-
- Assert.IsNull(result.DebugTrace);
- });
- }
-
[TestMethodV1]
public void TestMethodInfoInvokeShouldReportTestContextMessages()
{
diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodRunnerTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodRunnerTests.cs
index 9f9a5c7910..dd082732cd 100644
--- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodRunnerTests.cs
+++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TestMethodRunnerTests.cs
@@ -210,42 +210,6 @@ public void ExecuteForPassingTestShouldReturnUnitTestResultWithPassedOutcome()
Assert.AreEqual(AdapterTestOutcome.Passed, results[0].Outcome);
}
- [TestMethodV1]
- public void ExecuteShouldFillInDebugAndTraceLogsFromClassInitialize()
- {
- StringWriter writer = new StringWriter(new StringBuilder());
- DummyTestClass.ClassInitializeMethodBody = (UTFExtension.TestContext tc) =>
- {
- writer.Write("ClassInit trace");
- };
- this.testClassInfo.ClassInitializeMethod = typeof(DummyTestClass).GetMethod("DummyClassInit");
- var testMethodInfo = new TestableTestmethodInfo(this.methodInfo, this.testClassInfo, this.testMethodOptions, () => new UTF.TestResult() { Outcome = UTF.UnitTestOutcome.Passed });
- var testMethodRunner = new TestMethodRunner(testMethodInfo, this.testMethod, this.testContextImplementation, true);
-
- this.testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- var results = testMethodRunner.Execute();
- Assert.AreEqual("ClassInit trace", results[0].DebugTrace);
- }
-
- [TestMethodV1]
- public void ExecuteShouldFillInDebugAndTraceLogsFromAssemblyInitialize()
- {
- StringWriter writer = new StringWriter(new StringBuilder());
- DummyTestClass.AssemblyInitializeMethodBody = (UTFExtension.TestContext tc) =>
- {
- writer.Write("AssemblyInit trace");
- };
- this.testClassInfo.Parent.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("DummyAssemblyInit");
- var testMethodInfo = new TestableTestmethodInfo(this.methodInfo, this.testClassInfo, this.testMethodOptions, () => new UTF.TestResult() { Outcome = UTF.UnitTestOutcome.Passed });
- var testMethodRunner = new TestMethodRunner(testMethodInfo, this.testMethod, this.testContextImplementation, true);
-
- this.testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- var results = testMethodRunner.Execute();
- Assert.AreEqual("AssemblyInit trace", results[0].DebugTrace);
- }
-
[TestMethodV1]
public void ExecuteShouldNotFillInDebugAndTraceLogsIfDebugTraceDisabled()
{
@@ -283,28 +247,6 @@ public void ExecuteShouldNotFillInDebugAndTraceLogsFromRunningTestMethod()
Assert.AreEqual(string.Empty, results[0].DebugTrace);
}
- [TestMethodV1]
- public void ExecuteShouldFillInLogsIfAssemblyInitializeThrows()
- {
- StringWriter writer = new StringWriter(new StringBuilder());
- DummyTestClass.AssemblyInitializeMethodBody = (UTFExtension.TestContext tc) =>
- {
- writer.Write("Hills");
- tc.WriteLine("Valleys");
- throw new ArgumentException();
- };
- this.testClassInfo.Parent.AssemblyInitializeMethod = typeof(DummyTestClass).GetMethod("DummyAssemblyInit");
- var testMethodInfo = new TestableTestmethodInfo(this.methodInfo, this.testClassInfo, this.testMethodOptions, () => new UTF.TestResult() { Outcome = UTF.UnitTestOutcome.Passed });
- var testMethodRunner = new TestMethodRunner(testMethodInfo, this.testMethod, this.testContextImplementation, true);
-
- this.testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- var results = testMethodRunner.Execute();
-
- Assert.AreEqual("Hills", results[0].DebugTrace);
- StringAssert.Contains(results[0].TestContextMessages, "Valleys");
- }
-
[TestMethodV1]
public void RunTestMethodForTestThrowingExceptionShouldReturnUnitTestResultWithFailedOutcome()
{
diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/UnitTestRunnerTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/UnitTestRunnerTests.cs
index 79e5130a2a..fb7ce88259 100644
--- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/UnitTestRunnerTests.cs
+++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/UnitTestRunnerTests.cs
@@ -386,59 +386,6 @@ public void RunCleanupShouldReturnCleanupResultsForAssemblyAndClassCleanupMethod
Assert.IsTrue(cleanupresult.Warnings.All(w => w.Contains("NotImplemented")));
}
- [TestMethodV1]
- public void RunCleanupShouldReturnCleanupResultsWithDebugTraceLogsSetIfDebugTraceEnabled()
- {
- this.unitTestRunner = new UnitTestRunner(this.GetSettingsWithDebugTrace(true));
- try
- {
- var type = typeof(DummyTestClassWithCleanupMethods);
- var testMethod = new TestMethod(nameof(DummyTestClassWithCleanupMethods.TestMethod), type.FullName, "A", isAsync: false);
-
- this.testablePlatformServiceProvider.MockFileOperations.Setup(fo => fo.LoadAssembly("A", It.IsAny()))
- .Returns(Assembly.GetExecutingAssembly());
-
- StringWriter writer = new StringWriter(new StringBuilder("DummyTrace"));
-
- DummyTestClassWithCleanupMethods.ClassCleanupMethodBody = () =>
- {
- writer.Write("ClassCleanup");
- };
-
- this.testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- var testResult = this.unitTestRunner.RunSingleTest(testMethod, this.testRunParameters).FirstOrDefault();
- Assert.IsNotNull(testResult);
- Assert.AreEqual("DummyTrace", testResult.DebugTrace);
-
- var cleanupresult = this.unitTestRunner.RunCleanup();
- Assert.AreEqual("ClassCleanup", cleanupresult.DebugTrace);
- }
- finally
- {
- DummyTestClassWithCleanupMethods.ClassCleanupMethodBody = null;
- }
- }
-
- [TestMethodV1]
- public void RunCleanupShouldReturnCleanupResultsWithNoDebugAndTraceLogsSetIfDebugTraceDisabled()
- {
- var type = typeof(DummyTestClassWithCleanupMethods);
- var methodInfo = type.GetMethod("TestMethod");
- var testMethod = new TestMethod(methodInfo.Name, type.FullName, "A", isAsync: false);
-
- this.testablePlatformServiceProvider.MockFileOperations.Setup(fo => fo.LoadAssembly("A", It.IsAny()))
- .Returns(Assembly.GetExecutingAssembly());
-
- StringWriter writer = new StringWriter(new StringBuilder("DummyTrace"));
- this.testablePlatformServiceProvider.MockTraceListener.Setup(tl => tl.GetWriter()).Returns(writer);
-
- this.unitTestRunner.RunSingleTest(testMethod, this.testRunParameters);
-
- var cleanupresult = this.unitTestRunner.RunCleanup();
- Assert.AreEqual(null, cleanupresult.DebugTrace);
- }
-
#endregion
#region private helpers
@@ -510,28 +457,34 @@ public void TestMethod()
[DummyTestClass]
private class DummyTestClassWithCleanupMethods
{
+ public DummyTestClassWithCleanupMethods()
+ {
+ }
+
public static Action AssemblyCleanupMethodBody { get; set; }
public static Action ClassCleanupMethodBody { get; set; }
+ public static Action TestMethodBody { get; set; }
+
+ public UTFExtension.TestContext TestContext { get; set; }
+
[UTF.AssemblyCleanup]
public static void AssemblyCleanup()
{
- if (AssemblyCleanupMethodBody != null)
- {
- AssemblyCleanupMethodBody.Invoke();
- }
+ AssemblyCleanupMethodBody?.Invoke();
}
[UTF.ClassCleanup]
public static void ClassCleanup()
{
- ClassCleanupMethodBody.Invoke();
+ ClassCleanupMethodBody?.Invoke();
}
[UTF.TestMethod]
public void TestMethod()
{
+ TestMethodBody?.Invoke(this.TestContext);
}
}
diff --git a/test/UnitTests/PlatformServices.Desktop.Unit.Tests/Services/DesktopTestContextImplTests.cs b/test/UnitTests/PlatformServices.Desktop.Unit.Tests/Services/DesktopTestContextImplTests.cs
index 6d3faa6e4a..7f8c59e833 100644
--- a/test/UnitTests/PlatformServices.Desktop.Unit.Tests/Services/DesktopTestContextImplTests.cs
+++ b/test/UnitTests/PlatformServices.Desktop.Unit.Tests/Services/DesktopTestContextImplTests.cs
@@ -43,7 +43,7 @@ public void TestInit()
[TestMethod]
public void TestContextConstructorShouldInitializeProperties()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsNotNull(this.testContextImplementation.Properties);
}
@@ -54,7 +54,7 @@ public void TestContextConstructorShouldInitializeDefaultProperties()
this.testMethod.Setup(tm => tm.FullClassName).Returns("A.C.M");
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsNotNull(this.testContextImplementation.Properties);
@@ -69,7 +69,7 @@ public void TestContextConstructorShouldInitializeDefaultProperties()
[TestMethod]
public void CurrentTestOutcomeShouldReturnDefaultOutcome()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.AreEqual(UnitTestOutcome.Failed, this.testContextImplementation.CurrentTestOutcome);
}
@@ -77,7 +77,7 @@ public void CurrentTestOutcomeShouldReturnDefaultOutcome()
[TestMethod]
public void CurrentTestOutcomeShouldReturnOutcomeSet()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.SetOutcome(UnitTestOutcome.InProgress);
@@ -89,7 +89,7 @@ public void FullyQualifiedTestClassNameShouldReturnTestMethodsFullClassName()
{
this.testMethod.Setup(tm => tm.FullClassName).Returns("A.C.M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.AreEqual("A.C.M", this.testContextImplementation.FullyQualifiedTestClassName);
}
@@ -99,7 +99,7 @@ public void TestNameShouldReturnTestMethodsName()
{
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.AreEqual("M", this.testContextImplementation.TestName);
}
@@ -113,7 +113,7 @@ public void PropertiesShouldReturnPropertiesPassedToTestContext()
this.properties.Add(property1);
this.properties.Add(property2);
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
CollectionAssert.Contains(this.testContextImplementation.Properties, property1);
CollectionAssert.Contains(this.testContextImplementation.Properties, property2);
@@ -124,7 +124,7 @@ public void ContextShouldReturnTestContextObject()
{
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsNotNull(this.testContextImplementation.Context);
Assert.AreEqual("M", this.testContextImplementation.Context.TestName);
@@ -135,7 +135,7 @@ public void TryGetPropertyValueShouldReturnTrueIfPropertyIsPresent()
{
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsTrue(this.testContextImplementation.TryGetPropertyValue("TestName", out var propValue));
Assert.AreEqual("M", propValue);
@@ -144,7 +144,7 @@ public void TryGetPropertyValueShouldReturnTrueIfPropertyIsPresent()
[TestMethod]
public void TryGetPropertyValueShouldReturnFalseIfPropertyIsNotPresent()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsFalse(this.testContextImplementation.TryGetPropertyValue("Random", out var propValue));
Assert.IsNull(propValue);
@@ -153,7 +153,7 @@ public void TryGetPropertyValueShouldReturnFalseIfPropertyIsNotPresent()
[TestMethod]
public void AddPropertyShouldAddPropertiesToThePropertyBag()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddProperty("SomeNewProperty", "SomeValue");
CollectionAssert.Contains(
@@ -164,7 +164,7 @@ public void AddPropertyShouldAddPropertiesToThePropertyBag()
[TestMethod]
public void AddResultFileShouldThrowIfFileNameIsNull()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
var exception =
ActionUtility.PerformActionAndReturnException(() => this.testContextImplementation.AddResultFile(null));
@@ -176,7 +176,7 @@ public void AddResultFileShouldThrowIfFileNameIsNull()
[TestMethod]
public void AddResultFileShouldThrowIfFileNameIsEmpty()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
var exception =
ActionUtility.PerformActionAndReturnException(() => this.testContextImplementation.AddResultFile(string.Empty));
@@ -188,7 +188,7 @@ public void AddResultFileShouldThrowIfFileNameIsEmpty()
[TestMethod]
public void AddResultFileShouldAddFiletoResultsFiles()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddResultFile("C:\\temp.txt");
@@ -200,7 +200,7 @@ public void AddResultFileShouldAddFiletoResultsFiles()
[TestMethod]
public void AddResultFileShouldAddMultipleFilestoResultsFiles()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new System.IO.StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddResultFile("C:\\temp.txt");
this.testContextImplementation.AddResultFile("C:\\temp2.txt");
@@ -214,7 +214,7 @@ public void AddResultFileShouldAddMultipleFilestoResultsFiles()
[TestMethod]
public void WriteShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("{0} Testing write", 1);
StringAssert.Contains(stringWriter.ToString(), "1 Testing write");
@@ -223,7 +223,7 @@ public void WriteShouldWriteToStringWriter()
[TestMethod]
public void WriteShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("{0} Testing \0 write \0", 1);
StringAssert.Contains(stringWriter.ToString(), "1 Testing \\0 write \\0");
@@ -232,7 +232,7 @@ public void WriteShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
this.testContextImplementation.Write("{0} Testing write", 1);
@@ -244,7 +244,7 @@ public void WriteShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void WriteWithMessageShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("1 Testing write");
StringAssert.Contains(stringWriter.ToString(), "1 Testing write");
@@ -253,7 +253,7 @@ public void WriteWithMessageShouldWriteToStringWriter()
[TestMethod]
public void WriteWithMessageShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("1 Testing \0 write \0");
StringAssert.Contains(stringWriter.ToString(), "1 Testing \\0 write \\0");
@@ -262,7 +262,7 @@ public void WriteWithMessageShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteWithMessageShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
this.testContextImplementation.Write("1 Testing write");
@@ -274,7 +274,7 @@ public void WriteWithMessageShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void WriteWithMessageShouldWriteToStringWriterForReturnCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("2 Testing write \n\r");
this.testContextImplementation.Write("3 Testing write\n\r");
@@ -284,7 +284,7 @@ public void WriteWithMessageShouldWriteToStringWriterForReturnCharacters()
[TestMethod]
public void WriteLineShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("{0} Testing write", 1);
@@ -295,7 +295,7 @@ public void WriteLineShouldWriteToStringWriter()
[TestMethod]
public void WriteLineShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("{0} Testing \0 write \0", 1);
@@ -306,7 +306,7 @@ public void WriteLineShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteLineShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
@@ -320,7 +320,7 @@ public void WriteLineShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void WriteLineWithMessageShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("1 Testing write");
@@ -331,7 +331,7 @@ public void WriteLineWithMessageShouldWriteToStringWriter()
[TestMethod]
public void WriteLineWithMessageShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("1 Testing \0 write \0");
@@ -342,7 +342,7 @@ public void WriteLineWithMessageShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteLineWithMessageShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
@@ -356,7 +356,7 @@ public void WriteLineWithMessageShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void GetDiagnosticMessagesShouldReturnMessagesFromWriteLine()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.WriteLine("1 Testing write");
this.testContextImplementation.WriteLine("2 Its a happy day");
@@ -368,7 +368,7 @@ public void GetDiagnosticMessagesShouldReturnMessagesFromWriteLine()
[TestMethod]
public void ClearDiagnosticMessagesShouldClearMessagesFromWriteLine()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("1 Testing write");
@@ -382,7 +382,7 @@ public void ClearDiagnosticMessagesShouldClearMessagesFromWriteLine()
[TestMethod]
public void SetDataRowShouldSetDataRowObjectForCurrentRun()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
DataTable dataTable = new DataTable();
@@ -402,7 +402,7 @@ public void SetDataRowShouldSetDataRowObjectForCurrentRun()
[TestMethod]
public void SetDataConnectionShouldSetDbConnectionForFetchingData()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.Odbc");
diff --git a/test/UnitTests/PlatformServices.NetCore.Unit.Tests/Services/NetCoreTestContextImplementationTests.cs b/test/UnitTests/PlatformServices.NetCore.Unit.Tests/Services/NetCoreTestContextImplementationTests.cs
index 19e01619db..f0e1a7cc6a 100644
--- a/test/UnitTests/PlatformServices.NetCore.Unit.Tests/Services/NetCoreTestContextImplementationTests.cs
+++ b/test/UnitTests/PlatformServices.NetCore.Unit.Tests/Services/NetCoreTestContextImplementationTests.cs
@@ -47,7 +47,7 @@ public void TestInit()
[TestMethod]
public void TestContextConstructorShouldInitializeProperties()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsNotNull(this.testContextImplementation.Properties);
}
@@ -58,7 +58,7 @@ public void TestContextConstructorShouldInitializeDefaultProperties()
this.testMethod.Setup(tm => tm.FullClassName).Returns("A.C.M");
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsNotNull(this.testContextImplementation.Properties);
@@ -73,7 +73,7 @@ public void TestContextConstructorShouldInitializeDefaultProperties()
[TestMethod]
public void CurrentTestOutcomeShouldReturnDefaultOutcome()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.AreEqual(UnitTestOutcome.Failed, this.testContextImplementation.CurrentTestOutcome);
}
@@ -81,7 +81,7 @@ public void CurrentTestOutcomeShouldReturnDefaultOutcome()
[TestMethod]
public void CurrentTestOutcomeShouldReturnOutcomeSet()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.SetOutcome(UnitTestOutcome.InProgress);
@@ -93,7 +93,7 @@ public void FullyQualifiedTestClassNameShouldReturnTestMethodsFullClassName()
{
this.testMethod.Setup(tm => tm.FullClassName).Returns("A.C.M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.AreEqual("A.C.M", this.testContextImplementation.FullyQualifiedTestClassName);
}
@@ -103,7 +103,7 @@ public void TestNameShouldReturnTestMethodsName()
{
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.AreEqual("M", this.testContextImplementation.TestName);
}
@@ -117,7 +117,7 @@ public void PropertiesShouldReturnPropertiesPassedToTestContext()
this.properties.Add(property1);
this.properties.Add(property2);
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
CollectionAssert.Contains(this.testContextImplementation.Properties, property1);
CollectionAssert.Contains(this.testContextImplementation.Properties, property2);
@@ -128,7 +128,7 @@ public void ContextShouldReturnTestContextObject()
{
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsNotNull(this.testContextImplementation.Context);
Assert.AreEqual("M", this.testContextImplementation.Context.TestName);
@@ -139,7 +139,7 @@ public void TryGetPropertyValueShouldReturnTrueIfPropertyIsPresent()
{
this.testMethod.Setup(tm => tm.Name).Returns("M");
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsTrue(this.testContextImplementation.TryGetPropertyValue("TestName", out object propValue));
Assert.AreEqual("M", propValue);
}
@@ -147,7 +147,7 @@ public void TryGetPropertyValueShouldReturnTrueIfPropertyIsPresent()
[TestMethod]
public void TryGetPropertyValueShouldReturnFalseIfPropertyIsNotPresent()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
Assert.IsFalse(this.testContextImplementation.TryGetPropertyValue("Random", out object propValue));
Assert.IsNull(propValue);
}
@@ -155,7 +155,7 @@ public void TryGetPropertyValueShouldReturnFalseIfPropertyIsNotPresent()
[TestMethod]
public void AddPropertyShouldAddPropertiesToThePropertyBag()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddProperty("SomeNewProperty", "SomeValue");
@@ -167,7 +167,7 @@ public void AddPropertyShouldAddPropertiesToThePropertyBag()
[TestMethod]
public void WriteShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("{0} Testing write", 1);
StringAssert.Contains(stringWriter.ToString(), "1 Testing write");
@@ -176,7 +176,7 @@ public void WriteShouldWriteToStringWriter()
[TestMethod]
public void WriteShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("{0} Testing \0 write \0", 1);
StringAssert.Contains(stringWriter.ToString(), "1 Testing \\0 write \\0");
@@ -185,7 +185,7 @@ public void WriteShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
this.testContextImplementation.Write("{0} Testing write", 1);
@@ -197,7 +197,7 @@ public void WriteShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void WriteWithMessageShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("1 Testing write");
StringAssert.Contains(stringWriter.ToString(), "1 Testing write");
@@ -206,7 +206,7 @@ public void WriteWithMessageShouldWriteToStringWriter()
[TestMethod]
public void WriteWithMessageShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("1 Testing \0 write \0");
StringAssert.Contains(stringWriter.ToString(), "1 Testing \\0 write \\0");
@@ -215,7 +215,7 @@ public void WriteWithMessageShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteWithMessageShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
this.testContextImplementation.Write("1 Testing write");
@@ -227,7 +227,7 @@ public void WriteWithMessageShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void WriteWithMessageShouldWriteToStringWriterForReturnCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.Write("2 Testing write \n\r");
this.testContextImplementation.Write("3 Testing write\n\r");
@@ -237,7 +237,7 @@ public void WriteWithMessageShouldWriteToStringWriterForReturnCharacters()
[TestMethod]
public void WriteLineShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("{0} Testing write", 1);
@@ -248,7 +248,7 @@ public void WriteLineShouldWriteToStringWriter()
[TestMethod]
public void WriteLineShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("{0} Testing \0 write \0", 1);
@@ -259,7 +259,7 @@ public void WriteLineShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteLineShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
@@ -273,7 +273,7 @@ public void WriteLineShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void WriteLineWithMessageShouldWriteToStringWriter()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("1 Testing write");
@@ -284,7 +284,7 @@ public void WriteLineWithMessageShouldWriteToStringWriter()
[TestMethod]
public void WriteLineWithMessageShouldWriteToStringWriterForNullCharacters()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("1 Testing \0 write \0");
@@ -295,7 +295,7 @@ public void WriteLineWithMessageShouldWriteToStringWriterForNullCharacters()
[TestMethod]
public void WriteLineWithMessageShouldNotThrowIfStringWriterIsDisposed()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
stringWriter.Dispose();
@@ -309,7 +309,7 @@ public void WriteLineWithMessageShouldNotThrowIfStringWriterIsDisposed()
[TestMethod]
public void GetDiagnosticMessagesShouldReturnMessagesFromWriteLine()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.WriteLine("1 Testing write");
this.testContextImplementation.WriteLine("2 Its a happy day");
@@ -321,7 +321,7 @@ public void GetDiagnosticMessagesShouldReturnMessagesFromWriteLine()
[TestMethod]
public void ClearDiagnosticMessagesShouldClearMessagesFromWriteLine()
{
- var stringWriter = new StringWriter();
+ var stringWriter = new ThreadSafeStringWriter(null, "test");
this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, stringWriter, this.properties);
this.testContextImplementation.WriteLine("1 Testing write");
@@ -335,7 +335,7 @@ public void ClearDiagnosticMessagesShouldClearMessagesFromWriteLine()
[TestMethod]
public void AddResultFileShouldAddFiletoResultsFiles()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddResultFile("C:\\files\\myfile.txt");
var resultFile = this.testContextImplementation.GetResultFiles();
@@ -346,7 +346,7 @@ public void AddResultFileShouldAddFiletoResultsFiles()
[TestMethod]
public void AddResultFileShouldThrowIfFileNameIsNull()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
var exception = ActionUtility.PerformActionAndReturnException(() => this.testContextImplementation.AddResultFile(null));
@@ -357,7 +357,7 @@ public void AddResultFileShouldThrowIfFileNameIsNull()
[TestMethod]
public void AddResultFileShouldThrowIfFileNameIsEmpty()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
var exception = ActionUtility.PerformActionAndReturnException(() => this.testContextImplementation.AddResultFile(string.Empty));
@@ -368,7 +368,7 @@ public void AddResultFileShouldThrowIfFileNameIsEmpty()
[TestMethod]
public void AddResultFileShouldAddMultipleFilestoResultsFiles()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddResultFile("C:\\files\\file1.txt");
this.testContextImplementation.AddResultFile("C:\\files\\files2.html");
@@ -382,7 +382,7 @@ public void AddResultFileShouldAddMultipleFilestoResultsFiles()
[TestMethod]
public void GetResultFilesShouldReturnNullIfNoAddedResultFiles()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
var resultFile = this.testContextImplementation.GetResultFiles();
@@ -392,7 +392,7 @@ public void GetResultFilesShouldReturnNullIfNoAddedResultFiles()
[TestMethod]
public void GetResultFilesShouldReturnListOfAddedResultFiles()
{
- this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new StringWriter(), this.properties);
+ this.testContextImplementation = new TestContextImplementation(this.testMethod.Object, new ThreadSafeStringWriter(null, "test"), this.properties);
this.testContextImplementation.AddResultFile("C:\\files\\myfile.txt");
this.testContextImplementation.AddResultFile("C:\\files\\myfile2.txt");