Aaron Jensen

Sponsors

The Lounge

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Introducing Machine.Specifications (or MSpec for short)

As some of you who follow me on twitter know, I've been working on Yet Another Context/Specification Framework as an experiment. Yeah, I know we already have NSpec and NBehave, and they're great and all, but MSpec takes things on from a slightly different angle, and it's just an experiment (for now). Here's a sample Description:

[Description]
public class Transferring_between_from_account_and_to_account
{
  static Account fromAccount;
  static Account toAccount;

  Context before_each =()=>
  {
    fromAccount = new Account {Balance = 1m};
    toAccount = new Account {Balance = 1m};
  };
  
  When the_transfer_is_made =()=>
  {
    fromAccount.Transfer(1m, toAccount);
  };
   
  It should_debit_the_from_account_by_the_amount_transferred =()=>
  {
    fromAccount.Balance.ShouldEqual(0m);
  };

  It should_credit_the_to_account_by_the_amount_transferred =()=>
  {
    toAccount.Balance.ShouldEqual(2m);
  };
}

And a TestDriven.NET run:

------ Test started: Assembly: Machine.Specifications.Example.dll ------

Transferring between from account and to account
  When the transfer is made
    * It should debit the from account by the amount transferred
    * It should credit the to account by the amount transferred


2 passed, 0 failed, 0 skipped, took 0.79 seconds.

Err, What?

Different eh? The idea was heavily inspired by Scott Bellware's SpecUnit.Net framework he showed at the ALT.NET conference. It also took heavy cues from RSpec and my insanity. I realize that the the code doesn't look much like C# code and I'm OK with that. Many have and will ask why I don't just use Boo or RSpec w/ IronRuby eventually or even one of the existing Context/Spec/BDD frameworks. Those are good questions, but my main motivations are tooling and syntax. I enjoy the tooling I get in C# and I personally like the syntax in this library considering the limitations imposed by C#.

How's it work?

The simplest way to describe it is to compare it to a normal *Unit style testing framework:

  • Description = TestContext
  • Context before_each = SetUp
  • Context before_all = SetUpFixture
  • Context after_each = TearDown
  • Context after_all = TearDownFixture
  • When = Also SetUp, but happens after Context before_each
  • It = Test

Rather than methods and attributes, MSpec uses named delegates and anonymous functions. The only reason for this is readability. You'll also notice that the fields used in the context are static. This is necessary so that the anonymous functions in the field initializers can access them. Probably the first thing you noticed is the =()=> construct. I won't mention the names that this was given on twitter, but I think it's an acceptable thing to have to deal with in exchange for the cleanliness of the rest of the syntax.

Ok, you're crazy, but how do I try it?

First, this is a very rough cut. Everything is subject to change as we experiment with the language. That said, here's how you play with it:

  1. Grab the drop here.
  2. Extract it somewhere. Put it somewhere semi-permanent because the TestDriven.NET runner will need a static location for the MSpec TDNet Runner.
  3. If you want TestDriven.NET support, run InstallTDNetRunner.bat
  4. Check out the example in Machine.Specifications.Example. Note that you can run with TD.NET.
  5. Create a project of your own. Just add Machine.Specifications.dll and get started.
  6. Send me feedback! Leave comments, email me, tweet me, whatever.

Also, this is part of Machine, so feel free to take a look at the code and/or submit patches. There's also a Gallio adapter in there, but I didn't include it in the release as it's not quite polished enough yet. If you're interested in it, talk to me. Special thanks to Scott Bellware, Jeff Brown and Jamie Cansdale for their help and support.


Posted 05-08-2008 12:12 AM by aaronjensen
Filed under: , ,

[Advertisement]

Comments

Colin Jack wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-08-2008 5:33 AM

I'm not normally one that gets excited by new syntactic sugar but I saw the example you put on twitter and immediately liked it. Very cool.

Best thing was I looked at it and thought "It", what’s that about? I was expecting it to be some mad work around but when I downloaded the Machine codebase I found it was really elegant and understandable. Made me feel dumb (in a good way).

Anyway to me the "=()=>" is not a major issue, it’s at the end of the line and easily ignored. The static field thing threw me a little but I guess with the BDD style of small focussed fixtures it won't be an issue.

