First impressions of MSpec
Posted at 07:00 on 23 September 2011
For several years now, I’ve used Gallio and MbUnit for unit testing, but just the other day I was introduced to MSpec. I’ve been posting some of my initial thoughts about it on Twitter and I thought I’d better expand on them here. The idea is that you should be able to express your tests succinctly in a language that is supposedly closer to English than to C#.
Something like this:
[Subject(typeof(LogoController))] public class when_index_action_is_invoked { static LogoController controller; static ViewResult result; Establish context = () => { controller = new LogoController(); }; Because of = () => result = controller.Index(); It should_return_a_ViewResult_with_default_view_name = () => { result.ViewName.ShouldBeEmpty(); }; }
Whoa there. Just what’s going on here?
Whatever it’s doing, it completely subverts the C# language, gives the finger to Resharper and StyleCop, and throws out every best practice and coding convention in the book. Multiple classes per file. All lower-case names, with underscores. And for class and class property names, which should be nouns, you get verbs (Establish
), pronouns (It
) and prepositions (Because of
). It’s like waking up one morning and discovering that the word “the” is no longer the definite article, but now means Gatwick Airport.
When I see code like this, it reminds me of one thing in particular.
Why’s (Poignant) Guide to Ruby.
Now I’ve no idea where Joel Spolsky got the idea that Python is for Asperger’s geeks, but he was definitely onto something when he said that Ruby is for tear-streaked emo teenagers, because the Poignant Guide is the very manifesto for that particular stereotype. With the aid of talking cartoon foxes making inexplicable remarks about chunky bacon, _why devotes 176 pages to the thesis that if your code looks sufficiently like English, it automatically qualifies as a Mills and Boon novel.
I say this because MSpec was, in fact, heavily influenced by RSpec, a similar framework for Ruby, and I can’t help getting the impression that throwing out all the .NET conventions looks like an attempt to make C# look more like Ruby — in a kind of Ruby-that-tries-to-look-like-English way.
The principles behind MSpec seem sound enough. A typical unit test should have three phases to it: Arrange (set up your sample data and context), Act (carry out the action under test), and Assert (make sure that you get the correct results). MSpec represents these as the Establish
, Because of
, and It
clauses respectively. One advantage is that every assertion is treated as a separate test, so you can have multiple Asserts for a single context and action, and see their outcomes separately in your reports.
Is it any better than the conventional way of writing tests? One of the claims of MSpec is that it is designed to reduce noise in tests. I’m not sure that it does. In effect, each MSpec class performs the same work as a single test method in MbUnit, and in fact the framework is coercing a C# class to behave as if it were a function. This, along with lower case identifiers with underscores, and multiple classes per file, look like examples of dragging Ruby conventions kicking and screaming into the .NET world, and this inevitably introduces a lot of cognitive dissonance, which can be quite confusing until you’ve figured out what’s going on. It also makes me worry how many leaky abstractions are involved, and I doubt if it reduces the amount of code that you have to write overall.
Long lines are another thing that worry me — the MSpec best practices say that you should have only one line of code in your Because
and It
clauses, and as a result, some of the MSpec code I’ve encountered extends well past 80 columns. I hate long lines of code with a passion because having to scroll left and right all the time dramatically reduces readability and makes it much harder to diff your code in source control.
Of course, these are just my initial impressions. Perhaps in a few months’ time, you may find me in slim-fit jeans and a tight T-shirt, my eyes hidden behind long side-swept bangs, and tears streaming down my cheeks at the poignancy of MSpec. But as far as I can see at the moment, it’s a bit of an acquired taste.