Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resharper test runner not outputting Console.WriteLine()?

Why is it that Console.Writeline() will work when executing from a console app main() method; but when I execute the same using resharpers test runner I do not see the Console.Writeline() in the test runner output window?

The best way to explain this is with an example.

I am using: Resharper Ultimate 2017.1.3, Visual Studio 2017 Community, and .Net 4.6.1 framework. Language is C#. I also installed (via nuget) nunit framework 2.6.4.

First create a class library and copy paste the following in to a .cs file.

using System;
using System.Collections;
using System.Threading;
using NUnit.Framework;

namespace ObserverPatternExample
{
    [TestFixture]
    internal class ObserverTestFixture
    {
        [Test]
        public void DemonstrateObserverPattern()
        {
            var subject = new Subject();
            var a = new Observer(subject, "a");
            var b = new Observer(subject, "b"); // etc. as many observers as you want.

            subject.Go();
        }
    }

    // "subject" is observer pattern lingo. The "subject" will do the broadcasting to the observers.
    public class Subject 
    {
        public delegate void CallbackHandler(string s);
        public event CallbackHandler NotifyEvent;
        private const int waitTimeInMilliseconds = 200;
        private readonly Simulator simulator = new Simulator();
        public string FakeSimulatorState { get; set; }

        public void Go()
        {
            new Thread(Run).Start(); // a good thing to notice: events cross thread boundaries!!!
        }

        private void Run()
        {
            foreach (string s in simulator)
            {
                Console.WriteLine("Subject: " + s);
                FakeSimulatorState = s;
                NotifyEvent?.Invoke(s);
                Thread.Sleep(
                    waitTimeInMilliseconds); // we do this to "pretend" that the simulator is actually doing someting.
            }
        }


    }

    public class Observer : IObserverPattern // the "observer" will subscribe to the event being broadcast by the "subject"
    {
        private readonly string _name;
        public Observer(Subject subject, string name)
        {
            _name = name;
            subject.NotifyEvent += Update;
        }
        public void Update(string state)
        {
            Console.WriteLine("Observer {0}: {1}", _name, state);
        }
    }

    internal interface IObserverPattern
    {
        void Update(string state);
    }

    public class Simulator : IEnumerable
    {
        private readonly string[] _stateSequence = { "BEGIN", "CRAWL", "WALK", "JUMP", "END" };

        public IEnumerator GetEnumerator()
        {
            foreach (var s in _stateSequence)
                yield return s;
        }
    }
}

And now execute the test. I expect to see the Console.WriteLine() calls display strings in the Resharper test runner output window. But I don't. For example here is a screenshot:

enter image description here

Now let's perform the exact same sequence, but this time we'll call the client code from a new console project main() method. To set this up copy paste the following code and reference the class library you created in the steps above.

using ObserverPatternExample;

namespace ConsoleApp1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var subject = new Subject();
            var a = new Observer(subject, "a");
            var b = new Observer(subject, "b"); // etc. as many observers as you want.

            subject.Go();
        }
    }
}

Next execute the console app. You should see the following displayed:

enter image description here

Can anyone please explain how I can configure either my code or the test runner to display the output in the test runner output window?

* UPDATE * I made partial success. InBetween's suggestion to use a TraceListener made me realize I should be using a ConsoleTraceListener. To faciliate this I modified the unit test to appear like this:

using System.Threading;
using NUnit.Framework;

namespace ObserverPatternExample.DontUse
{
    [TestFixture]
    internal class ObserverTestFixture
    {
        [SetUp]
        public void Setup()
        {
            Trace.Listeners.Add(new ConsoleTraceListener());
        }

        [TearDown]
        public void TearDown()
        {
            Trace.Flush();
        }

        [Test]
        public void DemonstrateObserverPattern()
        {
            var subject = new Subject();
            var a = new Observer(subject, "a");
            var b = new Observer(subject, "b"); // etc. as many observers as you want.

            subject.Go();
        }
    }

And the results are surprising: I do get SOME output; but only the initial BEGIN state. Which appears like this:

enter image description here

Short story: I'm still looking for a solution.

*** SOLUTION ****

        [Test]
        public void DemonstrateObserverPattern()
        {
            var subject = new Subject();
            var a = new Observer(subject, "a");
            var b = new Observer(subject, "b"); // etc. as many observers as you want.

            subject.Go();

Thread.Sleep(1000); // <--- add this to force test runner to wait for other thread to complete.
        }
like image 288
sapbucket Avatar asked Oct 29 '22 23:10

sapbucket


1 Answers

It looks like Resharper is finishing before your thread completes. Your call to

Thread(Run).Start();

is non-blocking. This means the test thread will complete before the Go thread does, hence you get no results.

See https://msdn.microsoft.com/en-us/library/6x4c42hc(v=vs.110).aspx where is states "Note that the call to Start does not block the calling thread."

like image 50
Stephen Straton Avatar answered Nov 15 '22 06:11

Stephen Straton