Hanalei, Hawaii 9/2/2010
438 Posts and Counting

Make BDD Your BFF

Monday, September 21, 2009 -

symmetry

I just can’t say enough about BDD (Behavio[u]r Driven Design) and how it’s helping me with an application I’m writing (which you’ll know all about soon enough). I’ve stopped myself from soooo many stupid errors it’s unbelievable – and since I’ve been writing so many opinion posts lately, I thought I’d do an end to end BDD post for the masses.

Step 1: Get the Bits You’ll Need

Download Aaron Jensen’s Machine.Specifications (MSpec) from here (click on Download) and put it on a drive on your machine. If you’re Git-savvy, then just clone the repo (git://github.com/machine/machine.specifications.git). This is (in my opinion) by far the best test-running framework out there.

Step 2: Download and install Test-driven .NET (TD.NET)

You don’t need to do this if you have ReSharper – but if you want to debug the tests (err – specs) that you write, you’ll need a way to invoke it. TD.NET is your best friend – got get it – it’s free for personal use.

Step 3: Make TD.NET and MSpec friends

When you download MSpec, Aaron and friends are good enough to create a BAT file that hooks TD.NET and MSpec up. You only need to run this once and what you’re doing is telling TD.NET “When I tell you to run a test for MSPec – do this”. ‘

If you open up the MSpec download folder there is another folder in there called “Distribution”, in there is one called “Specifications” and you’ll see the .bat file that you can double-click. For some reason I couldn’t get this to work right and TD.NET wouldn’t work with the MSPec stuff. If you’re in this boat with me – then create a .reg file and add this text, then execute it by double-clicking:

Windows Registry Editor Version 5.00 
[HKEY_CURRENT_USER\Software\MutantDesign\TestDriven.NET\TestRunners\MSpec] 
"Application"="" 
"AssemblyPath"="[DOWNLOAD PATH]\\machine.specifications\\Build\\Debug\\Machine.Specifications.TDNetRunner.dll" 
"TargetFrameworkAssemblyName"="Machine.Specifications" 
"TypeName"="Machine.Specifications.TDNetRunner.SpecificationRunner" 
@="5" 

 

Name the file whatever you want with a “.reg” extension – double click and you’re off.

Step 4: Hook MSpec up to Visual Studio

I don’t like running all the tests using TD.NET – it’s too slow. Instead I use the test runner Aaron and team have created as it’s screaming fast. To do this I like to use External Tools (Tools | External Tools) and I add the setting as you see below:

extools 

Note that the command box points to the ConsoleRunner in the Build\Debug folder. If you want an HTML report to be output to your project – you can do it (and I recommend it) by adding this as your arguments:

$(TargetName)$(TargetExt) --html "$(ProjectDir)\Report.html"

This will tell MSpec to output a file called “Report.html” that you can share with others. More on this below…

Step 5: Create a Class Lib Project and Add References

Easy enough – File | New Class Library, then add the following references:

  1. Machine.Specifications
  2. Machine.Specifications.NUnit
  3. nunit.framework

If you don’t have nunit – well go get it!

This might seem like a lot of steps – the truth is most of them are one-time setup steps that will be easier next time.

All set? Let’s write some SPECS!

Writing Specs (Tests) With MSpec

The first thing to remember when using MSpec is that you’re testing the behavior of whatever it is you’re working with – not necessarily the functionality. The goal of writing these weird looking things is to have them readable by your client - “Executable Specifications” if you will.

So, when you sit down to crank these things out, change your mind a bit and realize you are (literally) writing “specs” for others to read – not tests that you want to pass (that’s a developer thing). Unfortunately this means that you’ll also be writing some funky looking code – but it’s all worth it.

Example – Object Overrides

You’re building a blog for your client, and you’ve discussed URLs. They want their posts to be identifiable by a “pretty URL” and it should be based on a title. You think the typical Wordpress URL might work so you propose this:

  1. A post will have a “slug” which will be based on the title, minus any URL-prohibited characters
  2. The post URL will use the slug and the year, month, and day of the post to uniquely identify the post.

You now have some requirements and you can write your Post class. Being a good geek you decide to override the core .NET object methods so you can test your Post a bit easer:

public override bool Equals(object obj) {
    if (obj.GetType() == typeof(Post)) {
        Post compare = (Post)obj;
        return compare.Slug.Equals(this.Slug, StringComparison.InvariantCultureIgnoreCase);
    } else {
        return base.Equals(obj);
    }

}

public override string ToString() {
    return Title;
}

public override int GetHashCode() {
    return ID.GetHashCode();
}

 

All good –this should work nicely – or will it? We should probably have written the specs first (in BDD they’re “specs”, not tests) – but we haven’t even written one yet. Let’s come back to this.

Bending C# To Your BDD Will

C# wasn’t meant for this kind of gymnastics – but it’s what we got. If you ever use RSpec with Ruby you’ll know why this stuff was written this way (Ruby/RSpec are amazingly clean and simple to read) – but for now just know that I have some tricks for you – just hang tight.

The idea is that you want to use a thing called a “Context” which you will test the behavior of. In our case, we want to test our Post – but that Post will have certain settings on it so we know what we’re testing. This is our Context and in MSpec you write the Context as an abstract class which must be inherited:

    public abstract class with_null_post {
        protected static Post post;
        Establish context = () => {
            post = null;
        };

    }

Yes – freaky. Very freaky. But I can explain this…

First – this is a class – an abstract class which means you can’t instantiate it directly. It’s sort of like an Interface, but not.

Second – the name. It’s written that way to help the MSPec reporting bits output something groovy and awesome. It goes against every fiber of most people’s C# super powers – but just stick with it. It’s not such a big deal after a while and there’s also a reason it starts with “with_”. I’ll get to that.

Next – WTF is “= () =>”. I’ll tell you –but I’ll also tell you not to worry about it. It’s an Anonymous Delegate – basically a “method on the fly”. The syntax here is “Set the Establish delegate equal to this code I’m about to write”. Establish is used by MSpec when you run your tests – just accept it, it won’t hurt you.

Finally – we have our Post and it’s static. This is a concession Aaron and team had to make for the final result – and it’s damn worth it, as you’ll see.

In summary form what we have here is something that makes sense when spoken aloud:

“Establish with_null_post as a post=null”

Writing Your First Spec

You can’t write a Spec without a Context – and we have one of them now. At this point you’re saying “Big F***in Deal” and hopefully I’ll convince you that it actually is. When writing specifications they have to be founded on a “context” if you will – and if that doesn’t make sense, consider this statement:

“When a Post is created it should default the publication date to today and the status to draft”.

This is behavior – and it’s something we should spec out, and we can use our null Post to do it since that will be our Context (creating a Post from nothing).

Actually, if you slice and dice that sentence a bit you’ll see we have two bits of behavior – setting the publish date and the status – so we can use MSPec to define this (again, with crunchy syntax):

[Subject("New Post")]
public class when_creating: with_null_post {

    Because of = () => {
        post = new Post();
    };

    It should_default_published_date_to_now;
    It should_default_status_to_draft;
}

 

Yes – whacky syntax again – but I promise you will get used to it. It’s worth it, especially when you see the result…

First is the Subject attribute – this is purely for reporting and you can send in a type or a string – whatever makes your reports more readable.

Second – you’ll notice this is a class that inherits from the Context – this is intended to be readable (as it is here). If it doesn’t make sense – neither does your spec.

Because is another delegate and “of” is just magic – but it’s meant to be readable. What this code is saying is “because of this action on the Context” and in it’s curly bits you need to put the action that will be tested. In this case – it’s creating a new Post.

The following lines are just crazy. Again – they are delegates (“It” is another special test delegate) but they’re formed the way they are to be readable – as you’ll see in a second.

This is a spec – and it’s executable and when I run it using the MSpec runner I setup above, this is what i see:

Specs in MyProject.Specs:

New Post, when creating
¯ should default published date to now (NOT IMPLEMENTED)
¯ should default status to draft (NOT IMPLEMENTED)

And that’s the payoff. What this type of testing allows us to do is to define behaviors for our classes without writing a lick of code – and not worrying about compiler issues. In this case our spec is reporting a very accurate answer – we haven’t done anything yet…

Being good BDD coders we can go nuts with this – setting up specs to code against, and the filling out the tests as we go.

And that, friends, is BDD.

Getting Your First Spec to Pass

This next part is where we actually test. Let’s say you write the code for your post – setting up the default values in the constructor etc. Now you want to test that functionality to make sure your spec is valid:

    [Subject("New Post")]
    public class when_creating : with_null_post {

        Because of = () => {
            post = new Post();
        };
        It should_default_published_date_to_now = () => {
            post.PublishedAt.ShouldBeGreaterThan(DateTime.Now.AddSeconds(-1));
            post.PublishedAt.ShouldBeLessThan(DateTime.Now.AddSeconds(1));

        };
        It should_default_status_to_draft = () => {
            post.Status.ShouldEqual(PostStatus.Draft);
        };
    }

Notice here that we’ve filled out the “It” stuff to include some tests. These “tests” use a set of Extension Methods that come with MSpec to, again, make things more humanly readable. I think my date tests there could use some love, but if you read them I think you get the idea.

Now, when I execute these tests I see a nice result:

Specs in MyProject.Specs:

New Post, when creating
¯ should default published date to now
¯ should default status to draft

Contexts: 1, Specifications: 2

 

I can actually print that out and take it to my client or manager and we can read it together (along with the 50 or so NOT IMPLEMENTED specs) – and we’ll be right on the same page.

What’s that? Don’t like the weird text layout? That’s OK – here’s a snippet of the HTML output that I mentioned above, with all the specs I’ve written for my blog engine I’m making for myself:specs

 

This is being output in my project directory – but I could easily put it in a network share or somewhere else – it reads very well!

Why You Should Care

Remember where we started with all of this with the object overrides? Well I decided to write it first because hey – it’s just object overrides and I’ve written them before and I’ll test them anyway. Let’s consider the specs we’ll write:

[Subject("New Post")]
public class object_overrides : with_null_post {
    protected static Post post2;
    Because of = () => {
        post=new Post();
    };

    It should_have_title_as_main_identifier;
    It should_be_equal_to_other_post_with_same_slug;
    It should_have_same_hash_code_as_ID;
}

As I’ve been mentioning – the main goal of BDD is to get you to think about Behavior of the application, not just functionality. You might think that that’s great for the results – why the hell do I need to see it in my code?

The answer is right in front of you – are these specs correct? Let’s revisit the requirements:

  1. A post will have a “slug” which will be based on the title, minus any URL-prohibited characters
  2. The post URL will use the slug and the year, month, and day of the post to uniquely identify the post.

If I was writing Unit Tests I don’t think I would have ever caught the problem – but maybe that’s just me. Writing “specs” that my client can understand – well that threw the problem right in my face: the equality test was all kinds of wrong (no year, month, day). How do I know? Because it’s the way I wrote it – AFTER I wrote the code. Oops. Had I written the failing specs first, my client could have reviewed the specs and “accepted” them – then I would have been quite sure of what it was I was doing!

Let’s try that again – this time I’ll tweak it so my client knows what’s going on:

[Subject("New Post")]
public class identifiers_and_equality : with_null_post {
    protected static Post post2;
    Because of = () => {
        post=new Post();
    };

    It should_have_title_as_main_identifier;
    It should_be_equal_to_other_post_with_same_slug_year_month_day;
    It should_use_id_as_system_identifier;
}

 

Here’s what’s changed:

  1. I renamed the Concern to make a bit more sense to the client (“identifiers and equality”).
  2. I changed the second spec to include year, month, and day in the equality test
  3. I changed the last spec to get rid of “hash code” and used something my client could understand

The Payoff

This is the goal of BDD – to get you to think a bit more like your client, and to write tests that fit a bit more into what they see. This will help you to design and build your application in a much more client-specific way and ultimately save you LOADS of time. I can attest to this in all kinds of ways – taking my time and writing specs first is much, much faster.

Tips and Tricks

By far the biggest hurdle to BDD is the syntax. It took me a while to get it and rather than type all that unfamiliar syntax out, I decided to create some code snippets instead. You can download them here. To use them, download to your hard drive somewhere and open up your Code Snippets Manager (VS 2008 – Tools | Code Snippets Manager) and click the “Add” button. Select the snippets folder and then click OK.

To use them, type “context” and TAB – TAB and you’ll have your context. “spec” will create a spec template, and “spec0” will create one that’s not implemented.

If you want to see a screencast on BDD and MSpec, you can watch this one here that I did a few months back.

Related


Gravatar
DarkDeny - Monday, September 21, 2009 - Hello Rob.

Thanks for this great post. I have one question - why did you use NUnit, but not xUnit, which as you answered to my question ealier is much faster?
Gravatar
Cohen - Tuesday, September 22, 2009 - Great post, did you also look at nbehave?
When I compared both (2 years ago I have to add) nbehave had some advantages IMHO:
- you can keep true to the c# coding guidelines since te text comes from attributes and strings...
- you can create parameterized specs (it's a FIT meets nunit kinda like thing, but on a small scale)

Wouldn't it actually be great if your client could create executable specs/reqs so you could use them for BDD and perhaps even user acceptance testing?

Did you also look at storyteller?
Gravatar
Eyston - Tuesday, September 22, 2009 - Hey Rob,

If you ever write web acceptance tests take a look at cucumber. I'm testing an asp.net as if it were a black box (due to many reasons...) and I decided it was a good excuse to try out cucumber and other ruby tools. It's been helpful in understand how to apply BDD at different levels of testing.

For the web side you then have webrat with mechanize, celerity, and then selenium/watir. Webrat with mechanize is rather cool. Webrat has a simple API that is easy to use but also encourages writing more human meaningful tests (testing what the user sees). Mechanize acts like a real browser and lets you do assertions on the html output without having to drive a real browser -- its all headless and fast. But it doesn't do Javascript. Celerity (which I haven't used yet) does everything mechanize does but uses some java utils to actually run the javascript. So in theory you could do all of your web testing headless. Finally selenium/watir are the normal methods of driving a browser, but the syntax in Ruby is preferable to me.

I'm still toying with this stuff seeing what is useful, but it is a good excuse to learn Ruby at work.
Gravatar
junior programmer - Tuesday, September 22, 2009 - i was trying developwithpassion.bdd hosted on github but i haven't gotten my head around bdd just yet. it will take time. rob what were the reasons you chose mspec? there seems to be a few options (around 4 or 5) available for .net platform. now i need to read/try more about bdd to really shift my thinking from tdd.
Gravatar
Estuardo - Tuesday, September 22, 2009 - Excellent post... I like so much your blog and now I'm follower from you in twitter. Can you put your blog address in you Bio of twitter? Because is more easy find.

Thank you
Gravatar
Nick Berardi - Tuesday, September 22, 2009 - Wow thanks for the quick intro. I have had BDD on my list of things to look over, and now that I have looked through your post, this is definitely something I want to pay more attention to. Mostly because it has classes called "Because" and "It" :)
Gravatar
Aaron Jensen - Tuesday, September 22, 2009 - Great post Rob. I really appreciate it when people go out of their way to document the things I really should have at some point :) Thank you.

