Extends xUnit to simplify logging.
Redirects Trace.Write, Debug.Write, and Console.Write and Console.Error.Write to ITestOutputHelper. Also provides static access to the current ITestOutputHelper for use within testing utility methods.
Uses AsyncLocal to track state.
toc
https://nuget.org/packages/XunitLogger/
snippet: ClassBeingTested.cs
XunitLoggingBase
is an abstract base class for tests. It exposes logging methods for use from unit tests, and handle the flushing of longs in its Dispose
method. XunitLoggingBase
is actually a thin wrapper over XunitLogging
. XunitLogging
s Write*
methods can also be use inside a test inheriting from XunitLoggingBase
.
snippet: TestBaseSample.cs
XunitLogging
provides static access to the logging state for tests. It exposes logging methods for use from unit tests, however registration of ITestOutputHelper and flushing of logs must be handled explicitly.
snippet: XunitLoggerSample.cs
XunitLogging
redirects Trace.Write, Console.Write, and Debug.Write in its static constructor.
snippet: writeRedirects
These API calls are then routed to the correct xUnit ITestOutputHelper via a static AsyncLocal.
XunitLogger.Filters
can be used to filter out unwanted lines:
snippet: FilterSample.cs
Filters are static and shared for all tests.
For every tests there is a contextual API to perform several operations.
Context.TestOutput
: Access to ITestOutputHelper.Context.Write
andContext.WriteLine
: Write to the current log.Context.LogMessages
: Access to all log message for the current test.- Counters: Provide access in predicable and incrementing values for the following types:
Guid
,Int
,Long
,UInt
, andULong
. Context.Test
: Access to the currentITest
.
There is also access via a static API.
snippet: ContextSample.cs
There is currently no API in xUnit to retrieve information on the current test. See issues #1359, #416, and #398.
To work around this, this project exposes the current instance of ITest
via reflection.
Usage:
snippet: CurrentTestSample.cs
Implementation:
snippet: LoggingContext_CurrentTest.cs
When a test fails it is expressed as an exception. The exception can be viewed by enabling exception capture, and then accessing Context.TestException
. The TestException
will be null if the test has passed.
One common case is to perform some logic, based on the existence of the exception, in the Dispose
of a test.
snippet: TestExceptionSample
Provide access to predicable and incrementing values for the following types: Guid
, Int
, Long
, UInt
, and ULong
.
Counters can also be used outside of the current test context:
snippet: NonTestContextUsage
snippet: LoggingContext_Counters.cs
snippet: Counters.cs
snippet: GuidCounter.cs
snippet: LongCounter.cs
When creating a custom base class for other tests, it is necessary to pass through the source file path to XunitLoggingBase
via the constructor.
snippet: XunitLoggingCustomBase
Provided the parameters passed to the current test when using a [Theory]
.
Usage:
snippet: ParametersSample.cs
Implementation:
snippet: Parameters
Provided a string that uniquely identifies a test case.
Usage:
snippet: UniqueTestNameSample.cs
Implementation:
snippet: UniqueTestName
Approaches to routing common logging libraries to Diagnostics.Trace:
- Serilog use Serilog.Sinks.Trace.
- NLog use a Trace target.
The default behavior of ApprovalTests uses the StackTrace to derive the current test and hence compute the name of the approval file. This has several drawbacks/issues:
- Fragility: Deriving the test name from a stack trace is dependent on several things to be configured correctly. Optimization must be disabled to avoid in-lining and debug symbols enabled and parsable.
- Performance impact: Computing a stack trace is a relatively expensive operation. Disabling optimization also impacts performance
Xunit.ApprovalTests avoids these problems by using the current xUnit context to derive the approval file name.
https://nuget.org/packages/Xunit.ApprovalTests/
Usage is done via inheriting from a base class XunitApprovalBase
snippet: XunitApprovalBaseUsage
xUnit Theories are supported.
snippet: Theory
Will result in the following .approved.
files:
Sample.Theory_value=Foo.approved.txt
Sample.Theory_value=9.approved.txt
Sample.Theory_value=True.approved.txt
ApprovalTests NamerFactory.AsEnvironmentSpecificTest
is supported.
snippet: AsEnvironmentSpecificTest
Will result in the following .approved.
file:
Sample.AsEnvironmentSpecificTest_Foo.approved.txt
ApprovalTests [UseApprovalSubdirectory]
is supported.
snippet: UseApprovalSubdirectory
Will result in the following .approved.
file:
SubDir\Sample.InSubDir.approved.txt
ApprovalTests ApprovalResults.ForScenario
is supported.
snippet: ForScenario
Will result in the following .approved.
file:
Sample.ForScenarioTest_ForScenario.Name.approved.txt
When creating a custom base class for other tests, it is necessary to pass through the source file path to XunitApprovalBase
via the constructor.
snippet: XunitApprovalCustomBase
See closed milestones.
Wolverine designed by Mike Rowe from The Noun Project.