Introducing NUnit.Specifications

I recently started working with a new team that uses NUnit as their testing framework.  While I think NUnit is a solid framework, I don’t think the default API and style lead to effective tests

As an advocate of Test-Driven Development, I’ve always appreciated how context/specification-style frameworks such as Machine.Specifications (MSpec) allow for the expression of executable specifications which model how a system is expected to be used rather than the typical unit-test style of testing which tends to obscure the overall purpose of the system. 

To facilitate a context/specification-style API, I created a base class which makes use of the hooks provided by the NUnit testing framework to emulate MSpec.  I’ve published this code under the project name NUnit.Specifications.

The following is an example NUnit test written using the ContextSpecification based class from NUnit.Specifications using the Should assertion library:

image01

One nice benefit of building on top of NUnit is the wide-spread tool support available.  Here is the test as seen through various test runners:

Resharper Test Runner:

image03

TestDriven.Net: (see notes below)

image04

NUnit Test Runner:

image00

NUnit Test Adaptor for Visual Studio:

image02

 

One caveat I discovered with the TestDriven.Net runner is it’s failure to recognize tests without the specification referencing types from the NUnit.Framework namespace (e.g. TestFixtureAttribute, CategoryAttribute, use of Assert, etc.).  That is to say, it didn’t seem to be enough that the spec inherited from a base type with NUnit attributes, but something in the derived class had to reference a type from the NUnit.Framework namespace for the test to be recognized.  Therefore, the TestDriven.Net results shown above were actually achieved by annotating the class with [Category(“component”)] explicitly.

 

Other Stuff

As a convenience, NUnit.Specifications also provides attributes for denoting categories of Unit, Component, Integration, Acceptance, and Subcutaneous as well as a Catch class (as provided by the MSpec library) for working with exceptions.

You can obtain the NUnit.Specifications from NuGet or grab the source from github.

About Derek Greer

Derek Greer is a consultant, aspiring software craftsman and agile enthusiast currently specializing in C# development on the .Net platform.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • shaynevanasperen

    Why? This seems very silly. Why reimplement MSpec with NUnit? Why not just use MSpec?

    • a couple of reasons I could see…

      1 less testing framework dependency, sometimes you want to just write normal NUnit unit tests

      1 less test runner to manage, just use NUnit’s test runner, especially on build servers

      I actually may adopt some of this as well in a project that primarily uses xUnit

    • derekgreer

      Don’t be so hard on yourself. I don’t think your questions aren’t silly at all! :)

      In all seriousness, one doesn’t always have the option to join a new team and impose their own personal framework preferences. In this case, the project I’ve joined is a very large platform whose development effort has been underway for over a year. The project is broken down into several sub-teams which are distributed geographically and the code base already contains a suite of tests written using NUnit. At this stage of the project, introducing the team to the context/specification style of testing using the tools they’ve already adopted is less friction than trying to introduce a new framework. Development methodology is more important than tooling.

  • if this doesn’t have the equivalent of Machine.Fakes for MSpec, it’s entirely worthless. xSpecification tests are only worth doing with an auto mocking container built in. There’s definitely a cost to writing these tests and without an auto mocking container to pick up the overhead, there’s only net-loss compared to regular ole unit tests.

  • derekgreer

    I appreciate the value you see in the use of auto-mocking containers, but I disagree that a testing framework is entirely worthless without their use and especially just because someone hasn’t written the tiny bit of code it takes to utilize an auto-mocking container. While I’m an advocate of the use of auto-mocking containers, they aren’t completely without a cost to the clarity of your tests/specifications. I invite you to read the article I wrote on this topic a few years ago here for a bit more on this topic.

    Concerning your opinion on which style is best suited for the task, one of the nice things about the context/specification approach to TDD is that it is equally applicable for all levels of automated testing (i.e. acceptance, subcutaneous, integration, component, unit). Your preference may be to use Cucumber style testing for acceptance testing and that’s perfectly fine, but many prefer to use context/specification across the board. I personally prefer to use context/specification for all levels of isolation tests because they lead to clearer tests and they provide consistency in the design experience.

  • FWIW, good tooling around NUnit is one reason I chose to build SpecsFor on top of NUnit. Everytyhing works with it, from test runners to build servers, no need for separate plug-ins.

    Oh, and it also has an auto-mocking container built in (and ExpectedObjects, too!) :D

    • derekgreer

      I hear ExpectedObjects is the bomb :)