NSpec - A testing framework that's like Mocha and RSpec, but for C#


NSpec is a battle hardened testing framework for C# that's heavily inspired by Mocha and RSpec. It has a fancy logo, is released under the MIT License, and is an OSS project.

Table of Contents


Getting Started


Classic .NET Framework


Install-Package nspec
Install-Package FluentAssertions

PM> NSpecRunner.exe YourClassLibraryName\bin\debug\YourClassLibraryName.dll
my first spec
  asserts at the method level
  describe nesting
    asserts in a method
    more nesting
      also asserts in a lambda

.NET Core


Please see Targeting .NET Core section down below.

Why NSpec?


Consistent With Modern Testing Frameworks


If you’ve used any of the following testing frameworks, you’ll feel right at home with NSpec:

Noise Free Tests


In NSpec, there is no need for access modifiers on tests, and no need to decorate test methods with attributes.

For example, this NUnit/XUnit test:

Would be written like this in NSpec (notice that there are no access modifiers or attributes):

Fluid Test Structures


You can nest a lambda within a method (you can defer inheritance hierarchies):

Here is an NSpec test that has nested structures:

Here is what you’d have to write the test above in NUnit/XUnit. It’s gross and poopy. Specifically:

Features


Lets take a look at some features of NSpec.

Assertions


NSpec has some simple assertions, but you should really just use FluentAssertions, or Shouldly, or another assertion framework. You can build your own assertions by using extension methods. For example:

Before


Want to do some setup before tests are run? Use before. The state of the class is reset with each test case (side effects/mutations don’t spill over).

Context


Test hierarchies are communicated through the context keyword. If a method contains underscores, then it will be picked up by NSpec. Any method that starts with it_ or specify_ will be treated as just a simple NUnit/XUnit style test case.

Pending Tests


You can ignore tests by preceding any structure with an x. Or you can use the todo keyword provided by NSpec.

Helper Methods


Title cased (conventional C#) methods are ignored my NSpec.

Act


Here’s a fancy feature. Sometimes, what is done to a class remains the same, but the setup varies. You can use act. Each nested context will execute act before assertions are run.

Inheritance


Being able to nest tests is awesome. But you can always use inheritance to “flatten” tests if needed.

Class Level


All test structures are supported at the class level too. Here is how you’d write a before, act, and it/specify at the class level.

Debugger Support


If you want to hook into the debugger quickly, just place the following line inside of your tests. When you run NSpecRunner.exe, the debugger will pop right up:

System.Diagnostics.Debugger.Launch()

NSpec also includes DebuggerShim.cs when you install it via Nuget. So you can use TDD.NET/ReSharper to run your tests.

Console App


Or you can do something even fancier, and build your own console app! Instead of creating a Class Library for the test project, create a Console Application. Add the following code in Program.cs:

Then you can debug everything like you would any other program. More importantly, creating your own console app gives you the power to tailor input and output to your liking using NSpecs’s API/constructs.

Async/Await Support


Your NSpec tests can run asynchronous code too.

Class Level


At a class level, you still declare hook methods with same names, but they must be asynchronous and return async Task, instead of void:

For all sync test hooks at class level you can find its corresponding async one, just by turning its signature to async:

Sync Async
void before_all() async Task before_all()
void before_each() async Task before_each()
void act_each() async Task act_each()
void it_xyz() async Task it_xyz()
void specify_xyz() async Task specify_xyz()
void after_each() async Task after_each()
void after_all() async Task after_all()

Throughout the test class you can run both sync and async expectations as needed, so you can freely mix void it_xyz() and async Task it_abc().

Given a class context, for each test execution phase (before all/ before/ act/ after/ after all) you can choose to run either sync or async code according to your needs: so in the same class context you can mix e.g. void before_all() with async Task before_each(), void act_each() and async Task after_each().

What you can’t do is to assign both sync and async hooks for the same phase, in the same class context: so e.g. the following will not work and break your build at compile time (for the same rules of method overloading):

Context level


At a context and sub-context level, you need to set asynchronous test hooks provided by NSpec, instead of the synchronous ones:

For almost all sync test hooks and helpers you can find its corresponding async one:

Sync Async
beforeAll beforeAllAsync
before beforeAsync
beforeEach beforeEachAsync
act actAsync
it itAsync
xit xitAsync
expect expectAsync
todo todoAsync
after afterAsync
afterEach afterEachAsync
afterAll afterAllAsync
specify Not available
xspecify Not available
context Not needed, context remains sync
xcontext Not needed, context remains sync
describe Not needed, context remains sync
xdescribe Not needed, context remains sync

Throughout the whole test class you can run both sync and async expectations as needed, so you can freely mix it[] and itAsync[].

Given a single context, for each test execution phase (before all/ before/ act/ after/ after all) you can choose to run either sync or async code according to your needs: so in the same context you can mix e.g. beforeAll with beforeAsync, act and afterAsync.

What you can’t do is to assign both sync and async hooks for the same phase, in the same context: so e.g. the following will not work and throw an exception at runtime:

If you want to dig deeper for any level, whether class- or context-, you might directly have a look at how async support is tested in NSpec unit tests.

Just look for nspec-derived classes in following files:

Data-driven test cases


Test frameworks of the xUnit family have dedicated attributes in order to support data-driven test cases (so-called theories). NSpec, as a member of the xSpec family, does not make use of attributes and instead obtains the same result with a set of expectations automatically created through code. In detail, to set up a data-driven test case with NSpec you just:

  1. Build a set of data points.
  2. Name and assign an expectation for each data point by looping though the whole set.

Any NSpec test runner will be able to detect all the (aptly) named expectations and run them. Here you can see a sample test case, where we took advantage of NSpec.Each<> class and NSpec.Do() extension to work more easily with data point enumeration, and NSpec.With() extension to have an easier time composing text:

Additional info


Order of execution


Please have a look at this wiki page for an overview on which test hooks are executed when: execution order in xSpec family frameworks can get tricky when dealing with more complicated test configurations, like inherithing from an abstract test class or mixing before_each with before_all at different context levels.

Targeting .NET Core


Besides targeting classic .NET Framework, NSpec supports writing tests for projects targeting .NET Core too. That means you can also run tests from console with dotnet test Command Line Interface.

.NET Core Tooling Preview 2


The following setup holds for projects based on .xproj and project.json, currently working with .NET Core 1.0 and .NET Core Tooling Preview 2.

As of today this scenario is deemed to become obsolete, once .NET Core Tooling reaches RTM with projects based back again on .csproj and MSBuild.

To setup test project you can proceed from scratch, or take advantage of xUnit template and start modifying from there. Either way, the final result is to have a project.json as the following (also targeting net451):

{
  "version": "1.0.0-*",

  "testRunner": "nspec",

  "dependencies": {
    "dotnet-test-nspec": "0.1.1",
    "LibraryUnderTest": {
      "target": "project"
    },
    "NSpec": "2.0.1",
    "Shouldly": "2.8.2"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "portable-net45+win8"
      ],
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        }
      }
    },
    "net451": {
    }
  }
}

From scratch

From template

Whichever way you choose, project is now setup. From a command line located at test project directory, run dotnet restore. Add your test class, like the one shown at the top of this page, then from the same command line run:

> dotnet build
> dotnet test

Extensions


NSpec in NUnit


NSpec examples can be run as NUnit tests from inside Visual Studio (using for example the ReSharper test runner) or on a CI server using the NUnit console runner. To do this, install the NSpecInNUnit package and extend a special base class. Full usage instructions are at the project site for NSpecInNUnit.