Home
Introduction
.NetSpec is a small test extension framework for the Visual Studio Testing Framework. Its main goals are:
- Allow users to write tests in an RSpec like syntax more in terms with Behaviour Driven Developement (BDD)
- Make tests easier to read
- Integrate with TFS team build and Visual Studio test view
Behaviour driven development (BDD)
BDD is a software development technique which in many ways is similar to Test Driven Development (TDD). Many people consider it an enhancement of TDD. The main goal in BDD is that tests should describe the behaviour of your classes, and thus provide documentation of your code using code. It also makes it easier to write tests, because the focus has switched from "what to test" to "how should this class behave in differnt scenarios". You can read more about BDD on Wikipedia or http://behaviour-driven.org/
Usage
Create a new unit test and add the Using NetSpec; line to the usings add the top. Now you are ready to roll.
The new extension methods in .NET 3.5 allows for a really nice syntax:
[TestClass]
public class StackDescription
{
var stack = new Stack<String>();
[TestMethod]
public void ShouldReturnTopElementOnPop()
{
stack.Push("car");
stack.Push("Elephant");
stack.Pop().ShouldBe("Elephant");
}
[TestMethod]
public void ShouldUpdateCountOnPush()
{
stack.Count.ShouldBe(0);
stack.Push("s");
stack.Count.ShouldBe(1);
stack.Push("x");
stack.Count.ShouldBe(2);
}
As you can see you can now write the asserts using a method called ShouldBe(). Personally I think this makes the test a lot easier to read.
The syntax for expecting exceptions has also changed:
[TestMethod]
public void ShouldThrowExceptionOnPoppingEmptyStack()
{
stack.Count.ShouldBe(0);
Call.To(() => stack.Pop()).ShouldThrow<InvalidOperationException>();
}
You write whatever code you expect to throw an exception inside a lambda expression or delegate block, and the ShouldThrow method checks that the exception was actually caught and was of correct type. There are several reasons why this way checking that expected exceptions are thrown, is better than using the [ExpectedException] attribute. The most important reason is that when you are using the attribute, you don't know which line threw the exception. So you are not really sure your test fails when you expect it to.
Note that the TestClass and TestMethod attributes are kept to allow the tests to be run using the Visual Studio test view and the TFS builds.
Syntax
Check value
- Syntax:
object.ShouldBe(expectedValue) - Example:
Stack.Count.ShouldBe(1);
Check value (alternative)
- Syntax:
object.ShouldEqual(expectedEqualObject) - Example:
PersonFinder.GetPerson(1).ShouldEqual(person);
Check different value
- Syntax:
object.ShouldNotBe(unexpectedValue) - Example:
Stack.Count.ShouldNotBe(2);
Check different value (alternative)
- Syntax:
object.ShouldNotEqual(objectNotExpectedToBeEqual) - Example:
PersonFinder.GetPerson(2).ShouldNotEqual(person);
Check that string contains
- Syntax:
string.ShouldContain(expectedString) - Example:
html.ShouldContain("<body");
Check that string does not contain
- Syntax:
string.ShouldNotContain(unexpectedString) - Example:
escapedHtml.ShouldNotContain("<");
Check that string matches regular expression
- Syntax:
string.ShouldMatch(expectedPattern) - Example:
name.ShouldMatch(new Regex("[a-z]+"));
Check that string does not match regular expression
- Syntax:
string.ShouldNotMatch(unexpectedPattern) - Example:
escapedHtml.ShouldNotContain(new Regex("[<>]"));
Check that list/enumerable contains
- Syntax:
IEnumerable.ShouldContain(expectedElement) - Example:
personList.ShouldContain(person);
Check that list/enumerable does not contain
- Syntax:
IEnumerable.ShouldNotContain(unexpectedElement) - Example:
studentList.ShouldNotContain(professor);
Expect an exception
- Syntax (lambda):
Call.To(() => methodCall on object).ShoultThrow<ExceptionType>() - Syntax (delegate):
Call.To(delegate { methodCall on object }).ShoultThrow<ExceptionType>() - Example (lambda):
Call.To(() => stack.Pop()).ShouldThrow<InvalidOperationException>(); - Example (delegate):
Call.To(delegate { stack.Pop(); }).ShouldThrow<InvalidOperationException>(); - Returns: The exception

