Skip to content

Commit c2f2d47

Browse files
committed
Add ability to provide live output messages from running tests
1 parent 013093b commit c2f2d47

22 files changed

Lines changed: 254 additions & 21 deletions

src/common/TestOptionsNames.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ internal static class Execution
1818
public static readonly string DisableParallelization = "xunit.execution.DisableParallelization";
1919
public static readonly string MaxParallelThreads = "xunit.execution.MaxParallelThreads";
2020
public static readonly string ParallelAlgorithm = "xunit.execution.ParallelAlgorithm";
21+
public static readonly string ShowLiveOutput = "xunit.execution.ShowLiveOutput";
2122
public static readonly string SynchronousMessageReporting = "xunit.execution.SynchronousMessageReporting";
2223
}
2324
}

src/xunit.console/CommandLine.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ protected CommandLine(string[] args, Predicate<string> fileExists = null)
5454

5555
public bool Serialize { get; protected set; }
5656

57+
public bool ShowLiveOutput { get; protected set; }
58+
5759
public bool StopOnFail { get; protected set; }
5860

5961
public bool UseAnsiColor { get; protected set; }
@@ -166,6 +168,11 @@ protected XunitProject Parse(Predicate<string> fileExists)
166168
GuardNoOptionValue(option);
167169
FailSkips = true;
168170
}
171+
else if (optionName == "showliveoutput")
172+
{
173+
GuardNoOptionValue(option);
174+
ShowLiveOutput = true;
175+
}
169176
else if (optionName == "stoponfail")
170177
{
171178
GuardNoOptionValue(option);

src/xunit.console/ConsoleRunner.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public int EntryPoint(string[] args)
8989
commandLine.ParallelizeTestCollections, commandLine.MaxParallelThreads,
9090
commandLine.DiagnosticMessages, commandLine.NoColor, commandLine.AppDomains,
9191
commandLine.FailSkips, commandLine.StopOnFail, commandLine.InternalDiagnosticMessages,
92-
commandLine.ParallelAlgorithm);
92+
commandLine.ParallelAlgorithm, commandLine.ShowLiveOutput);
9393

