Tidycode

Tidy and clean code

Archive for the ‘Fluent language’ Category

Writing custom assertion handlers for Fluent Tests

leave a comment »

With Fluent Tests you can write tests in your own domain language using custom assertions handlers.

As an example, say you have a class Company and this class has a reference to another class Address, seems like a not so very uncommon scenario. In your unit tests you might want to assert that the company has an address. In a normal scenario this would be done like this :

Assert.IsTrue(company.Address!=null)

Well it’s readable, you can se that an assert is made and the address of the company should be set to an instance of a object. If this is done on several occasions you might want to consider using Fluent Tests.

With Fluent Tests you write a custom assertion handler that really just is an extension method. The extension method will be applied to a verb within the Fluent Tests framework.

First off, lets define so classes from the domain, Company and Address.

 

    public class Company
    {
       
public string Name { get; set; }
       
public Address Address { get; set
; }
    }

    public class Address
    {
       
public string StreetName { get; set; }
       
public string PostalCode { get; set
; }
       
public string ZipCode { get; set
; }
    }

The actual assertion handler is written as an extension method for the verb Has. In this case we won’t compare the value against another value so the only parameter in our extension method will be the verb.

    public static class CustomAssertionHandler
    {
       
public static void Address(this Has<Company
> verb)
        {
           
VerbAssert<Company>.Assert(verb,c=>c.Address==null,
                                           "Company has no address");
        }
    }

In our extension method we are using a helper class from the framework, VerbAssert. This class makes it easy to write the actual implementation by using a lambda expression as the actual assert method. When the lambda expression c=>c.Address==null is true, an assertion should be made. If an assertion should be made, an AssertionException will be thrown with the message “Company has no address”.

Now we can use our new assertion handler by simply typing Ensure.That(company).Has.Address();. You are now writing tests in your own domain language!

    [TestFixture]
   
public class CustomAssertionHandlerTest
    {
        [
Test
]
       
public void
TestCompanyForAddress()
        {
           
var company = new Company
();
           
Ensure.That(company).Has.Address();
        }
    }
Advertisements

Written by arvander

May 3, 2011 at 5:42 pm

Fluent testing

leave a comment »

The Assert class in MSTest can sometimes be a little limited when trying to write clean code. The readability of the code is far from optimal

int expected = 4;
int actual = 5;
Assert.IsTrue(expected>actual);

By extracting the variables expected and actual the intent is somewhat more readable. What I’m really is missing is a method called IsGreaterThan that compares two values. However, that method will take two parameters and there is a chance that they can be confused. Less parameters is better.

Since the class Assert is using static methods, creating an extension method is not an option. Instead, the natural thing to do seems to be to create a new class, MyAssert and attach a bunch of validating methods on that class instead.

public class MyAssert
{
 public void IsGreaterThan(int expected, int actual)
 {
 Assert .IsTrue(expected > actual);<
 }
}

But,  this makes it only partially easier to understand the code. The intent is clear, I want to assert that one value is to be greater than another but we still have the issue of the two parameters that has to be lifted out in separate fields in order to increase the readability.
To make it really readable, I’m using a fluent language so that I can type something like this.

 Ensure.That(4).IsGreaterThan(3);

This way the intent is totally clear and the parameters can not be confused.

There are a lot of frameworks availible that solves the problem in a very similar way, check out Codeplex for more information.

Written by arvander

April 26, 2011 at 10:03 pm