January 25, 2012

Shipped: xUnit.net 1.9

On January 2nd, Jim and I shipped xUnit.net 1.9. We updated NuGet with the 1.9 build binaries, and for the first time, we're including the MSBuild runner inside the "xunit" NuGet package.

There are a few big new features that are worth calling out.

Async Unit Tests

Late in 2010, the C# team announced a new feature that was coming in C# 5: the "async" and "await" keywords. These keywords allow the developer to consume Task-based asynchronous APIs with code that looks linear and procedural, and mimics the code that the developer would write when calling synchronous APIs. In addition, .NET 4.5 is introducing new Task-based async APIs to supplement the existing event-based asynchronous APIs, and new async APIs will only offer Task-based versions.

Before now, unit testing these asynchronous APIs meant resorting to calls like .Wait() and .ContinueWith(), since unit testing frameworks are inherently synchronous by nature. With the release of 1.9, xUnit.net allows you to write asynchronous unit tests by marking your test method with the "async" keyword, and changing the return value from void to Task.

Prior to 1.9, a unit test around an asynchronous API might look something like this:

The code gets sufficiently more complex with every additional asynchronous API you add into the mix (for example, calling some async APIs during the setup phase of the unit tests). Adding try/catch logic becomes difficult and/or redundant, as the exception handling logic needs to be duplicated for both the setup code and the ContinueWith handler).

The same unit test can be simplified by using xUnit.net 1.9 (and either the Async CTP, or the pre-release version of .NET 4.5 which includes C# 5):

xUnit.net does the rest of the work. It sees that you're returning a Task and waits for it to complete. Traditional sequential coding mechanics like try/catch/finally and using are much easier to reason about when using async/await, and the compiler takes care of the boilerplate code necessary to ensure that it all works properly.

Generic Theories

One of the most used features in the xUnit.net Extensions project is support for theories. In quick review: Facts are for expressing tests which are invariants; Theories are used for expressing tests that are only necessarily true for a given set of input data. As such, theories are sometimes called "data-driven unit tests", because part of testing a theory is providing sets of conforming data.

The new Generic Theories feature allows the developer to write their theories using the .NET generic method syntax. xUnit.net will attempt to determine the best signature for the generic types of the method based on the provided data, and it makes this decision individually on a data-row by data-row basis. This is most useful for writing unit tests against generic APIs, wherein you want to choose the generic API to call based on the type of the input data.

For example, here is a unit test which is testing a generic get-and-cast behavior of a container:

This generic theory will be called 3 times as expected, and the type of T will be implied based on the value that was provided. We've also updated the output from theories to include any generic types that were used, so if this theory fails, its output method names would be: