HowTo – NUnit – Fluent Assertions

Source Code

All source code can be found on GitHub here.

My cheat sheet for NUnit can be found here.

This is part of my HowTo in .NET seriies. An overview can be seen here,

Intro

NUnit is a unit test framework for .net; it is very mature and contains lots of features when compared to XUnit.

This post is part of a 3 part post on NUnit:

  1. NUnit Features
  2. Assertions
  3. Fluent Assertions

This post covers the Fluent Assertions.

Most of these are self explanatory so my words will at time be minimal; highlighting or obscure points.

The examples given are the simplest self explantory way to define a pass using the assertion.

Fluent

Fluent is a programming style or design pattern. Methods return the class instance to allow another method on the test to be called by simply writing the next method on the same line of code.

The reason why this coding is nice as it allows grouping parameters together and allowing the method names to describe what happens.

Consider the following example.

// Fluent
Assert.That (1.1, Is.EqualTo (1.01).Within (10).Percent);

An equivalent though theoretical equivalent on the non fluent assertions.

// Non Fluent
Assert.EqualToOrWithin (1.1, 1.01, 10);

Both methods only actually have one method executing ‘functional’ code though without an understanding of the parameter names or even what the methods do the fluent syntax is more verbose and easier to read; especially if you are new to the code.

Numerical Equality

Numerical equality with error tolerance and units. No units would use the tolerance value directly, the percent tolerance allows the difference between the result and expected result up to within the provided percent.

Assert.That (1, Is.EqualTo (1));
Assert.That (1, Is.Not.EqualTo (2));
Assert.That (1.1, Is.EqualTo (1.2).Within (0.1)); // Allow a tolerance exact value used
Assert.That (1.1, Is.EqualTo (1.01).Within (10).Percent); // Pass tolerance within percent

Float Equality

Float tolerance allows error tolerance ignoring the last x placed digits.

Assert.That (20000000000000004.0, Is.EqualTo (20000000000000000.0).Within (1).Ulps); // Pass tolerance with units of last place

The tolerance unit has many types for tolerating against all fractions of a time of day; day, hour, minutes etc.

Assert.That (DateTime.Today, Is.EqualTo (DateTime.Today));
Assert.That (DateTime.Now, Is.Not.EqualTo (DateTime.Now));
Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (TimeSpan.FromSeconds (1))); // Time based pass tolerances
Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Days);
Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Hours);
Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Minutes);
Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Seconds);
Assert.That (DateTime.Now, Is.EqualTo (DateTime.Now).Within (1).Milliseconds);

String Equality

String equality with and without case sensitivity. Also comparing all elements within a collection.

Assert.That ("Foo!", Is.EqualTo ("Foo!"));
Assert.That ("Foo!", Is.Not.EqualTo ("FOO!"));
Assert.That ("Foo!", Is.EqualTo ("FOO!").IgnoreCase);
Assert.That (new List<string> (){ "FOO!"}, Is.EqualTo (new List<string> (){ "Foo!"}).IgnoreCase);

Collection

Assertions for comparing collections and their elements for equality; equality is made if each element in the same position (irrelevant of the collection and the element types) are equal and the amount of elements inside both collections is the same.

AsCollection provides a way to ‘flatten’ a jagged array or collection of collections to compare just the elements. In the example below {{1,2},{3,4}} flattens to {1,2,3,4}.

Assert.That (new double[] {1.0,2.0,3.0}, Is.EqualTo (new int[] {1,2,3}));
Assert.That (new double[] {1.0,2.0,3.0}, Is.Not.EqualTo (new int[] {1,2,3, 4}));
Assert.That (new double[] {1.0,2.0,3.0,4.0}, Is.EqualTo (new  int[,] {{1,2}, {3,4}}).AsCollection); // Compare data and not collection (flattens a collection of collections)

Customer Comparer

A custom comparer can be written for comparison between two objects of the same type. Create a class which implements IEqualityComparer and use the EqualTo assertion along with providing an instance of the comparer class.

Assert.That( int.MinValue, Is.EqualTo(int.MaxValue).Using(new WhoCaresComparer()));

public class WhoCaresComparer : IEqualityComparer<int>
{
    public bool Equals(int b1, int b2)
    {
		return true;
    }

    public int GetHashCode(int aNumber)
    {
		return aNumber.GetHashCode();
    }
}

Identity

Identify assertions check that two reference types are the same instance.

Assert.That( string.Empty, Is.SameAs(string.Empty));
Assert.That( new object(), Is.Not.SameAs(new object()));

A few conditional assertions for checking reference types are null or not null, collections are empty and unique etc.

Assert.That( string.Empty, Is.Not.Null);
Assert.That( true, Is.True);
Assert.That( true, Is.Not.False);
Assert.That( double.NaN, Is.NaN);
Assert.That( string.Empty, Is.Empty);
Assert.That( new List<int>(), Is.Empty);
Assert.That( new List<int>(){1,2,3}, Is.Unique);

Comparision

A number of assertions for comparing types which are numbers. AtLeast is the same as GreaterThanOrEqualTo and AtMost() is the same as LessThanOrEqualTo.

Assert.That(1, Is.LessThan(2));
Assert.That(1, Is.GreaterThan(0));
Assert.That(1, Is.LessThanOrEqualTo(1));
Assert.That(1, Is.GreaterThanOrEqualTo(1));
Assert.That(1, Is.AtLeast(0));	// Same as GreaterThanOrEqualTo
Assert.That(1, Is.AtMost(2)); 	// Same as LessThanOrEqualTo
Assert.That(1, Is.InRange(1,2));

File Paths

File path assertions; comparing the file path name only.

All path names are converted to ‘canonical’ path before comparing; full direct path to file. For example ‘~/Foo.txt’ would not fail against ‘/home/Luke/Foo/txt’ for user name Luke.

