Getting MSpec is pretty easy. Pull the source code from the github repo and build it. Once you have everything built you should just reference the dll in your C# project: Machine.Specifications.
I wanted to keep my solution as simple as possible so I kept both the TicketCalculator and its specs in the same .cs file.
The kata specifies the method names that you start with so I went ahead and created the class:
public class TicketCalculator {
  public void StartPurchase(int runtime, DayOfWeek day, bool isParquet, bool is3D) {}
  public void AddTicket(int age, bool isStudent) {}
  public decimal FinishPurchase() {return 0m;}
}
I put my first spec right below the TicketCalculator class:[Subject("Basic admission rates")]
public class Purchasing_general_ticket_as_an_adult_non_student{
  private static TicketCalculator _calculator;
  Establish setup_expectation = () => {
    _calculator = new TicketCalculator();
    _calculator.StartPurchase(115, DayOfWeek.Monday, true, false);};
  Because trigger = () =>
    _calculator.AddTicket(33, false);
  It verify = () =>
    _calculator.FinishPurchase().ShouldEqual(11m);
}
It compiled fine, however, when I executed the spec this is the error I got:TryMSpec (1 test), 1 test failed
Basic admission rates, Purchasing general ticket as an adult non student (1 test), 1 test failed
verify, Failed: Machine.Specifications.SpecificationException: Should equal [11] but is [0]
Since refactoring in the "red" is forbidden, I did the simplest thing that would make my test to pass: I returned 11 from the "FinishPurchase()" method.
I am looking at both the MSpec code and the output and they are ugly: it's really hard to read. To me a test is readable when I can show it to someone and can pretty much tell what's going on in there.
My spec passed so I started cleaning up my code. The first thing I did was introducing new aliases for the delegate names. Establish, Because and It felt awkward. I always think about Given-When-Then state transitions in my tests and this change just felt more natural to me.
using Given = Machine.Specifications.Establish;
using When = Machine.Specifications.Because;
using Then = Machine.Specifications.It;
[Subject("Basic admission rates")]
  public class Purchasing_general_ticket_as_an_adult_non_student{
    private static TicketCalculator _calculator;
    Given setup_expectation = () =>{
      _calculator = new TicketCalculator();
      _calculator.StartPurchase(115, DayOfWeek.Monday, true, false);};
    When trigger = () =>
      _calculator.AddTicket(33, false);
    Then verify = () =>
      _calculator.FinishPurchase().ShouldEqual(11m);
  }
This was a good start, but the code is far from readable. I tweaked the delegate names a little bit and I ended up with this:[Subject("Basic admission rates")]
  public class Purchasing_general_ticket_as_an_adult_non_student{
    private static TicketCalculator _calculator;
    Given i_buy_a_standard_movie_ticket = () =>{
      _calculator = new TicketCalculator();
      _calculator.StartPurchase(115, DayOfWeek.Monday, true, false);};
    When i_purchase_it_for_an_adult_non_student = () =>
      _calculator.AddTicket(33, false);
    Then i_pay_11_bucks = () =>
      _calculator.FinishPurchase().ShouldEqual(11m);
  }
Try to read this code! There is some noise around it, but you should be able to read it out:Given - I buy a standard movie ticket
When - I purchase it for an adult non-student
Then - I pay $11
I don't have much space on this page, but if you indent the lambda a little more the Given - When - Then words will become more apparent.
Let's look at the second scenario: a standard movie ticket for a student is $8.
Here is my spec for that:
[Subject("Basic admission rates")]
public class Purchasing_general_ticket_as_an_adult_student{
  private static TicketCalculator _calculator;
  Given i_buy_a_standard_movie_ticket = () => {
    _calculator = new TicketCalculator();
    _calculator.StartPurchase(115, DayOfWeek.Monday, true, false);};
  When i_purchase_it_for_an_adult_student = () =>
    _calculator.AddTicket(33, true);
  Then i_pay_8_bucks = () =>
    _calculator.FinishPurchase().ShouldEqual(8m);
}
When I executed the spec with MSpec I received the following error:TryMSpec (2 tests), 1 test failed
Basic admission rates, Purchasing general ticket as an adult non student (1 test), Success
i pay 11 bucks, Success
Basic admission rates, Purchasing general ticket as an adult student (1 test), 1 test failed
i pay 8 bucks, Failed: Machine.Specifications.SpecificationException: Should equal [8] but is [11]
Again, I did the simplest thing that could possibly work:
public class TicketCalculator{
  private decimal _ticket_price = 11m;
  public void StartPurchase(int runtime, DayOfWeek day, bool isParquet, bool is3D) {}
  public void AddTicket(int age, bool isStudent){
    if (isStudent)
      _ticket_price = 8m;
  }
  public decimal FinishPurchase(){ return _ticket_price; }
}
Everything passed:TryMSpec (2 tests), Success
Basic admission rates, Purchasing general ticket as an adult non student (1 test), Success
i pay 11 bucks, Success
Basic admission rates, Purchasing general ticket as an adult student (1 test), Success
i pay 8 bucks, Success
Notice we have duplication in our specs: the "Given" delegate is duplicated the exact same way in both of them. Time to DRY up the code a little bit. I created a base class called SpecBase and moved the field "_calculator" and the "Given" delegate into it.
public class SpecBase{
  protected static TicketCalculator _calculator;
  Given i_buy_a_standard_movie_ticket = () => {
    _calculator = new TicketCalculator();
    _calculator.StartPurchase(115, DayOfWeek.Monday, true, false);
  };
}
Both of the specs are now inheriting from this base class. The second one looks like this:[Subject("Basic admission rates")]
public class Purchasing_general_ticket_as_an_adult_student : SpecBase{
  When i_purchase_it_for_an_adult_student = () =>
    _calculator.AddTicket(33, true);
  Then i_pay_8_bucks = () =>
    _calculator.FinishPurchase().ShouldEqual(8m);
}
This way the spec is short and there is no duplication, however, I don't see the "Given" part in it. I took care of it by renaming the "SpecBase" class to "Given_i_buy_a_standard_ticket" and with the right indentation I should have a readable spec that tells a story.[Subject("Basic admission rates")]
public class Purchasing_general_ticket_as_an_adult_student : 
  Given_i_buy_a_standard_ticket{
  When i_purchase_it_for_an_adult_student = () => _calculator.AddTicket(33, true);
  Then i_pay_8_bucks = () => _calculator.FinishPurchase().ShouldEqual(8m);
}
You can find the final C# file in this gist: http://gist.github.com/576433.I'd like to list a couple of things that you should see - and maybe follow - based on this example:
- look at the length of the specs, none of them are more than 3 lines of code,
- there is no code duplication,
- there is only one assertion in each one of them,
- the spec tells you a story.
 