9494
if (cancel)
9595
return -1073741510; // 0xC000013A: The application terminated as a result of a CTRL+C
@@ -239,6 +239,7 @@ void PrintUsage(IReadOnlyList<IRunnerReporter> reporters)
239239
Console.WriteLine(" -wait : wait for input after completion");
240240
Console.WriteLine(" -diagnostics : enable diagnostics messages for all test assemblies");
241241
Console.WriteLine(" -internaldiagnostics : enable internal diagnostics messages for all test assemblies");
242+
Console.WriteLine(" -showliveoutput : show output messages from tests live");
242243
#if DEBUG
243244
Console.WriteLine(" -pause : pause before doing any work, to help attach a debugger");
244245
#endif
@@ -302,7 +303,8 @@ int RunProject(XunitProject project,
302303
bool failSkips,
303304
bool stopOnFail,
304305
bool internalDiagnosticMessages,
305-
ParallelAlgorithm? parallelAlgorithm)
306+
ParallelAlgorithm? parallelAlgorithm,
307+
bool showLiveOutput)
306308
{
307309
XElement assembliesElement = null;
308310
var clockTime = Stopwatch.StartNew();
@@ -319,7 +321,7 @@ int RunProject(XunitProject project,
319321

320322
if (parallelizeAssemblies.GetValueOrDefault())
321323
{
322-
var tasks = project.Assemblies.Select(assembly => Task.Run(() => ExecuteAssembly(consoleLock, assembly, serialize, needsXml, parallelizeTestCollections, maxThreadCount, diagnosticMessages, noColor, appDomains, failSkips, stopOnFail, project.Filters, internalDiagnosticMessages, parallelAlgorithm)));
324+
var tasks = project.Assemblies.Select(assembly => Task.Run(() => ExecuteAssembly(consoleLock, assembly, serialize, needsXml, parallelizeTestCollections, maxThreadCount, diagnosticMessages, noColor, appDomains, failSkips, stopOnFail, project.Filters, internalDiagnosticMessages, parallelAlgorithm, showLiveOutput)));
323325
var results = Task.WhenAll(tasks).GetAwaiter().GetResult();
324326
foreach (var assemblyElement in results.Where(result => result != null))
325327
assembliesElement.Add(assemblyElement);
@@ -328,7 +330,7 @@ int RunProject(XunitProject project,
328330
{
329331
foreach (var assembly in project.Assemblies)
330332
{
331-
var assemblyElement = ExecuteAssembly(consoleLock, assembly, serialize, needsXml, parallelizeTestCollections, maxThreadCount, diagnosticMessages, noColor, appDomains, failSkips, stopOnFail, project.Filters, internalDiagnosticMessages, parallelAlgorithm);
333+
var assemblyElement = ExecuteAssembly(consoleLock, assembly, serialize, needsXml, parallelizeTestCollections, maxThreadCount, diagnosticMessages, noColor, appDomains, failSkips, stopOnFail, project.Filters, internalDiagnosticMessages, parallelAlgorithm, showLiveOutput);
332334
if (assemblyElement != null)
333335
assembliesElement.Add(assemblyElement);
334336
}
@@ -362,7 +364,8 @@ XElement ExecuteAssembly(object consoleLock,
362364
bool stopOnFail,
363365
XunitFilters filters,
364366
bool internalDiagnosticMessages,
365-
ParallelAlgorithm? parallelAlgorithm)
367+
ParallelAlgorithm? parallelAlgorithm,
368+
bool showLiveOutput)
366369
{
367370
foreach (var warning in assembly.ConfigWarnings)
368371
logger.LogWarning(warning);
@@ -394,6 +397,8 @@ XElement ExecuteAssembly(object consoleLock,
394397
executionOptions.SetMaxParallelThreads(maxThreadCount);
395398
if (parallelizeTestCollections.HasValue)
396399
executionOptions.SetDisableParallelization(!parallelizeTestCollections.GetValueOrDefault());
400+
if (showLiveOutput)
401+
executionOptions.SetShowLiveOutput(showLiveOutput);
397402
if (stopOnFail)
398403
executionOptions.SetStopOnTestFail(stopOnFail);
399404
if (parallelAlgorithm.HasValue)

src/xunit.execution/Extensions/TestFrameworkOptionsReadExtensions.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,25 @@ public static int MaxParallelThreadsOrDefault(this ITestFrameworkExecutionOption
176176
return result.GetValueOrDefault();
177177
}
178178

179+
/// <summary>
180+
/// Gets a flag which indicates if the developer wishes to see output from <see cref="ITestOutputHelper"/>
181+
/// live while it's being reported (in addition to seeing it collected together when the test is finished).
182+
/// </summary>
183+
public static bool? ShowLiveOutput(this ITestFrameworkExecutionOptions executionOptions)
184+
{
185+
return executionOptions.GetValue<bool?>(TestOptionsNames.Execution.ShowLiveOutput);
186+
}
187+
188+
/// <summary>
189+
/// Gets a flag which indicates if the developer wishes to see output from <see cref="ITestOutputHelper"/>
190+
/// live while it's being reported (in addition to seeing it collected together when the test is finished).
191+
/// If the flag is not present, returns the default value (<c>false</c>).
192+
/// </summary>
193+
public static bool ShowLiveOutputOrDefault(this ITestFrameworkExecutionOptions executionOptions)
194+
{
195+
return executionOptions.ShowLiveOutput() ?? false;
196+
}
197+
179198
/// <summary>
180199
/// Gets a flag to stop testing on test failure.
181200
/// </summary>

src/xunit.runner.msbuild/xunit.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class xunit : MSBuildTask, ICancelableTask
2525
bool? parallelizeTestCollections;
2626
IMessageSinkWithTypes reporterMessageHandler;
2727
bool? shadowCopy;
28+
bool? showLiveOutput;
2829
bool? stopOnFail;
2930

3031
public string AppDomains { get; set; }
@@ -89,6 +90,8 @@ protected bool NeedsXml
8990

9091
public bool ShadowCopy { set { shadowCopy = value; } }
9192

93+
public bool ShowLiveOutput { set { showLiveOutput = value; } }
94+
9295
public bool StopOnFail { set { stopOnFail = value; } }
9396

9497
public string WorkingFolder { get; set; }
@@ -284,6 +287,8 @@ protected virtual XElement ExecuteAssembly(XunitProjectAssembly assembly, AppDom
284287
executionOptions.SetParallelAlgorithm(parallelAlgorithm);
285288
if (parallelizeTestCollections.HasValue)
286289
executionOptions.SetDisableParallelization(!parallelizeTestCollections);
290+
if (showLiveOutput.HasValue)
291+
executionOptions.SetShowLiveOutput(showLiveOutput);
287292
if (stopOnFail.HasValue)
288293
executionOptions.SetStopOnTestFail(stopOnFail);
289294

src/xunit.runner.reporters/VerboseReporterMessageHandler.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ public class VerboseReporterMessageHandler : DefaultRunnerReporterWithTypesMessa
55
public VerboseReporterMessageHandler(IRunnerLogger logger)
66
: base(logger)
77
{
8-
Execution.TestOutputEvent += args => Logger.LogMessage(" {0} [OUTPUT] {1}", Escape(args.Message.Test.DisplayName), Escape(args.Message.Output.TrimEnd('\r', '\n')));
98
Execution.TestStartingEvent += args => Logger.LogMessage(" {0} [STARTING]", Escape(args.Message.Test.DisplayName));
109
Execution.TestFinishedEvent += args => Logger.LogMessage(" {0} [FINISHED] Time: {1}s", Escape(args.Message.Test.DisplayName), args.Message.ExecutionTime);
1110
}

src/xunit.runner.utility/Configuration/ConfigReader_Configuration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ static class Configuration
132132
public const string AppDomain = "xunit.appDomain";
133133
public const string DiagnosticMessages = "xunit.diagnosticMessages";
134134
public const string InternalDiagnosticMessages = "xunit.internalDiagnosticMessages";
135+
public const string LongRunningTestSeconds = "xunit.longRunningTestSeconds";
135136
public const string MaxParallelThreads = "xunit.maxParallelThreads";
136137
public const string MethodDisplay = "xunit.methodDisplay";
137138
public const string MethodDisplayOptions = "xunit.methodDisplayOptions";
@@ -141,7 +142,6 @@ static class Configuration
141142
public const string PreEnumerateTheories = "xunit.preEnumerateTheories";
142143
public const string ShadowCopy = "xunit.shadowCopy";
143144
public const string StopOnFail = "xunit.stopOnFail";
144-
public const string LongRunningTestSeconds = "xunit.longRunningTestSeconds";
145145
}
146146
}
147147
}

src/xunit.runner.utility/Configuration/ConfigReader_Json.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ string ConfigDescription() =>
111111
result.PreEnumerateTheories = booleanValue;
112112
if (string.Equals(propertyName, Configuration.ShadowCopy, StringComparison.OrdinalIgnoreCase))
113113
result.ShadowCopy = booleanValue;
114+
if (string.Equals(propertyName, Configuration.ShowLiveOutput, StringComparison.OrdinalIgnoreCase))
115+
result.ShowLiveOutput = booleanValue;
114116
if (string.Equals(propertyName, Configuration.StopOnFail, StringComparison.OrdinalIgnoreCase))
115117
result.StopOnFail = booleanValue;
116118
}
@@ -270,6 +272,7 @@ static class Configuration
270272
public const string ParallelizeTestCollections = "parallelizeTestCollections";
271273
public const string PreEnumerateTheories = "preEnumerateTheories";
272274
public const string ShadowCopy = "shadowCopy";
275+
public const string ShowLiveOutput = "showLiveOutput";
273276
public const string StopOnFail = "stopOnFail";
274277
}
275278
}

src/xunit.runner.utility/Extensions/TestFrameworkOptionsReadWriteExtensions.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,25 @@ public static ParallelAlgorithm GetParallelAlgorithmOrDefault(this ITestFramewor
260260
return executionOptions.GetParallelAlgorithm() ?? ParallelAlgorithm.Conservative;
261261
}
262262

263+
/// <summary>
264+
/// Gets a flag which indicates if the developer wishes to see output from <see cref="ITestOutputHelper"/>
265+
/// live while it's being reported (in addition to seeing it collected together when the test is finished).
266+
/// </summary>
267+
public static bool? GetShowLiveOutput(this ITestFrameworkExecutionOptions executionOptions)
268+
{
269+
return executionOptions.GetValue<bool?>(TestOptionsNames.Execution.ShowLiveOutput);
270+
}
271+
272+
/// <summary>
273+
/// Gets a flag which indicates if the developer wishes to see output from <see cref="ITestOutputHelper"/>
274+
/// live while it's being reported (in addition to seeing it collected together when the test is finished).
275+
/// If the flag is not present, returns the default value (<c>false</c>).
276+
/// </summary>
277+
public static bool GetShowLiveOutputOrDefault(this ITestFrameworkExecutionOptions executionOptions)
278+
{
279+
return executionOptions.GetShowLiveOutput() ?? false;
280+
}
281+
263282
/// <summary>
264283
/// Gets a flag that determines whether xUnit.net stop testing when a test fails.
265284
/// </summary>
@@ -318,6 +337,15 @@ public static void SetParallelAlgorithm(this ITestFrameworkExecutionOptions exec
318337
executionOptions.SetValue(TestOptionsNames.Execution.ParallelAlgorithm, value.HasValue ? value.GetValueOrDefault().ToString() : null);
319338
}
320339

340+
/// <summary>
341+
/// Sets a flag which indicates if the developer wishes to see output from <see cref="ITestOutputHelper"/>
342+
/// live while it's being reported (in addition to seeing it collected together when the test is finished).
343+
/// </summary>
344+
public static void SetShowLiveOutput(this ITestFrameworkExecutionOptions executionOptions, bool? value)
345+
{
346+
executionOptions.SetValue(TestOptionsNames.Execution.ShowLiveOutput, value);
347+
}
348+
321349
/// <summary>
322350
/// Sets a flag that determines whether xUnit.net stop testing when a test fails.
323351
/// </summary>

src/xunit.runner.utility/Frameworks/TestAssemblyConfiguration.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Xunit.Abstractions;
23

34
namespace Xunit
45
{
@@ -168,6 +169,19 @@ public int MaxParallelThreadsOrDefault
168169
/// </summary>
169170
public bool ShadowCopyOrDefault { get { return ShadowCopy ?? true; } }
170171

172+
/// <summary>
173+
/// Gets or sets a flag indicating whether output from <see cref="ITestOutputHelper"/> should be
174+
/// shown live as they're logged (in addition to being collected together after the test finishes).
175+
/// </summary>
176+
public bool? ShowLiveOutput { get; set; }
177+
178+
/// <summary>
179+
/// Gets a flag indicating whether output from <see cref="ITestOutputHelper"/> should be
180+
/// shown live as they're logged (in addition to being collected together after the test finishes).
181+
/// If the flag is not set, returns the default value (<c>false</c>).
182+
/// </summary>
183+
public bool ShowLiveOutputOrDefault { get { return ShowLiveOutput ?? false; } }
184+
171185
/// <summary>
172186
/// Gets or sets a flag indicating whether testing should stop on a failure.
173187
/// </summary>

0 commit comments

Comments
 (0)