Adding console output to NUnit test results

3.8k views Asked by At

I have been trying to figure out a way to add some string output to NUnit test results. I did some research and came across this, but this is not what I want. I want to write the output to the result xml generated by NUnit, but I cannot find a way to do it. Please suggest!

I aware that NUnit 3 will have a mechanism called TextContex to accomplish something similar, but I am using 2.6.3.

1

There are 1 answers

1
Jeff P On

You could take advantage of PropertyAttributes to attach properties per test to the XML output. The example below assumes you really want to use Console.WriteLine to produce string output, but you could always make your own TestConsole.WriteLine or something if you don't want to mess with the console output.

E.g. this attribute says to attach an "Output" property to each test it's declared on:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class TestWriterAttribute : PropertyAttribute
{
    public TestWriterAttribute() : base()
    {
        // Create a container for test output
        Properties["Output"] = new StringBuilder();
    }
}

And this attribute says to redirect Console.Out to your "Output" property (again, you can use your own TestConsole kind of class instead of using this attribute if you don't want to mess with Console.Out).

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ConsoleOutToTestWriterAttribute : TestActionAttribute
{
    public override void BeforeTest(TestDetails testDetails)
    {
        // If the test has a [TestWriter], redirect Console.Out to its "Output" property
        var output = TestContext.CurrentContext.Test.Properties["Output"] as StringBuilder;
        if (output != null) 
            Console.SetOut(new System.IO.StringWriter(output));
        _consoleOutRedirected = output != null;
    }

    public override void AfterTest(TestDetails testDetails)
    {
        // Reset Console.Out, if appropriate
        if(_consoleOutRedirected)
            Console.SetOut(new System.IO.StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true });
    }

    public override ActionTargets Targets
    {
        // needs to apply to each test, since [TestWriter]s are applied per test
        get { return ActionTargets.Test; }
    }

    private bool _consoleOutRedirected;
}

And your tests can just use Console.WriteLine which will be captured per test:

[ConsoleOutToTestWriter] // redirect Console.Out into "Output" property per test
public class ClassTest
{
    [Test]
    [TestWriter] // adds "Output" property
    public void MyTest()
    {
        Console.WriteLine("test 123");
        Console.WriteLine("321 test");
    }

    [Test]
    [TestWriter]
    public void MyTest2()
    {
        // this console output will be written to this test's own "Output"
        Console.WriteLine("test2 123");
        Console.WriteLine("321 test2");
    }
}

Which produces the following under <results> in the NUnit XML output:

<test-case name="SO_31092459.ClassTest.MyTest" executed="True" result="Success" success="True" time="0.023" asserts="0">
    <properties>
        <property name="Output" value="test 123&#xD;&#xA;321 test&#xD;&#xA;" />
    </properties>
</test-case>
<test-case name="SO_31092459.ClassTest.MyTest2" executed="True" result="Success" success="True" time="0.000" asserts="0">
    <properties>
        <property name="Output" value="test2 123&#xD;&#xA;321 test2&#xD;&#xA;" />
    </properties>
</test-case>