There's one thing in here that I've sort of changed my position on--the whole with_xxx base class idea. I'm not really a fan of this any more for a few reasons. For one, I (purposely) don't include the base class in the report. I prefer to describe the entire context in the actual context class. In your particular example your "with_null_post", that's not really the context. The context is a description of important elements leading up to the observations. Setting an instance variable to null temporarily is not an important element.

Forcing you to describe your context in a single class name forces you to be and think more concisely and only put the important elements in.

Also, the "composition" of base classes is complicated from a naming perspective. If you have a with_situation_a and with_situation_b, you can't have a when_doing_this and use those two base classes. It doesn't work unless you namespace things and that's just silly. A better alternative is when_doing_this_in_situation_a and when_doing_this_in_situation_b.

My current modus operandi is to have a base class named for the subject (NewPostSpecs) and have that method contain non-important setup and well named utility methods so that the actual context (method/implementation/code) can read better, be more concise and intention revealing.

Hopefully this makes sense, I'm happy to expand further if need be. Thanks again Rob.
Gravatar
bonder - Tuesday, September 22, 2009 - Hey Rob, great post as always. I think you had problems with the BAT file because on Vista or Windows 7 you need to run it as an Administrator. Worked for me when I did that. Cheers!
Gravatar
Chris Kolenko - Tuesday, September 22, 2009 - I remember watching your first BDD vid and i gave it a shoot. I basically gave up after 2 mins. Mainly because of the learning curve and the fact i was trying to introduce it into a 1/2 built application.