Only thing that I'm still unsure of is whether just having [Description] is that useful, would I not also want to use something like this group my specifications (especially given that with the context/specification approach I might end up with lots of fixtures for one higher level behavior such as funds transfer). Guess it depends on how you use these specifications but finding ways to group them seems to be important.

My first impression is also that you are not necessarily covering exactly the same area as NBehave, my feeling it is xBehave is _supposed_ to be most suitable for higher level story tests where as to me the xSpec approach is more generally applicable.

Ray Houston wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-08-2008 8:59 AM

Nice work man!

Dew Drop - May 8, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop - May 8, 2008 | Alvin Ashcraft's Morning Dew
on 05-08-2008 9:18 AM

Pingback from  Dew Drop - May 8, 2008 | Alvin Ashcraft's Morning Dew

Jeff Brown wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-08-2008 10:23 AM

Neat!

The =()=> notation with fields is a clever way to work around the fact that we can't otherwise define new "shapes" for methods.

hmmm...  I can see interesting things coming out of this...

Sergio Pereira wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-08-2008 1:18 PM

This is brilliant, Aaron.

Rodrigo B. de Oliveira wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-08-2008 8:46 PM

That's pretty cool.

jamesthigpen wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-09-2008 10:38 AM

This is very awesome. However...

While I understand your choice for doing it in C#, I feel that by not using a language that would allow for a more fluent DSL syntax, you have created something that will hamper it's adoption.

The way you are using C# goes against the grain of how users are taught to use C#. static fields and what look like fancy function but end in semicolons. If I brought this to my team it'd be very confusing for them because it *is* C# but it's not the C# they're use to.

That could be just dumped into the "learning curve" bucket, but I see it being a recurring problem with the context switching required between MSpec and C# when bouncing between tests and code.

It could be argued that the context switching between MPsech C# and "regular" C# when bouncing back and forth between tests and code is no more grating than if it were a completely separate DSL, but I feel that all the syntactic sugar required to make this work prevents me from forgetting that it is C#. There is a certain amount of muscle memory in "private Account fromAccount;"

aaronjensen wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-13-2008 10:27 AM

James,

I hear you. It's definitely a stretch of C#. The benefits of using C# are clear though. The tool and the framework support make it worth it in my opinion. Like I said in the post though, this is an experiment. I've got no ego behind this and I'm not pushing for widespread adoption. I'm just kind of dropping it on the community and seeing if it sticks at all :)

Matthew Podwysocki wrote The Unit Testing Story in F# Revisited
on 05-29-2008 2:39 AM

Last week I posted about some troubles I was having with the unit testing frameworks for F#. Today, Brad

Matthew Podwysocki's Blog wrote The Unit Testing Story in F# Revisited
on 05-29-2008 2:43 AM

Last week I posted about some troubles I was having with the unit testing frameworks for F#. Today, Brad

Community Blogs wrote The Unit Testing Story in F# Revisited
on 05-29-2008 3:22 AM

Last week I posted about some troubles I was having with the unit testing frameworks for F#. Today, Brad

The Unit Testing Story in F# Revisited | Developer Home wrote The Unit Testing Story in F# Revisited | Developer Home
on 05-30-2008 4:55 AM

Pingback from  The Unit Testing Story in F# Revisited | Developer Home

Michael wrote re: Introducing Machine.Specifications (or MSpec for short)
on 06-26-2008 10:48 AM

Hi Aaron,

You might have already mentioned that somewhere but I can't seem to find it.. How do you manage to have a pretty print output after you run your test in TestDriven.NET. ?

Thanks,

Take care

Aaron Jensen wrote re: Introducing Machine.Specifications (or MSpec for short)
on 07-08-2008 12:00 PM

Michael,

TD.NET allows you to print whatever you like when implementing a custom runner. I just used that.

It's not super flexible (errors always print the same, along w/ the stack trace) so I save the errors until the end in TD.NET.

Aaron Jensen wrote MSpec v0.2
on 09-02-2008 9:52 PM

It's been a while, but we've gotten several new things into Machine.Specifications (MSpec). I'm

Mirrored Blogs wrote MSpec v0.2
on 09-05-2008 12:41 AM

It's been a while, but we've gotten several new things into Machine.Specifications (MSpec). I'm

