… or how one could implement the It-Syntax introduced by MSpec. If you don’t know what the hell I’m talking about take a look at this code. (I don’t know if that’s the current MSpec syntax but I think you’ll get where I’d like to take you … )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
What you’ll see in this post is part of a spike I did some month ago while I was considering to move the xUnit.BDDExtensions syntax to something more GWT and MSpec like. I finally decided against that, partially because I realized that there is absolutely no need for a MSpec-Clone; partially because I’m still not so happy with the implications / side effects of the syntax (nearly everything in you spec needs to become static). Anyway, recently JP Boodhoo introduced the same feature to his jpboodhoo.bdd codebase. A lot of the comments requested a more detailed description of how he implemented that feature. While I can’t answer that question, I can talk about how I tackled that problem. So here we go!
Some prerequisites first
If you wonder how such a sweet syntax is possible in C#, here are some clues:
Ituses fields with ommited access modifiers (therefore private fields).
When, etc. are
- Field-initializers are used to specifiy the delegates inline. (and because field-initializers are run before the constructor you can only access static and no instance members here. Thats the sideeffect I mentioned earlier).
A closer look at my spike
The following class is the heart of the spike I implemented. It takes a blank object and uses reflection to
ISpecHandler instance which is ultimately used to run the specification.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
As you might guess a lot of extension methods are used in here, together with the composite pattern. Lets start be inspecting the
1 2 3 4 5
As its name implies this method reflects all the fields from the supplied object. It returns a collection of
IFieldInfo? Yes I introduced a little adapter here, which helped me to introduce better test isolation in the spike code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
And here is how the code that finds all the It delegates was implemented.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
The basic stuff happens in the
AllHandlersOf method which filters the supplied fields by the field type and also removes all compiler generated fields (which
CS$ in their names). The content (aka the delegate) of each field that is left is read and wrapped in a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Last but not least there is the
Then extension method which uses the composite pattern to wrap all found spec handlers into a single instance.
1 2 3 4
It’s not as hard to implement such a syntax in C# as one might initially think. Although the code shown in this post is only spike code and not considered production ready, you can derive all what’s necessary to implement such a syntax. Fields, omitted access modifiers, field-initializers and delegates are the basic parts together with some reflection logic to execute the code.