Fork me on GitHub

Sample code and output automatically executed against nspec version 0.9.66 on 2013-04-23 14:21:23 -0500.

Getting Started

Write Your First Spec

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

  1. Open Visual Studio 2010.
  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 given_the_world_has_not_come_to_an_end()
    {
        it["Hello World should be Hello World"] = () => "Hello World".should_be("Hello World");
    }
}
    

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
  given the world has not come to an end
    Hello World should be Hello World

1 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();
    

specifications

using NSpec;

class describe_specifications : nspec
{
    void when_creating_specifications()
    {
        //some of these specifications are meant to fail so you can see what the output looks like
        it["true should be false"] = () => true.should_be_false();
        it["enumerable should be empty"] = () => new int[] { }.should_be_empty();
        it["enumerable should contain 1"] = () => new[] { 1 }.should_contain(1);
        it["enumerable should not contain 1"] = () => new[] { 1 }.should_not_contain(1);
        it["1 should be 2"] = () => 1.should_be(2);
        it["1 should be 1"] = () => 1.should_be(1);
        it["1 should not be 1"] = () => 1.should_not_be(1);
        it["1 should not be 2"] = () => 1.should_not_be(2);
        it["\"\" should not be null"] = () => "".should_not_be_null();
        it["some object should not be null"] = () => someObject.should_not_be_null();
        //EXPERIMENTAL - specify only takes a lambda and does 
        //its best to make a sentence out of the code. YMMV.
        specify = ()=> "ninja".should_not_be("pirate");
    }
    object someObject = null;
}
describe specifications
  when creating specifications
    true should be false - FAILED - Expected: False, But was: True
    enumerable should be empty
    enumerable should contain 1
    enumerable should not contain 1 - FAILED - Expected: not collection containing 1, But was:...
    1 should be 2 - FAILED - Expected: 2, But was: 1
    1 should be 1
    1 should not be 1 - FAILED - Expected: not 1, But was: 1
    1 should not be 2
    "" should not be null
    some object should not be null - FAILED - Expected: not null, But was: null
    ninja should not be pirate

**** 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:\projects\NSpec\src\Sa...

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:\projects\NSpec\src\Sa...

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:\projects\NSpec\src\Sa...

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:\projects\NSpec\src\Sa...

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:\projects\NSpec\src\Sa...

11 Examples, 5 Failed, 0 Pending

before

using NSpec;

class describe_before : nspec
{
    void they_run_before_each_example()
    {
        before = () => number = 1;
        it["number should be 2"] = () => (number = number + 1).should_be(2);
        //even though it was incremented in the previous example
        //the before runs again for each spec resetting it to 1
        it["number should be 1"] = () => number.should_be(1);
    }
    int number;
}
describe before
  they run before each example
    number should be 2
    number should be 1

2 Examples, 0 Failed, 0 Pending

contexts

using NSpec;

class describe_contexts : nspec
{
    //context methods require an underscore. For more info see DefaultConventions.cs.
    void describe_Account()
    {
        //contexts can be nested n-deep and contain befores and specifications
        context["when withdrawing cash"] = () =>
        {
            before = () => account = new Account();
            context["account is in credit"] = () =>
            {
                before = () => account.Balance = 500;
                it["the Account dispenses cash"] = () => account.CanWithdraw(60).should_be_true();
            };
            context["account is overdrawn"] = () =>
            {
                before = () => account.Balance = -500;
                it["the Account does not dispense cash"] = () => account.CanWithdraw(60).should_be_false();
            };
        };
    }
    private Account account;
}
describe contexts
  describe Account
    when withdrawing cash
      account is in credit
        the Account dispenses cash
      account is overdrawn
        the Account does not dispense cash

2 Examples, 0 Failed, 0 Pending

pending

using NSpec;

class describe_pending : nspec
{
    void when_creating_pending_specifications()
    {
        it["pending spec"] = todo;
        //or just add an 'x' at the beginning of a specification that isn't quite ready
        xit["\"\" should be \"something else\""] = () => "".should_be("something else");
    }
}
describe pending
  when creating pending specifications
    pending spec - PENDING
    "" should be "something else" - PENDING

2 Examples, 0 Failed, 2 Pending

helpers

using NSpec;

class describe_helpers : nspec
{
    void when_making_tea()
    {
        context["that is 210 degrees"] = () =>
        {
            before = () => MakeTea(210);
            it["should be hot"] = () => tea.Taste().should_be("hot");
        };
        context["that is 90 degrees"] = () =>
        {
            before = () => MakeTea(90);
            it["should be cold"] = () => tea.Taste().should_be("cold");
        };
    }
    //helper methods do not have underscores
    void MakeTea(int temperature)
    {
        tea = new Tea(temperature);
    }
    Tea tea;
}
describe helpers
  when making tea
    that is 210 degrees
      should be hot
    that is 90 degrees
      should be cold

2 Examples, 0 Failed, 0 Pending

act

using NSpec;

[Tag("describe_act")]
class describe_batman_sound_effects_as_text : nspec
{
    void they_are_loud_and_emphatic()
    {
        //act runs after all the befores, and before each spec
        //declares a common act (arrange, act, assert) for all subcontexts
        act = () => sound = sound.ToUpper() + "!!!";
        context["given bam"] = () =>
        {
            before = () => sound = "bam";
            it["should be BAM!!!"] = 
                () => sound.should_be("BAM!!!");
        };
        context["given whack"] = () =>
        {
            before = () => sound = "whack";
            it["should be WHACK!!!"] = 
                () => sound.should_be("WHACK!!!");
        };
    }
    string sound;
}
describe batman sound effects as text
  they are loud and emphatic
    given bam
      should be BAM!!!
    given whack
      should be WHACK!!!

2 Examples, 0 Failed, 0 Pending

class level

using NSpec;

class describe_class_level : nspec
{
    //before, act, and it can also be declared at the class level like so
    void before_each()
    {
        sequence = "arrange, ";
    }
    void act_each()
    {
        sequence += "act";
    }

    //prefixing a method with "it_" or "specify_"
    //will tell nspec to treat the method as an example
    void specify_given_befores_and_acts_run_in_the_correct_sequence()
    {
        sequence.should_be("arrange, act");
    }

    string sequence;
}
describe class level
  specify given befores and acts run in the correct sequence

1 Examples, 0 Failed, 0 Pending

inheritance

using NSpec;

[Tag("describe_inheritance")]
class given_the_sequence_continues_with_2 : given_the_sequence_starts_with_1
{
    void before_each()
    {
        sequence += "2";
    }
    void given_the_sequence_continues_with_3()
    {
        before = () => sequence += "3";

        //the befores run in the order you would expect
        it["sequence should be \"123\""] =
            () => sequence.should_be("123");
    }
}

class given_the_sequence_starts_with_1 : nspec
{
    void before_each()
    {
        sequence = "1";
    }
    protected string sequence;
}
given the sequence starts with 1
  given the sequence continues with 2
    given the sequence continues with 3
      sequence should be "123"

1 Examples, 0 Failed, 0 Pending

exception

using System;
using NSpec;

class describe_exception : nspec
{
    void given_a_null_string()
    {
        it["should throw null-ref"] =
            expect<NullReferenceException>(() => nullString.Trim());
    }
    string nullString = null;
}
describe exception
  given a null string
    should throw null-ref

1 Examples, 0 Failed, 0 Pending

Summary

  • Install via NuGet (VS2010 only)
  • 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