How to Write Output from a Unit Test

How can I write output from a unit test?

Try using TestContext.WriteLine() which outputs text in test results.

Example:

[TestClass]
public class UnitTest1
{
private TestContext testContextInstance;

/// <summary>
/// Gets or sets the test context which provides
/// information about and functionality for the current test run.
/// </summary>
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}

[TestMethod]
public void TestMethod1()
{
TestContext.WriteLine("Message...");
}
}

The "magic" is described in MSDN:

To use TestContext, create a member and property within your test class [...] The test framework automatically sets the property, which you can then use in unit tests.

Can I write into the console in a unit test? If yes, why doesn't the console window open?

NOTE: The original answer below should work for any version of Visual Studio up through Visual Studio 2012. Visual Studio 2013 does not appear to have a Test Results window any more. Instead, if you need test-specific output you can use @Stretch's suggestion of Trace.Write() to write output to the Output window.


The Console.Write method does not write to the "console" -- it writes to whatever is hooked up to the standard output handle for the running process. Similarly, Console.Read reads input from whatever is hooked up to the standard input.

When you run a unit test through Visual Studio 2010, standard output is redirected by the test harness and stored as part of the test output. You can see this by right-clicking the Test Results window and adding the column named "Output (StdOut)" to the display. This will show anything that was written to standard output.

You could manually open a console window, using P/Invoke as sinni800 says. From reading the AllocConsole documentation, it appears that the function will reset stdin and stdout handles to point to the new console window. (I'm not 100% sure about that; it seems kind of wrong to me if I've already redirected stdout for Windows to steal it from me, but I haven't tried.)

In general, though, I think it's a bad idea; if all you want to use the console for is to dump more information about your unit test, the output is there for you. Keep using Console.WriteLine the way you are, and check the output results in the Test Results window when it's done.

Print output of function inside of unit test

In your class (Function) you are using Console.WriteLine. This will not generate any output in the test. Instead you can use an ILogger which can be installed with Microsoft.Extensions.Logging.Abstractions. When using an ILogger you can have several providers, which in turn can write to both Console and to test-output. The code below is based on a post from meziantou.net. Read that post for a complete example. It creates an implementation for ILogger that will write to your test-output.

Your logger:

public class XUnitLogger : ILogger
{
private readonly ITestOutputHelper _testOutputHelper;
private readonly LoggerExternalScopeProvider _scopeProvider;
private readonly string _categoryName;

public static ILogger CreateLogger(ITestOutputHelper testOutputHelper) => new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider(), "");

public XUnitLogger(ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider, string categoryName)
{
_testOutputHelper = testOutputHelper;
_scopeProvider = scopeProvider;
_categoryName = categoryName;
}

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var sb = new StringBuilder();
sb.Append(GetLogLevelString(logLevel))
.Append(" [").Append(_categoryName).Append("] ")
.Append(formatter(state, exception));

if (exception != null)
{
sb.Append('\n').Append(exception);
}

// Append scopes
_scopeProvider.ForEachScope((scope, state) =>
{
state.Append("\n => ");
state.Append(scope);
}, sb);

_testOutputHelper.WriteLine(sb.ToString());
}

private static string GetLogLevelString(LogLevel logLevel)
{
return logLevel switch
{
LogLevel.Trace => "trce",
LogLevel.Debug => "dbug",
LogLevel.Information => "info",
LogLevel.Warning => "warn",
LogLevel.Error => "fail",
LogLevel.Critical => "crit",
_ => throw new ArgumentOutOfRangeException(nameof(logLevel))
};
}

public bool IsEnabled(LogLevel logLevel)
{
return true;
}

public IDisposable BeginScope<TState>(TState state)
{
return _scopeProvider.Push(state);
}
}

Then you can change your function to the code below. If you are unable to inject it to ctor you can pass the logger as parameter to the function.

public class Function
{
private readonly ILogger logger;

public Function(ILogger logger)
{
this.logger = logger;
}

public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)
{
// Write with logger instead.
logger.LogInformation($"Hello there");

var body = new Dictionary<string, string>
{
{ "message", "hello world" }
};

return new APIGatewayProxyResponse
{
Body = JsonConvert.SerializeObject(body),
StatusCode = (int)HttpStatusCode.OK,
Headers = new Dictionary<string, string> { { "Content-Type", MediaTypeNames.Application.Json } }
};
}
}

And then change your test.

public class FunctionTest
{
private readonly ITestOutputHelper _testOutputHelper;

public FunctionTest(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}

[Fact]
public async Task TestHelloWorldFunctionHandler()
{
// .. other code

// Create your logger
ILogger logger = XUnitLogger.CreateLogger(_testOutputHelper);

// Inject logger.
var response = await new Function(logger).FunctionHandler(request, context);

_testOutputHelper.WriteLine("Lambda Response: \n" + response.Body);
_testOutputHelper.WriteLine("Expected Response: \n" + expectedResponse.Body);
_testOutputHelper.WriteLine("Header: \n" + response.Headers.Values.ToArray()[0]);

Assert.Equal(expectedResponse.Body, response.Body);
Assert.Equal(expectedResponse.Headers, response.Headers);
Assert.Equal(expectedResponse.StatusCode, response.StatusCode);
}
}

Python: Write unittest for console print

You can easily capture standard output by just temporarily redirecting sys.stdout to a StringIO object, as follows:

import StringIO
import sys

def foo(inStr):
print "hi"+inStr

def test_foo():
capturedOutput = StringIO.StringIO() # Create StringIO object
sys.stdout = capturedOutput # and redirect stdout.
foo('test') # Call unchanged function.
sys.stdout = sys.__stdout__ # Reset redirect.
print 'Captured', capturedOutput.getvalue() # Now works as before.

test_foo()

The output of this program is:

Captured hitest

showing that the redirection successfully captured the output and that you were able to restore the output stream to what it was before you began the capture.


Note that the code above in for Python 2.7, as the question indicates. Python 3 is slightly different:

import io
import sys

def foo(inStr):
print ("hi"+inStr)

def test_foo():
capturedOutput = io.StringIO() # Create StringIO object
sys.stdout = capturedOutput # and redirect stdout.
foo('test') # Call function.
sys.stdout = sys.__stdout__ # Reset redirect.
print ('Captured', capturedOutput.getvalue()) # Now works as before.

test_foo()

How to output in CLI during execution of PHP Unit tests?

UPDATE

Just realized another way to do this that works much better than the --verbose command line option:

class TestSomething extends PHPUnit_Framework_TestCase {
function testSomething() {
$myDebugVar = array(1, 2, 3);
fwrite(STDERR, print_r($myDebugVar, TRUE));
}
}

This lets you dump anything to your console at any time without all the unwanted output that comes along with the --verbose CLI option.


As other answers have noted, it's best to test output using the built-in methods like:

$this->expectOutputString('foo');

However, sometimes it's helpful to be naughty and see one-off/temporary debugging output from within your test cases. There is no need for the var_dump hack/workaround, though. This can easily be accomplished by setting the --verbose command line option when running your test suite. For example:

$ phpunit --verbose -c phpunit.xml

This will display output from inside your test methods when running in the CLI environment.

See: Writing Tests for PHPUnit - Testing Output.



Related Topics



Leave a reply



Submit