SubPath allows checking that the file under test is within a compared directory path.

SamePathOrUnder is the same as SubPath though won’t fail if the path names are the same.

File and directory paths can both be provided.

Assert.That( "MyFile.txt", Is.SamePath("MyFile.txt"));
Assert.That( "MyFile.txt", Is.SamePath( "MYFILE.TXT" ).IgnoreCase );
Assert.That( "MyFile.txt", Is.SamePath("MyFile.txt").RespectCase);
Assert.That( "/usr/bin", Is.SubPath("/usr"));			// directory exists within another
Assert.That( "/usr/bin", Is.SamePathOrUnder("/usr"));	// SamePath or SubPath

Type Constraints

Allow comparison that an instance is of a type, ancestor or can be cast to or from a type.

Assert.That(new MemoryStream(), Is.InstanceOf<Stream>());  // Is type or ancestor
Assert.That(new MemoryStream(), Is.TypeOf<MemoryStream>()); // Is type and not ancestor
Assert.That(new object(), Is.AssignableFrom<MemoryStream>()); // Can be assigned from
Assert.That(new MemoryStream(), Is.AssignableTo<Stream>()); // Can be assignable to

String Comparison

Comparison of strings for their contents with and without case sensitivity.

Assert.That( "Foo", Is.StringContaining( "o" ) );
Assert.That( "Foo", Is.StringContaining( "O" ).IgnoreCase );
Assert.That( "Foo", Is.StringStarting( "F" ) );
Assert.That( "Foo", Is.StringEnding( "o" ) );
Assert.That( "Foo", Is.StringMatching( "^[F]" ) ); // Regular ecpression match

Collection comparison for comparing all entities; all very self explanatory with the fluent interface.

Equivalent compares entities and not their order; i.e performs a sort prior.

Assert.That( new List<int>(){1,2,3}, Has.All.GreaterThan(0) );
Assert.That( new List<int>(){1,2,3}, Is.All.GreaterThan(0) );
Assert.That( new List<int>(){1,2,3}, Has.None.GreaterThan(4));
Assert.That( new List<int>(){1,2,3}, Has.Some.GreaterThan(2));
Assert.That( new List<int>(){1,2,3}, Has.Count.EqualTo(3));
Assert.That( new List<int>(){1,2,3}, Is.Unique);
Assert.That( new List<int>(){1,2,3}, Has.Member(1));  // Contains
Assert.That( new List<int>(){1,2,3}, Is.EquivalentTo( new List<int>(){3,2,1})); // Same data without caring about the order
Assert.That( new List<int>(){1,2,}, Is.SubsetOf( new List<int>(){3,2,1})); // All are contained.

Property Constraint

Ability to compare a property value of a class and a required value. There are some predefined property names for exceptions message and inner exception.

Assert.That( new List<int>(), Has.Property("Count").EqualTo(0));  // Checks public property
Assert.That( new List<int>(), Has.Count.EqualTo(0));			  // Same as Has.Property("Count").EqualTo(0)
Assert.That( string.Empty, Has.Length.EqualTo(0));				  // Same as Has.Property("Length").EqualTo(0)
Assert.That ( new Exception("Foo"), Has.Message.EqualTo("Foo"));  // Exception has message
Assert.That ( new Exception("Foo", new ArgumentException("Moo")), // Inner exception is of type and has message
             Has.InnerException.InstanceOf<ArgumentException>().And.InnerException.Message.EqualTo("Moo"));

Exception

Ability to ensure that an exception is thrown and that it is of the right types and contents. Throws also contains references to some of the more common exceptions.

Assert.That (() => { throw new ArgumentException("Foo"); },
	Throws.Exception.InstanceOf<ArgumentException>().And.Message.EqualTo("Foo"));

Assert.That (() => { throw new ArgumentNullException("Foo"); },
	Throws.Exception.TypeOf<ArgumentNullException>());

Assert.That (() => { throw new ArgumentNullException("Foo"); },
	Throws.InstanceOf<ArgumentNullException>());

Assert.That (() => { }, Throws.Nothing);

Assert.That (() => { throw new Exception("Foo", new ArgumentException("Moo"));},
	Throws.Exception.Message.EqualTo("Foo").And.InnerException.InstanceOf<ArgumentException>());

Assert.That (() => { throw new ArgumentException(); }, Throws.ArgumentException);

Compound Constraints

Compound constraints allow chaining checks together for when their readability is easier; i.e not intended to perform every check in one line of code as if we have to pay for a new line.

.And and & or Or and | can be used.

.Not and .All are also available.

Assert.That( 2, Is.Not.EqualTo( 1 ));
Assert.That( new List<int>(){ 1, 2, 3 }, Is.All.GreaterThan( 0 ) );

Assert.That( 1, Is.GreaterThan( 0 ).And.LessThan( 2 ) );  // .And amd & are the same
Assert.That( 1, Is.GreaterThan( 0 ) & Is.LessThan( 2 ) );

Assert.That( 1, Is.LessThan( 10 ) | Is.GreaterThan( 0 ) ); // .Or and | are the same
Assert.That( 1, Is.LessThan( 10 ).Or.GreaterThan( 0 ) );

Provides a thread sleep before performing the test. The second argument allows ‘pooling’ where assertion will happen after x time though the execution of the next line of code won’t be delayed.

Assert.That(() => { return true;}, Is.True.After(10));		// Passes after x time
Assert.That(() => { return true;}, Is.True.After(10, 10));	// Passes after x time and polling..

List Mapper

Allows all elements in a list to have a condition provided to them and a list of the expected results.

Assert.That(List.Map(new List<string>(){"1", "22", "333"}).Property("Length"), Is.EqualTo(new List<int>(){1,2,3}));
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s