.NET Core

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:

RSpec

Minitest

Jasmine

Mocha

FunSpec

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:

Attributes on every class.

Attributes for setup methods and test methods.

Access modifiers on every class and method.

Setup method names have to be unique to ensure there are no
collisions in the inheritance hierarchy.

Inheritance hierarchy isn’t visually obvious.

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.

Exceptions

When your code should throw under specific conditions, you can assert that it does so with an expected Exception of known type and message.

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.

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:

Build a set of data points.

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.

Expect and assert

Currently with NSpec out-of-the-box you can only expect that some code
under test throws, but you cannot at the same time perform any further
assertion, e.g. that some flag has been set or resource disposed in a
finally block.

One workaround to this scenario is to add a custom helper like the
following to your test class:

classdescribe_expect_and_assert:nspec{voidExpectAndAssert<TEx>(stringtestName,ActionactionThatThrows,Action<TEx>assertAfter)whereTEx:Exception{it[testName]=()=>{boolexceptionThrown=false;try{actionThatThrows();}catch(TExex){exceptionThrown=true;assertAfter(ex);}if(!exceptionThrown)thrownewInvalidOperationException("Exception was not thrown when expected");};}// ...}

and then use it to both expect some specific Exception type to be thrown,
as well as asserting some further expectation:

classdescribe_expect_and_assert:nspec{// before_each ...voida_context(){// add a specificationExpectAndAssert<KnownException>("throws an exception",()=>someObject.DoSomething(),ex=>someObject.Flag.should_be(true));// add another specificationExpectAndAssert<OtherKnownException>("throws another exception",()=>someObject.DoSomethingElse(),ex=>someObject.OtherFlag.should_be(true));}}

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):

From custom NSpec template

Create a new NSpec test project from command line by running
dotnet new nspectest -n MyTestProject

Add a reference to main project under test

Add a reference to your favourite assertion library package

NOTE: Even if template currently creates a project supporting .NET Core Tools Preview 2 (the one based on project.json),
in order to install custom CLI templates like this you need to have at least .NET Core Tools RC4 on your development machine.

From built-in XUnit template

Create a new xUnit test project from command line by running
dotnet new -t xunittest (when you have .NET Core Tools Preview 2)
or dotnet new xunit -n MyTestProject (when you have .NET Core Tools RC4)

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

or, from within Visual Studio 2015, build solution then open Test Explorer
window in order to list and run tests.

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.

NSpec Visual Studio Adapter

NSpec.VsAdapter is a test adapter to run NSpec tests from Test Explorer in
Visual Studio. It runs tests in VS 2013, 2015 and 2017 from projects
targeting classic .NET Framework.