So why should i use this foreign looking syntax?

Is this just for the end client to see it working? because the people i do work for don't really care how the code works, they just want a product that works 100% and is done tomorrow basically.

Rob, when you first started writing these tests what made you think.. damn i should have been using this all along?

After reading your blog over the past year normally i get a light bulb popping into mind. This one is going to take a bit more convincing.
Gravatar
Argyle - Tuesday, September 22, 2009 - I wonder what Ayende will have to offer regarding this subject in his upcoming book Building DSL's With Boo. In the free unedited first chapter, he makes reference to RSpec, and it sounds like the book would be related to BDD. He says he likes Boo because it is CLI compliant, statically typed, and runs on the CLR (I guess that means no waiting for C# dynamic and DLR? I may wrong).

At my company we have non-technical account managers writing specs that I typically tear apart at both the technical and "what does the client really intend" levels (in a professional manner, of course ;)). If I ever get the opportunity to run my own show, BDD tools would be great asset.

Good post!
Gravatar
Jake Scott - Tuesday, September 22, 2009 - Hi Rob, thanks for the awesome post. I think that their will be alot of people waiting to look at the blog engine you are building to get a feel for how to write a suite of specs for an entire application. I guess that the more feedback you get from the likes of Aaron and team the better. It will be really useful for the rest of us who are sitting back and learning from your experiences. Excited about Hana :)
Gravatar
Liam McLennan - Tuesday, September 22, 2009 - I prefer spec unit (http://code.google.com/p/specunit-net/), mostly because the syntax is simpler.

Lots of people suggested cucumber and similar tools but I think they solve a different problem. Those tools only seem to work against systems that can maintain their state and are therefore more suited to functional testing. MSpec and the like leave state management to the developer making them better for fine grained BDD tests.
Gravatar
Craig Stuntz - Wednesday, September 23, 2009 - I'm not sure C# "isn't meant for [writing BDD]." But I'm pretty sure C# is a poor tool for writing Ruby code.
Gravatar
FutureTurnip - Wednesday, September 23, 2009 - Another great framework is FluentSpec (http://fluentspec.codeplex.com/)
Gravatar
Oz - Thursday, September 24, 2009 - Thanks for another awesome post! I was completely oblivious to BDD. I "got it" after reading the post and watching the Kona video twice. I'm very impressed with the simplicity yet tremendous value it delivers across the development process. It would also chop off hours of rummaging through stacks of documentation if business and systems analyst were able to produce a specs list like this for every use-case too! Anyway, thanks again Rob!!!
Gravatar
Tim Hardy - Thursday, September 24, 2009 - I'm heavily researching BDD and am having trouble figuring out where spec writing ends and unit testing begins. If anyone has any practical experience around this, I'd love to hear your thoughts. It seems to me that customer-focused specs will stop short of the unit tests required to fully cover a complex system. I'd like to know how the two meet and how this impacts the TDD "flow".

I'm basically asking Mike's question from above, "So my question then is: do you still write unit tests too? Or does BDD imply writing all tests as specs?"
Gravatar
Lance - Friday, September 25, 2009 - So when does it fail? I did a quick spike. Love how it reads and outputs but mine didn't fail when it should have. What gives

[Subject("Spike")]
public class when_does_it_fail
{
static bool _spike;

Establish context = () => { _spike = false; };

It should_still_be_false = () => _spike.Equals(true);
}

output
Spike, when does it fail
¯ should still be false
Gravatar
Apostolis Bekiaris - Saturday, September 26, 2009 - Thnks for the blog Rob. Anyone not convince yet read this blog with more resources on BDD http://apobekiaris.blogspot.com/2009/09/bdd-in-few-hours.html. Also users with x64 machines should change the reg path to HKEY_CURRENT_USER\Software\Wow6432Node\MutantDesign\TestDriven.NET\TestRunners\MSpec
Gravatar
Nick Swarr - Sunday, September 27, 2009 - Just to give MSpec another bump, I really appreciate that it removes a lot of the traditional unit testing noise. I like not having to mark up the fixtures with test attributes (barring the class-level attributes that help in reporting). I enjoy no longer specifying access modifiers like marking class-level members as private simply because it's just less text cluttering the fixture. It creates very clean, concise, modifiable, and understandable tests.

As far as the base class, I saw a couple of posts on the web using the "with_blah" nomenclature. That never quite felt right for me. I share the same sentiment as Aaron but I ended up appending the word "scenario" to them instead. So, using the above examples, I'd have called it new_post_scenario. I don't think it offers any more clarity than what Aaron suggests but it helps me think about the domain a little more organically. I want to think less about pounding out specs and more about modeling behaviors. On that note, perhaps I should be calling the base class new_post_behaviors...

Anyways, excellent write up and I thank you for getting the word out! I enjoy writing my applications using BDD, Context/Specification and MSpec. It's a winning combination.
Gravatar
phenryll - Sunday, September 27, 2009 - Thanks for the article and your 40-minute video.
You are writing your personal blog, aren't you?
I would love to read the code you have been writing with BDD, a real world project with BDD. It sounds like a book for professional developers :pp
Gravatar
Andrew Walker - Tuesday, September 29, 2009 - Great Video - I really appreciate it and as you said - it is a bit of an "A-ha" moment (Take on me... take me on..) I've been trying to get into the swing of TDD for a few months be hit mental blocks all the time!

One thing - I've been trying since last night to download MSpec - and each time - the download just dies! Tried FF & Chrome! Anyone got another link for it?
Gravatar
Eric Duncan - Tuesday, September 29, 2009 - One tweak to Rob's post, and one enhancement:

1) To get InstallTDNetRunner*.bat working, the batch files have to be copied to your Machine.Specifications bin location. If you downloaded the entire source, you will need to build the project first. The Build is located in \Build\Release from the mspec root directory.

Just copy those batch files into the \Build\Release\ directory and double-click to run it.

2) I am going to try MSpec in my next enterprise client, starting Monday! :) I've been tinkering with BDD for a bit now and feel ready to commit it on this next new, very large, project (I myself was introduced to BDD from Rob's initial video post, and tried for a while to 'get it').

