Inspired by Rob Conery's recent video on Behavior-Driven-Design, I decided to do a quick 'spike' to try out the concepts. I like MSpec, but still find the syntax a little scary. It definitely makes sense more after Rob's video, but I'd like to see something even more approachable and discoverable. I got to thinking - what if this approach has it backwards? MSpec, etc. generate readable specs from tests, but maybe a better approach would be to generate tests from readable specs? You could then generate even more readable specs if you needed.
Continuing with Rob's examples, I wrote the spec out first, to a file called Accounts.spec:
Now, what is the best way to go from this to some useful code? T4 code-gen of course! After brushing up on my T4, I came up with this, which I saved as a .tt file:
This code works by looping through every .spec file in the current directory and generating an NUnit partial class with partial methods for each condition in the specification. This T4 could have just of easily generated MSpec or any other type of testing code. In fact, I'm pretty sure it could generate better NUnit code. As it stands now, though, this is what it generates for the above spec:
The idea is that the tester has only to 'fill in the blanks' to build the test:
As with any test, ReSharper lets you right click-and-run the specification and outputs a fairly readable approximation with pass-fail for each bullet point.
I'm not ready to push this 'Spike' into production process, but I think it's interesting enough to blog about. I think with a little tweaking of the code gen, this could be pretty useful stuff. I'm not stuck on the testing framework, but ideally, I'd like to stick with a very simple, 'traditional' class where the test writers 'fill in the blanks'. I'd like it to have intellisense to help discover the methods to implement or override, and ideally throw a 'Not Implemented Exception' for any feature not yet implemented. And finally, I want the nice HTML report MSpec generates. So, we'll see where this develops. Let me know if you have any suggestions or questions on the code!