Constrained-based assert model

The latest version of NUnit Framework (version 2.4 and forward) comes with a new constrained-based assert model, which allows you to write complex assertions relatively easy with a new syntax. The old classical syntax for assertions with static methods still works and according to the NUnit blog there are no plans to deprecate the classical assertion syntax.

Assert.AreEqual(5, 5.0);

Assert.AreSame(person, person);

Assert.Greater(7, 5);

Assert.IsInstanceOfType(typeof(ArrayList), new ArrayList());

Assert.IsAssignableFrom(typeof(ICollection), new List());

StringAssert.StartsWith("Anders", "And");

CollectionAssert.AreEquivalent(col1, col2);

FileAssert.AreEqual(stream1, stream2);

The new constrained-based assert model uses a single method on the Assert class for all assertions:

Assert.That("Anders", new EqualConstraint("Anders"));

The second parameter is the type of assertions – here an equal constraint that works on all types of data – primitives, collections, streams etc.

NUnit comes with a number of constraints covering most scenarios, but also allows you to extend the model by developing custom constraint by realizing the IConstraint interface.

public interface IConstraint
{
    bool Matches(object actual);
    void WriteMessageTo(MessageWriter writer);
    void WriteDescriptionTo(MessageWriter writer);
    void WriteActualValueTo(MessageWriter writer);
}

If the syntax of constrained-based assert model seams a bit to complex and not very reader friendly, the NUnit team has implemented a range of syntax helper classes like so:

Assert.That("Anders", Is.EqualTo("Anders"));
Assert.That("Anders", Is.Not.EqualTo("Anja"));
Assert.That("Hello World!", Text.StartsWith("HELLO").IgnoreCase);
Assert.That("make me happy", Text.Contains("make"));

Assert.That(person, Is.SameAs(person));
Assert.That(null, Is.Null);
Assert.That(new object(), Is.Not.Null);
Assert.That("", Is.Empty);

Assert.That(new ArrayList(), Is.Empty);
Assert.That(myCol, Is.Unique);

Assert.That(7, Is.GreaterThan(5));
Assert.That(2.0d + 2.0d, Is.EqualTo(4.0d).Within(.000005d));

Assert.That(myPerson, Is.InstanceOfType(typeof(Person)));
Assert.That(new EqualConstraint(), Is.AssignableFrom(typeof(IConstraint)));

Assert.That(new int[] { 4, 5, 6 }, Is.All.GreaterThan(0));
Assert.That(new string[] { "abc", "bac", "cab" }, Has.All.Length(3));
Assert.That(new int[] { 4, 5 }, Is.SubsetOf(new int[] { 4, 5, 6 }));

The change of syntax separates NUnit from other unit test frameworks and therefore separates from the common approach of creating unit tests.

I like the new syntax – It is intuitive and easy to comprehend. All change is not, but it is simple rules of evolution. The notion of constraints is also found in NMock.


 Anders Lybecker is an chief architect at Kring Development A/S, a consultancy firm in Copenhagen, Denmark. He holds a degree in software engineering specializing in software development. His primary expertises are the Microsoft .Net framework and SQL Server which he has been working with since the start of this century! He enjoys discussing technical topics, teaching and speaking at conferences.


Related posts:

  1. A simple Windows Communication Foundation Web Service
  2. ASP.NET MVC Best Practices

Tags:

One Response to “Constrained-based assert model”

  1. adminNo Gravatar says:

    The Is.EqualTo(x).Within(tolerance) does not work as expected in the NUnit 2.4 release. The below unit test did not succeed with version 2.4:

    decimal expected = 35.27396M;
    decimal actual = 35.27397M;

    Assert.That(actual, Is.EqualTo(expected).Within(0.0001M));

    I upgrade to version NUnit version 2.4.3 today and then it work…

Leave a Reply