In doing this, I am going to present the REPORTS html to my project and account managers. Rob's "Just post this on my door, and everyone knows where I am at" comment in the video a while back. ;)

I have a suggestion for all that want those automated REPORTS html files generated, without having to click an "MSpec" button or setup an external tool for it. You can create a POST BUILD event that generates the reports for you on every build of the TEST project(s). Yep, this runs all tests within the project. Right-click on your Project in the solution explorer, click Properties, and select Build Events tab. In the "Post-build event command line", enter this:

[YOUR-FULLPATH-TO-YOUR-MSPEC-DIR]\Machine.Specifications.ConsoleRunner.exe $(TargetPath) --html $(SolutionDir)$(TargetName).html

Now, just build your TEST project and you will have a new .html in your solutions root. I actually prefer to use a local "\lib\" directory in teh root of my solution. So, the path to my consolerunner is as follows:

$(SolutionDir)lib\mspec-github20090804\Machine.Specifications.ConsoleRunner.exe $(TargetPath) --html $(SolutionDir)$(TargetName).html

Note: I organize my \lib\ by projects and versions, hence the odd name of github's date of pull.

TIP: Seperate your Integration Tests into a seperate IntegrationTests project, so you can quickly run these automated reports from your main specs.
Gravatar
Eric Duncan - Tuesday, September 29, 2009 - Well, in that last comment, there should be "two" dashs before the HTML argument. The comment posting here filtered out the two dashs "-" and "-"html like Rob posted.

