A small comparison of MSpec and MSTest

I really quite like MSpec.  I don’t, however, get to use this much on commercial projects.  The testing frameworks we use on projects is normally one of the MSTest / NUnit flavours.  The reason we don’t use MSpec is because people say it’s too complicated.  So, I thought I’d just compare them directly and hopefully people can see that MSpec isn’t complicated at all, but actually rather simple.

First thing to say is we do use the BDD naming style (if there is such a thing…).  There was even a debate at work whether this was a good thing, whether the naming style added any value…  Whether or not I’m doing BDD right or whether BDD is bad, I don’t really care.  It helps me write tests I understand later and that’s what I really want:  living, executable documentation.  So without further ado, which is nicer?  Let’s start with the code:

MSTest

[TestMethod]
[ExpectedException(typeof(Exception))]
public void When_invalid_throws_exception()
{
    isValid = false;
    Save();
}
 
[TestMethod]
public void When_valid_saves()
{
    isValid = true;
    var savedCustomer = Save();
    saveCustomerService.GetMock<ICustomerRepository>().Verify(r => r.Save(savedCustomer));
}

(I’ve been lazy and taken that from my previous mocking top tip, so if you want to see the full story have a look there).

MSpec

The same tests, expressed using MSpec:

public class Saving_customers
{
    protected static AutoMock<SaveCustomerService> SaveCustomerService;
 
    protected static Customer Customer;
 
    protected static bool IsValid;
 
    protected static Exception Exception;
 
    Establish context = () =>
        {
            SaveCustomerService = new AutoMock<SaveCustomerService>();
            SaveCustomerService.GetMock<IValidator>().Setup(v => v.Validate()).Returns(() => IsValid);
            Customer = new Customer();
        };
 
    Because of_saving_changes = () => Exception = Catch.Exception(() => SaveCustomerService.Object.Save(Customer));
}
 
[Subject("saving customers")]
public class When_invalid : Saving_customers
{
    Establish context = () => IsValid = false;
 
    It should_throw_exception = () => Exception.ShouldNotBeNull();
}
 
[Subject("saving customers")]
public class When_valid : Saving_customers
{
    Establish context = () => IsValid = true;
 
    It should_save_customer = () => SaveCustomerService.GetMock<ICustomerRepository>().Verify(r => r.Save(Customer));
}

 

Think of ‘Establish’ as your Arrange, ‘Because’ as the Act part of your test and ‘It’ as your Assert.  That’s not complicated.

Is the = () => a problem?  I don’t think so.  You use () => everyday (some people lovingly call this the penis operator, personally I can’t see the resemblance, mine doesn’t look that happy), you don’t often assign one to a variable like we’re doing here, but that’s all we’re doing.  It’s not complicated to assign a variable.  Yes, it would look a bit nicer if they weren’t there, and using other languages you may be able to make it look a lot nicer.  But we’re in c# so = () => will have to do. 

It’s ‘magic’.  Any less magic than putting a [TestMethod] on it?  It runs the Establish functions first, then the Because functions then the It functions.  Just like running [TestInitialise] and [TestMethod] methods.  So not really any more magic here.

If anything, there’s less syntax getting in the way.  The assert reads ‘it should save customer’.  Also, the post condition isn’t at the end of the test method far away from the code which asserts it.  Here they are right next to each other.

I’m going to get lots of class files!  No, put all related classes in the same file.  It’s no different to one class with lots of methods really is it?

Also, consider when you’ve got multiple post conditions, let’s say the acceptance criteria is, ‘when saving a customer, the customer must be saved and also an audit record must be inserted detailing who saved the customer’.  You’d need two methods public void When_valid_saves() and public void When_valid_audits()…  Each of those methods would have the arrange and act inside it.  You could stick two asserts in a method called When_valid_saves_ands_audits, but the test output isn’t so nice.  And the test has two reasons to fail so makes it more difficult to maintain.  Also, that doesn’t scale, if there’s a few more, you’ll have a test name which is huge.  So it’s less code and much clearer.

There is no test runner.  There is, resharper test runner (with the plug in which comes with MSpec).  And it gives you a much nicer output.  Here, have a look:

MSTest

resharper MS Test output

MSpec

resharper MSTest runner

In the build output you can include the MSpec report, which is a nice human readable representation of the tests.  I guess that’s an added bonus!

mspec –html .\report.html Specifications.dll

saving customers specifications

2 contexts, 2 specifications
When invalid
1 specification
When valid
1 specification

It can also do a lot more than I’m showing here, things like behaves like is a really nice concept…  It can help with domain driven design helping shape a ubiquitous language (I remember Howard van Roojen spoke about this at a scrum user group)…

So in summary…  It’s not complicated, it’s easy to read and easy to maintain and it actually can give you some level of documentation (that is in sync with the code).  If you’re using a BDD naming style, why not try it?

Advertisements

About Tom Peplow

C# .Net developer based in London and the South Coast
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s