I just started testing xUnit.net, but it doesn't seem to capture any output (Console, Debug, Trace), as I would have expected.
Is that possible? I am using a sample .NET 4.0 class-library with xUnit.net 1.8.
In general, it's a bad road to go down to be reliant on logging and tests. The pass/fail should be the outcome of the tests. And they simply shouldn't get to the stage where there's enough stuff going on that looking at a trace will be necessary.
The xunit.gui.exe
shows Console and Trace output, xunit.console.exe
does not. If it's important, you could hook up a TraceListener which redirects to a file by making appropriate standard .NET config entries (Theres' a FileWriterTraceListener
which you should be able to hook in if you google it).
UPDATE: As discussed in his blog post, Damian Hickey has a good example of a possible substitute - wiring logging to the xUnit 2 ITestOutputHelper
as demonstrated in https://github.com/damianh/CapturingLogOutputWithXunit2AndParallelTests/blob/master/src/Lib.Tests/Tests.cs
UPDATE 2: In some cases, one can add logging and feed it to the ITestOutputHelper
without involving LogContext
by using a simple adapter as follows (I only have it in F#, sorry):
// Requirement: Make SUT depend on Serilog NuGet
// Requirement: Make Tests depend on Serilog.Sinks.Observable
type TestOutputAdapter(testOutput : Xunit.Abstractions.ITestOutputHelper) =
let formatter = Serilog.Formatting.Display.MessageTemplateTextFormatter(
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}", null);
let write logEvent =
use writer = new System.IO.StringWriter()
formatter.Format(logEvent, writer);
writer |> string |> testOutput.WriteLine
member __.Subscribe(source: IObservable<Serilog.Events.LogEvent>) =
source.Subscribe write
let createLogger hookObservers =
LoggerConfiguration()
.WriteTo.Observers(Action<_> hookObservers)
.CreateLogger()
let createTestOutputLogger (output: ITestOutputHelper) =
let adapter = TestOutputAdapter testOutputHelper
createLogger (adapter.Subscribe >> ignore)
type Tests(testOutputHelper) =
let log = createTestOutputLogger testOutputHelper
[<Fact>] let feedToSut () =
// TODO pass log to System Under Test either as a ctor arg or a method arg
The difference with this approach vs using the log context is that logging to the global [contextualized] Serilog Logger
will not get picked up.