The day is finally here: we shipped 2.0 RTM today.
If you don't want to read a bunch of release notes and just want to get started, this documentation is for you.
Our 2½ year journey included 20 alphas, 5 betas, and 4 release candidates:
First public alpha of 2.0
First public beta of 2.0
First release candidate of 2.0
The community drove this release as much as anything else, and that feedback—whether it came through using the product, reporting issues, or contributing code—was directly responsible for its success. There are a few people that we want to call out:
Unlike traditional release notes (which cover incremental builds from previous drops), these will cover the major design shift from v1 to v2, and some discussion about what motivated some of these changes. The first thing to make clear: we will continue to support 1.9.2 through our new 2.0 runners, so your upgrade path is incremental. We have no plans to release any fixes for 1.9.2 unless they are complete showstoppers, but given its age, we don't expect that to ever happen.
One of the reasons that this process took so long is that there is almost no code in the framework itself that remains from the v1 timeframe, other than some of the assertion library. From an internal implementation standpoint (and an extensibility standpoint), this is an entirely new product.
The #1 feature for xUnit.net v2 was to improve consumability. To us, that falls into several separate but related buckets of functionality:
More Platforms. xUnit.net 1.x only directly supported writing and running unit tests on the desktop CLR. For 2.0, we have added support for Portable Class Libraries, Universal Applications (those that target Windows Phone 8.1, Windows 8.1, and Windows 10), Modern Windows 8 Applications, Windows Phone 8 Silverlight Applications, MonoAndroid Applications, MonoTouch Applications, and iOS Unified Applications. In addition, in 2.1 we are shipping support for ASP.NET 5 projects running on Windows, Linux, and OS X.
Separated Assertions. A common theme among xUnit.net users
was that they wanted the ability to choose assertion libraries other than
ours. In 2.0, we have separated the core framework from the assertion
library, and we offer the asserts in either binary or source form. By
bringing in assertions as source, you can extend the
class itself with your own assertion methods.
No more installers. We moved to a NuGet based distribution model in 1.7, and with 2.0, we've finally cut ties with all other distribution mechanisms. Even support for running tests inside of Visual Studio is shipped as NuGet package!
More Visual Studio. We regularly test our code with Visual Studio 2012, 2013, and the CTP builds of 2015. (Earlier versions of Visual Studio are no longer supported, since the minimum .NET version required for unit test projects is .NET 4.5.)
Lots of Samples. Our samples project has samples ranging from simple assertion enhancement all the way up to writing your own replacement unit testing framework.
One of the very first things we did for 2.0 was to remove the
xunit.extensions project, and integrate the theory support
directly into xUnit.net core. It did help us to have this as an
extension when we were driving the v1 design, but we heard from many
(if not most) of our users that they were all using theories.
The rest of the code in
xunit.extensions was moved primarily
into sample projects. We may ship some of these samples as source-based
NuGet packages in the near future, based on developer demand.
For more information on migrating v1 tests that use
One of the premiere new features in xUnit.net 2.0 is support for parallelism. Back in the old v1 days, people would occasionally hack together MSBuild scripts to run multiple assemblies in parallel; this desire to get tests running faster drove us to make parallelism a part of the framework itself as well as the runners.
The first and most visible part of this decision is the new default behavior of xUnit.net to run your tests in parallel. Tests in the same test class will not be run in parallel against each other, but tests in different test classes will. We call the delineation of tests which can run in parallel against each other test collections. In order to prevent tests from running in parallel against each other, you put them in the same test collection. The default behavior in 2.0 (in the absence of any other configuration) is create a test collection for each test class.
This will undoubtedly be the most surprising change for users moving from xUnit.net v1 (or other test frameworks). We decided to make this the default behavior because we believe that unit tests should be small, self-contained, and fast. By running them in parallel, we can better utilize modern computers, which typcially have somewhere between 2 and 12 virtual CPUs sitting at the ready.
Of course, we provide a way to influence parallelism. For more information on how you can tweak these settings, please see Running Tests in Parallel.
One of the "victims" of the new parallelism system is that we've removed the
Timeout property from the
[Fact] attribute. In a
world where many things are running at once, and the system cannot reliably
determine how much time a given set of code has been running, we needed to
remove this feature. In addition, if you want test timings to be accurate,
you will need to turn off all parallelism; otherwise, the test timing numbers
will be unreliable.
Finally, while xUnit.net 1.x half-heartedly supported asynchronous tests,
this has been embraced fully by 2.0. This means many of the extensibility
points in the system are now async, and we have full support for async
code in the assertion library. You can even decorate your test methods with
async void instead of
async Task, and we'll still
be able to wait for your tests to finish. (Just to be clear: returning
Task still works just fine; the
async void feature
is something you can choose to use or not.)
We mentioned test collections in the section above on parallelism, but it's worth mentioning it separately as a feature, since it has more utility value than just setting parallelism boundaries.
IUseFixture<T> interface in xUnit.net v1.x has been
replaced by two new interfaces:
ICollectionFixture<T>. In addition, the mechanism for
injecting fixture values into your tests has changed from property setters
to constructor arguments. Class fixtures are created once and shared amongst
all tests in the same class (much like the old
Collection fixtures work the same way, except that the single instance is
shared amongst all tests in the same test collection.
For more information on using test collections, please see Shared Context between Tests.
In xUnit.net v1, we captured output written to standard output, standard error, the debug channel, and the trace channel, and we surfaced this output up to the test runners (which displayed them in a way that was appropriate to the test). In addition, the output was placed into the XML output, if you saved the result of your test runs.
With xUnit.net v2, we have stopped capturing these sources. The primary reason
is that these are shared resources, and it's impossible to know which of
the many unit tests running in parallel might be writing to the console
or the tracing system. Instead, tests can accept
as a constructor argument, and use that to provide output that is reported
up to the runners (and placed into the XML results). It can be used from
the constructor, from within the test, and from within
IDisposable.Dispose() (if it's defined).
For more information on using test output, please see the TestOutputExample sample project.
One of the more common reasons people chose xUnit.net 1.x was because it was extremely easy to extend. Those extensibility points offered some measure of control over the test framework, but we repeatedly heard from our users about use cases they weren't able to accomplish with our extension points.
The re-design of the internal engine of xUnit.net 2.0 was driven primarily around our desire to dramatically improve the extensibility of the core testing framework itself. We are aware that people write extensions for a large number of reasons ranging from simply adding new assertions and assert comparers all the way up to writing new test frameworks that can leverage the runner infrastructure provided by xUnit.net. We wanted to ensure that these users could not only do what they already did, but given them many more options for extending xUnit.net.
The Samples project on GitHub contains several levels of extensibility samples. Over the next few weeks and months, we will be writing documentation (on this site) to go along with these samples, to help developers understand how to best exploit the power of the new xUnit.net v2 engine.
xUnit.net got its start not just on CodePlex, but inside of it. Jim and Brad developed the early versions of xUnit.net while they were on the CodePlex team. Our decision to move from CodePlex wasn't easy, but our community was pushing us to make the switch. It was good for us, because we saw an immediate and dramatic uptick in community contribution.
The xUnit.net organization is home to almost all of the projects related to xUnit.net. They include:
With all these projects come a lot of NuGet packages. If you want to know what's in each package and where to start, please see What NuGet Packages Should I Use?.
You can visit our AppVeyor page to see our CI build status, and use our MyGet feed to try our our CI builds.
Seriously, thank you to everybody who uses this framework. Happy coding!
- Jim & Brad