Tuesday, May 20, 2014

Time to break with the past a.k.a. Fluent Assertions 3.0

Boy do I love the .NET community. Since I moved Fluent Assertions to Github, people have been creating 32 forks and provided me with 37 pull requests. In fact, release 3.0 has been made possible by the likes of Adam Voss (who provided a lot of those pull requests), Maarten Balliauw (for setting up a Team City environment) and Oren Novotny (for building and publishing the Xamarin version). However, that's not all. Other contributions were provided by Kevin Kuszyk, Kai Eichinger, Gregor Stamac, Sam Holder, Philipp Dolder and Mark Lambert. I can honestly say that this release would not have been possible without those people. Anyway, just in case the release notes are a bit to concise, let me highlight some of the bigger changes in 3.0.

Powered by

clip_image001[4] clip_image002[4]
clip_image003[4] clip_image004[4]

The biggest problem in terms of maintenance has been the work to support the different framework and device variants of the .NET Framework. Up until recently we had to use file links to get the same set of source files compiled into different projects. Because that has been so cumbersome, at some point I started to become reluctant in refactoring classes into new ones, just because that would mean fixing up those file links. Some of my Twitter followers tried to talk me into using Portable Class Libraries, but saying that that conversion was a challenge is an understatement, in particular the mechanisms to hook the framework-specific parts into the PCL.

Anyway, as of version 3.0, FluentAssertions consists out of a single PCL assembly post fixed with .Core and one platform-specific assembly. The only drawback of this is that you need to retarget your unit test project to .NET 4.0.3 (which is Update 3 that was released in March 2012). However, if you're working with Visual Studio 2013, you already have the 4.5 runtime installed and you just need to get the Targeting Pack for .NET 4.0.3 which Visual Studio will download automatically for you. For that same reason, we also dropped support for .NET 3.5. If you are so unfortunate to still have to develop in that version of the .NET framework, stick with 2.2. It's in maintenance mode, which means we'll still fix bugs if necessary.

Since we use Semantic Versioning, the bump to 3.0 clearly means it contains breaking changes. So we took that opportunity to remove some of the stuff that was marked as obsolete. Amongst them is the old API for asserting the structural equality of two object graphs ShouldHave().AllProperties().Equal() which was superseded by the ShouldBeEquivalentTo syntax and the ComparisonMode enumeration that was used during exception message assertions.

Reading back on the post, you must be thinking that 3.0 is just a step back. But it also contains some nice improvements as well as a few important bug fixes. One neat feature is the ability to chain a specific assertion on top of an assertion that acts on a collection or graph of objects. It's something we've been looking for for a long time, but it was Sam Holder that proposed this syntax.


someObject.Should().BeOfType<Exception>().Which.Message.Should().Be("Other Message");

xDocument.Should().HaveElement("child").Which.Should().BeOfType<XElement>().And.HaveAttribute("attr", "1");

I've run into quite a few of these scenarios in which this chaining would make the unit test a lot easier to read. But, as usual, don't overdo it.

Another little improvement is that you can now assert two XElement objects and their children for equality. Granted, it's a first implementation, but know that we're working on supporting a more advanced implementation that will ignore the order of attributes, whitespace and other typical non-relavant XML junk.

So what's planned for 3.1? Well, Oren (Novotny) already provided me with a pull request for supporting Windows Phone 8.1 (the Windows Runtime based). And as soon as Maarten completed support for Visual Studio 2013 Update 2 on the CodeBetter TeamCity server, I will move the XML-specific parts of the PCL library in a Shared Project. This should fix the current requirement to target .NET 4.0.3. So if you can't wait for the official release, add our MyGet feed as a NuGet Package Source and start testing against the latest commits.