MSpec v0.2 - taccato! trend tracker, cool hunting, new business ideas wrote MSpec v0.2 - taccato! trend tracker, cool hunting, new business ideas
on 09-05-2008 8:28 AM

Pingback from  MSpec v0.2 - taccato! trend tracker, cool hunting, new business ideas

Community Blogs wrote MSpec v0.2
on 09-05-2008 12:01 PM

It's been a while, but we've gotten several new things into Machine.Specifications (MSpec). I'm

MSpec v0.2 - taccato! trend tracker, cool hunting, new business ideas wrote MSpec v0.2 - taccato! trend tracker, cool hunting, new business ideas
on 09-06-2008 12:27 PM

Pingback from  MSpec v0.2 - taccato! trend tracker, cool hunting, new business ideas

Chad Myers' Blog wrote ALT.NET Workshops: Internal DSL Draft Outline, Notes
on 10-26-2008 3:34 PM

I’ve been preparing for the upcoming ALT.NET Workshop (associated with KaizenConf ) on Internal Domain

Colin Jack's Blog wrote Context/Specification - Available Frameworks (BDD)
on 11-19-2008 4:16 PM

I've been using the context/specification style of BDD for a while now but so far I've just done

Joakim Sund??n » Blog Archive » ??redev 2008 wrote Joakim Sund??n » Blog Archive » ??redev 2008
on 12-02-2008 3:46 PM

Pingback from  Joakim Sund??n  » Blog Archive   » ??redev 2008

Test Styles - Standard vs. MSpec « Justin Rudd’s Drivel wrote Test Styles - Standard vs. MSpec « Justin Rudd’s Drivel
on 12-12-2008 8:35 PM

Pingback from  Test Styles - Standard vs. MSpec « Justin Rudd’s Drivel

Colin Jack's Blog wrote BDD - Available Frameworks
on 12-28-2008 5:08 PM

I've been using the Astels style of BDD for a while now but so far I've just done it using MSTest

Colin Jack's Blog wrote BDD - Available Frameworks
on 12-28-2008 5:10 PM

I've been using the Astels style of BDD for a while now but so far I've just done it using MSTest

Scott Densmore's Blog wrote My First Journey into BDD
on 02-15-2009 6:22 PM

Lately I have been trying to teach people TDD and running into the usual suspects of misconceptions.

NUnit: Tests with Context/Spec style assertions at Mark Needham wrote NUnit: Tests with Context/Spec style assertions at Mark Needham
on 03-01-2009 1:46 AM

Pingback from  NUnit: Tests with Context/Spec style assertions at Mark Needham

Eduardo Menoncello wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-16-2009 9:02 PM

Hi Aaron, I am testing the machine specification, but I have a problem... when I run my tests, the tests break like that:

TestCase 'N:Machine.Specifications.Example'

failed: Method not found: 'System.Collections.Generic.IEnumerable`1<Machine.Specifications.Model.Description> Machine.Specifications.Explorers.AssemblyExplorer.FindDescriptionsIn(System.Reflection.Assembly, System.String)'.

thanks for the help

aaronjensen wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-18-2009 12:25 PM

Hi Eduardo,

This looks like a versioning issue. I'm guessing you have some old mspec assemblies laying around somewhere (perhaps the td.net runner if this is from td.net). I'd rebuild mspec and reregister the td.net runner from the built location.

Paul Linton wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-28-2009 4:07 AM

Rob Conery opened my eyes to MSpec and I'm loving it.  I have followed all his suggestions and created a toolbar button and html reports.  

How do I debug a failing specification?  Setting a breakpoint on the failing line within the Because delegate doesn't work.

What am I missing?

aaronjensen wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-28-2009 9:32 PM

Paul, Thanks! Are you running TD.NET? If so you can just run with debugger. If not, I'd recommend it :) R#'s runner can run with debugger as well. If you're just running the console runner you'll have a harder time debugging, but you could always use Debugger.Break() and attach.

Paul Linton wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-30-2009 1:55 AM

<sheepish>What's TD.NET?  www.td.net is not very interesting nor is www.tdnet.com and nothing on the first page of a google search for "td.net" sheds any light</sheepish>

aaronjensen wrote re: Introducing Machine.Specifications (or MSpec for short)
on 05-30-2009 2:38 PM

Paul, TestDriven.NET

Add a Comment

(required)  
(optional)
(required)  
Remember Me?