-
Notifications
You must be signed in to change notification settings - Fork 742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.NET Core Logging only logs for the first test case #3919
Comments
Logging to console is not a reliable way to log something to test results, especially when multiple threads are involved (see here). The recommended way is to use Concerning behavior, that you've observed. |
Thank you for your reply. I appreciate very much you provided a sample I was wondering though if the root cause of the problem should be understood, as this doesn't appear to be a race condition to the threaded behaviour of the When I was singlestepping through the code, it appears that the After reading the specification, it does appear though that the authors want to remove this completely (it would be nice to know when, I've got a lot of my code that depends on this)!. |
As I mentioned - problem is that ConsoleLogger uses a separate thread to invoke Console.WriteLine, and this thread is created in the first executed test. NUnit uses thread info to associate console messages to particular test, and the actual logging thread is always the same - from that first test.
You mean NUnit authors? I might be wrong, of course, but I seriously doubt that will ever happen, as that would be hell of a breaking change for a lot of people. |
Hi @Dreamescaper, now it's clear
And that thread is constant as I saw from MS code, so NUnit can't know. I appreciate your time. I'll close this ticket as resolved and I'll work on my own NUnit ILogger based on your example. |
Yeah, the documentation you pointed to has "Trace and Log output will no longer be handled by NUnit at all.". |
Note that trace and Log output are not handled specially by NUnit now. The bullet in the specification was written when creating NUnit version 3, as version 2 had special handling of trace and of log4net. This is no longer the case. From #1139 (comment)
|
Add an NUnitLogger, based on the example given in [1], and documentation from Microsoft in [2]. When logging, it might be tempting to use `.AddConsole()`, but NUnit can't log the console reliably, and results in missing output, or output in the wrong test case. Using NUnit.TestContext.Write() resolves this problem and allows your test cases to log to NUnit. [1] nunit/nunit#3919 (comment) [2] https://docs.microsoft.com/en-us/dotnet/core/extensions/custom-logging-provider The code itself doesn't have a direct dependency to NUnit.Framework, but pulls it in via reflection. This allows the user to have the library automaticall adapt to NUnit 2.x or NUnit 3.x (they're similar, but not compatible and otherwise both can't be used at the same time). Issue: DOTNET-382
I'm attaching a very simple example on reproduction testlog.zip
Description
If I run
TestCase1
on its own, orTestCase2
on its own, then output from logging is captured and can be analysed. If I run them both, then generally the output ofTestCase1
is captured, but notTestCase2
, depending on which test case runs first (e.g.TestCase1
). If I modify sources so that theILoggerFactory
is instantiated before every test case, then it appears to work as expected, but this makes the assumption that code under test won't do this (and so this is not a suitable workaround).I used dotPeek as a symbol/source server, so some of the code might differ from what's published as sources. I was able to determine that the problem comes down to how the logs are written into a stringbuilder, but I do not understand enough of the NUnit sources to figure out where the root cause is, only that the underlying code is getting the log messages, but not recording it to the output.
I'd like to know if this is a bug in NUnit, and if not, how it might be possible to workaround.
Version: netcoreapp3.1
Environment: Debugging within VSIDE 2019
Preanalysis
The internal class
Microsoft.Extensions.Logging.Logger.Log<TState>(LogLevel, EventId, TState, Exception, Func<TState, Exception, string>)
is called.The value
local.IsEnabled(Debug)
istrue
, andLoggerLog
is called, which just calls:The above goes into
ConsoleLogger.Log<TState>(...)
, it writes successfully theWriteMessage
internally, which adds to a queue, and a separate thread is then responsible for writing this to the output. This is done byHence we can tell that the Microsoft Logger did receive the log message.
Then method
EnqueueMessage
is in the classConsoleLoggerProcessor
, and internally puts the message on a queue.In parallel a thread is reading from the queue and writing to the console calling
WriteMessage
.In the
WriteMessage
we see:and that the
console
is aSytem.IO.TextWriter.SyncTextWriter
, and it has an internal property_out
which is of typeNUnit.Framework.Internal.Execution.TextCapture
.It is simply defined in
WindowsLogConsole
as:I put a breakpoint in
NUnit.Framework.Internal.Execution.TextCapture.Write
here:and I can see that
value
is the debug message I'm printing. For some reason though, it is not showing up in the output of my test case.The actual
Write
method looks like:and the value is being appended to
_sb
, but appears as though it might be for the previous test case still, even though it isn't printed there.So NUnit did receive the debug message, but there seems to be some synchronization missing that it doesn't show up in the debug outputs.
The text was updated successfully, but these errors were encountered: