Fork me on GitHub

Getting Started

Write Your First Spec

This tutorial will walk you through installing NSpec and running a simple spec.

  1. Open Visual Studio.
  2. Ensure that you have NuGet installed. (NuGet only works with VS2010+. To use NSpec with VS2008, you must download the binaries zip.)
  3. Create a .Net 4.0 or .Net 3.5 class library project.
  4. Open the Package Manager Console and type the following command:

    PM> Install-Package nspec

  5. After installation completes, create a class with the following code:
using NSpec;

class my_first_spec : nspec
{
    void before_each() { name = "NSpec"; }

    void it_works()
    {
        name.should_be("NSpec");
    }

    void describe_nesting()
    {
        before = () => name += " BDD";

        it["works here"] = () => name.should_be("NSpec BDD");

        it["and here"] = () => name.should_be("NSpec BDD");
    }
    string name;
}
    

Run Your First Spec

Nuget placed NSpecRunner.exe in your PATH on the Package Manager Console.

  1. Build the class library.
  2. Run the following command in the Package Manager Console:
 NSpecRunner.exe YourClassLibraryName\bin\debug\YourClassLibraryName.dll
my first spec
  it works
  describe nesting
    works here
    and here

4 Examples, 0 Failed, 0 Pending
    

Debugger Support

DebuggerShim.cs is a class file included with NSpec, you can use that to debug a test using TestDriven.net or Resharper's test runner (we're working on fully integrated support).

Definitely try specwatchr. Specwatchr will automatically run impacted tests for you when you save a file. If you ever need to debug a test simply use this line of code in your test:

    [...]

    System.Diagnostics.Debugger.Launch();

    [...]
    

Mono Support

Mono binaries and samples are available here. Simply clone/download this repository.

Why NSpec? What NSpec Brings to the Table.

Consistent with other BDD testing frameworks

If you've used any of the following testing frameworks, you'll feel right at home with NSpec:
  • RSpec
  • Minitest
  • Jasmine
  • Mocha

Less Ceremony (save your keystrokes)

  • No need for access modifiers on tests.
  • NSpec test can live side by side with test from other testing frameworks (in the same project).
  • No need to attribute test.
  • Easy transition from xUnit, NUnit, and MSTest frameworks.

NUnit, XUnit, MSTest force you to place attributes and public access modifiers in your test suites:

[TestFixture]
public class describe_NUnit
{
    [Test]
    public void it_just_works()
    {
        Assert.AreEqual("hello", "hello"); //this is an arbitrary assertion
    }
}
    

NSpec uses underscore conventions, making your tests cleaner:

class describe_NSpec : nspec
{
    void it_just_works()
    {
        "hello".should_be("hello"); //this is an arbitrary assertion
    }
}
    

Fluid Test Structures

  • Elaborating a context can be done at the method level.
  • Reduce the ceremony of inheritance when it isn't needed.

NUnit, XUnit, MSTest force inheritance if you want to build on a context:

[TestFixture]
public class describe_NUnit
{
    [SetUp]
    public void before_each()
    {
        Console.WriteLine("I run before each test.");
    }

    [Test]
    public void it_works_here()
    {
        Assert.AreEqual("hello", "hello");
    }
}

[TestFixture]
public class category_of_examples : describe_NUnit
{
    [SetUp]
    public void before_each_for_this_context()
    {
        Console.WriteLine("I run before each test defined in this context.");
    }

    [Test]
    public void it_also_works_here()
    {
        Assert.AreEqual("hello", "hello");
    }

    [Test]
    public void it_works_here_too()
    {
        Assert.AreEqual("hello", "hello");
    }
}
    

NSpec can do that too (with less code):

class describe_NSpec : nspec
{
    void before_each()
    {
        Console.WriteLine("I run before each test.");
    }

    void it_works_here()
    {
        "hello".should_be("hello");
    }
}

class category_of_examples : describe_NSpec
{
    void before_each()
    {
        Console.WriteLine("I run before each test defined in this context.");
    }

    void it_also_works_here()
    {
        "hello".should_be("hello");
    }

    void it_works_here_too()
    {
        "hello".should_be("hello");
    }
}
    

but NSpec also provides a more concise option:

class describe_NSpec : nspec
{
    void before_each()
    {
        Console.WriteLine("I run before each test.");
    }

    void it_works_here()
    {
        "hello".should_be("hello");
    }

    void a_category_of_examples()
    {
        before = () => Console.WriteLine("I run before each test defined in this context.");

        it["also works here"] = () => "hello".should_be("hello");

        it["works here too"] = () => "hello".should_be("hello");
    }
}
    

specifications

using NSpec;
describe specifications
  when creating specifications
    true should be false (5ms) - FAILED - Expected: False, But was: True
    enumerable should be empty (1ms)
    enumerable should contain 1 (6ms)
    enumerable should not contain 1 (2ms) - FAILED - Expected: not collection containing 1, Bu...
    1 should be 2 (1ms) - FAILED - Expected: 2, But was: 1
    1 should be 1 (0ms)
    1 should not be 1 (3ms) - FAILED - Expected: not 1, But was: 1
    1 should not be 2 (0ms)
    "" should not be null (0ms)
    some object should not be null (0ms) - FAILED - Expected: not null, But was: null
    ninja should not be pirate (0ms)

**** FAILURES ****

nspec. describe specifications. when creating specifications. true should be false.
Expected: False, But was: True
   at describe_specifications.<when_creating_specifications>b__0() in c:\Development\NSpec\src...

nspec. describe specifications. when creating specifications. enumerable should not contain 1.
Expected: not collection containing 1, But was: < 1 >
   at describe_specifications.<when_creating_specifications>b__3() in c:\Development\NSpec\src...

nspec. describe specifications. when creating specifications. 1 should be 2.
Expected: 2, But was: 1
   at describe_specifications.<when_creating_specifications>b__4() in c:\Development\NSpec\src...

nspec. describe specifications. when creating specifications. 1 should not be 1.
Expected: not 1, But was: 1
   at describe_specifications.<when_creating_specifications>b__6() in c:\Development\NSpec\src...

nspec. describe specifications. when creating specifications. some object should not be null.
Expected: not null, But was: null
   at describe_specifications.<when_creating_specifications>b__9() in c:\Development\NSpec\src...

11 Examples, 5 Failed, 0 Pending

custom assertions

If you don't like the assertions provided by NSpec. You can create your own. Here is an example:
class custom_assertions : nspec
{
    void it_is_a_custom_assertion()
    {
        16.is_less_than(30);
    }
}

public static class AssertionExtensions
{
    public static void is_less_than(this int left, int right)
    {
         if(left >= right)
         {
             throw new InvalidOperationException(
                string.Format("{0} was not less than {1}", left, right));
         }
    }
}

  

NSpec also plays nice with assertion packages such as Fluent.Assertions.

before

using NSpec;
describe before
  they run before each example
    number should be 2 (9ms)
    number should be 1 (0ms)

2 Examples, 0 Failed, 0 Pending

contexts

using NSpec;
describe contexts
  describe Account
    when withdrawing cash
      account is in credit
        the Account dispenses cash (5ms)
      account is overdrawn
        the Account does not dispense cash (0ms)

2 Examples, 0 Failed, 0 Pending

pending

using NSpec;
describe pending
  when creating pending specifications
    pending spec - PENDING
    "" should be "something else" - PENDING

2 Examples, 0 Failed, 2 Pending

helpers

using NSpec;
describe helpers
  when making tea
    that is 210 degrees
      should be hot (10ms)
    that is 90 degrees
      should be cold (0ms)

2 Examples, 0 Failed, 0 Pending

act

using NSpec;

// TODO rename containing folder. Consider wrapping in namespace

[Tag("describe_act")]
describe batman sound effects as text
  they are loud and emphatic
    given bam
      should be BAM!!! (9ms)
    given whack
      should be WHACK!!! (0ms)

2 Examples, 0 Failed, 0 Pending

class level

using NSpec;
describe class level
  specify given befores and acts run in the correct sequence (8ms)

1 Examples, 0 Failed, 0 Pending

inheritance

using NSpec;

[Tag("describe_inheritance")]
given the sequence starts with 1
  given the sequence continues with 2
    given the sequence continues with 3
      sequence should be "123" (8ms)

1 Examples, 0 Failed, 0 Pending

exception

using System;
using NSpec;
describe exception
  given a null string
    should throw null-ref (2ms)

1 Examples, 0 Failed, 0 Pending

Summary

  • Install via NuGet (VS2010+)
  • or download zip from github https://github.com/mattflo/NSpec/downloads
  • Requires .NET 3.5
  • Classes inherit from nspec
  • Classes and methods
    • are contexts
    • do not require an access modifier
  • Inside methods
    • sub contexts are created (context/describe)
    • specifications are declared (it/specify)
    • before lambdas are assigned that run before each specification
    • act lambdas are assigned that run after befores but before specifications