- - html
Gravatar
Mike Williams - Saturday, October 03, 2009 - Great article! I am having a problem though and was wondering if someone could help me. I installed TD.NET (the RTM version), downloaded mspec from GitHub and rebuilt the solution in Visual Studio and installed the latest nunit.

I'm getting the following error when running mspec in my test project:

System.IO.FileLoadException: Could not load file or assembly 'nunit.framework, Version=2.4.6.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'nunit.framework, Version=2.4.6.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77'
at Machine.Specifications.NUnitShouldExtensionMethods.ShouldBeFalse(Boolean condition)
at TestLibrary.Class1.when_does_it_fail.b__1() in C:\Users\Mike\Documents\Visual Studio 2008\Projects\TestLibrary\TestLibrary\Class1.cs:line 18
at Machine.Specifications.Model.Specification.InvokeSpecificationField() in C:\mspec\Source\Machine.Specifications\Model\Specification.cs:line 75
at Machine.Specifications.Model.Specification.Verify() in C:\mspec\Source\Machine.Specifications\Model\Specification.cs:line 53

Any ideas?
Gravatar
Rob Conery - Saturday, October 03, 2009 - Well yah - you need to reference NUnit!
Gravatar
Asif Raza Ashraf - Monday, October 05, 2009 - This is great. Thanks Rob.
Gravatar
Kyle Finley - Tuesday, October 13, 2009 - Rob & others,

I created a macro you might find handy. Build Solution + Run MSpec using the MSpec test runner.

http://kylefinley.net/archive/2009/10/05/1337.aspx

It's simple but helpful.