Alan Dean

CTO, Developer, Agile Practitioner

Photograph of Alan Dean

Showing posts with label TDD. Show all posts
Showing posts with label TDD. Show all posts

Saturday, November 12, 2011

Unit test naming convention

I have been using TDD since before it was even called that. The practice was called test-first at the time and I learnt to do it with ComUnit against VB6 code. I suspect that there aren't many people who can put down more than a decade of of TDD on their CV. Probably due to this, I employ somewhat idiosyncratic practices, such as a distinct interface focus (both the default interface and those additionally implemented). Accordingly, I have a fairly well elaborated naming convention for my unit tests in order to make test scenario coverage more rigorous and visible.

The overall convention is public void memberKind_parameterType_parameterType_whenScenarioInfo()

Member Kinds (when default or implicit interface implementation)

  • Constructors: ctor
  • Properties: prop
  • Indexers: index
  • Methods: op, opImplicit, opExplicit
  • Generic Methods: op_MethodNameOfT, op_MethodNameOfClass, op_MethodNameOfNew, op_MethodNameOfIInterfaceName

Member Kinds (when explicit interface implementation)

  • Properties: IInterfaceName_prop
  • Indexers: IInterfaceName_index
  • Methods: IInterfaceName_op

Special Names

  • Type definition assertions: a_definition
  • Assert deserialization: xmlDeserialize, jsonDeserialize
  • Assert serialization: xmlSerialize, jsonSerialize

Parameter Types

  • Keywords: int, string
  • Null types: stringNull, TypeNameNull
  • Empty string: stringEmpty
  • Invalid string: stringInvalid
  • Specific values: longZero, intOne, decimalNegative, floatEpsilon, shortMin, DateTimeNow

When
Used to disambiguate two or more tests which otherwise have the same name, e.g. op_ToString_whenDefault(), op_ToString_whenDescriptionIsNull()

Examples
Cavity has almost complete test coverage so there are plenty of examples. Here are some:

Update

So obvious that I forgot to mention it, but worth putting on the record: each class should have exactly one test class, i.e. Example.cs has Example.Facts.cs (if xUnit) or Example.Tests.cs (if NUnit, MSTest, etc.). The period in Example.Facts or Example.Tests is to force the same sort order of units and tests in the Visual Studio solution explorer tree view. I use a pair of templates to assist me (installer available in downloads).

Tuesday, June 29, 2010

Multiton Pattern

I’m doing a little ‘brushing up on the basics’ at the moment and as part of that effort I am working up some pattern examples, starting with creational patterns. These include staples such as Factory Method, Abstract Factory, Prototype, Singleton and so on but there are other creational patterns which weren’t in the Gang of Four (GoF) Design Patterns book. One of these is the Multiton. I don’t know what it’s provenance is, but it is an extension to the Singleton pattern which provides centralised access to a single collection making keys unique within scope. In my example, the singleton is declared as a static member so it has application domain scope.

I like to work up examples that feel (at least somewhat) real-world as I find that these are easier to remember later on. For the Multiton pattern I decided to use the Rolodex which is simply a collection of cards for my purposes:

public sealed class Card
{
    internal Card(string key)
    {
        this.Key = key;
    }

    public string Information
    {
        get;
        set;
    }

    public string Key
    {
        get;
        set;
    }
}

The pattern defines that item creation is handled by a static factory if the key does not exist in the collection:

using System;
using System.Collections.ObjectModel;
using System.Linq;

public sealed class Rolodex
{
    private static Rolodex _rolodex = new Rolodex();

    private Rolodex()
    {
        this.Cards = new Collection<Card>();
    }

    private Collection<Card> Cards
    {
        get;
        set;
    }

    public static Card Open(string key)
    {
        Card result = null;

        lock (_rolodex)
        {
            result = _rolodex.Cards
                .Where(x => string.Equals(x.Key, key, StringComparison.Ordinal))
                .FirstOrDefault();

            if (null == result)
            {
                result = new Card(key);
                _rolodex.Cards.Add(result);
            }
        }

        return result;
    }
}

Here is a test which verifies the expected behaviour:

Xunit;

public sealed class MultitonFacts
{
    [Fact]
    public void rolodex_card()
    {
        string key = "John Doe";

        Card expected = Rolodex.Open(key);
        expected.Information = "john.doe@example.com";

        Card actual = Rolodex.Open(key);

        Assert.Same(expected, actual);
    }
}

It’s worth pointing out that, as with all Singleton patterns, the plain vanilla pattern doesn’t lend itself to unit testing as-is. The answer is to provide a wrapper for mocking purposes. Here is an example of doing so for DateTime.UtcNow:

using System;

public static class DateTimeFactory
{
    [ThreadStatic]
    private static DateTime? _mock;

    public static DateTime Today
    {
        get
        {
            DateTime value = DateTime.Today;

            if (null != _mock)
            {
                value = _mock.Value.Date;
            }

            return value;
        }
    }

    public static DateTime UtcNow
    {
        get
        {
            DateTime value = DateTime.UtcNow;

            if (null != _mock)
            {
                value = _mock.Value;
            }

            return value;
        }
    }

    public static DateTime? Mock
    {
        get
        {
            return _mock;
        }

        set
        {
            _mock = value;
        }
    }

    public static void Reset()
    {
        DateTimeFactory.Mock = null;
    }
}

Thursday, June 17, 2010

Mocking IServiceLocator

Using IoC has become far more popular in recent years but it is very easy to end up decoupling your components but at the same time end up tightly coupled to a specific provider, such as Castle Windsor. The first step to decouple the IoC provider is to utilize the Common Service Locator published by the Microsoft patterns & practices team. Here is a trivial example of decoupling using the ServiceLocator:

namespace Example
{
    using Microsoft.Practices.ServiceLocation;

    public interface IFoo
    {
        void Foo();
    }

    public sealed class FooImplementation : IFoo
    {
        public void Foo()
        {
        }
    }

    public sealed class Class1
    {
        public Class1()
        {
            this.Foo = ServiceLocator.Current.GetInstance<IFoo>();
        }

        public IFoo Foo
        {
            get;
            private set;
        }
    }
}

However, if you run the following test, a System.ArgumentNullException will be thrown as the ServiceLocator does not have a provider set:


namespace Example
{
    using Xunit;

    public sealed class Class1Facts
    {
        [Fact]
        public void ctor()
        {
            Assert.NotNull(new Class1());
        }
    }
}

Rather than configure a specific provider, it’s much cleaner to mock out the ServiceLocator. The following example uses Moq but the principle applies regardless of your preferred mocking framework:


namespace Example
{
    using Microsoft.Practices.ServiceLocation;
    using Moq;
    using Xunit;

    public sealed class Class1Facts
    {
        [Fact]
        public void ctor()
        {
            try
            {
                var mock = new Mock<IServiceLocator>();
                mock.Setup(x => x.GetInstance<IFoo>()).Returns(new FooImplementation()).Verifiable();
                ServiceLocator.SetLocatorProvider(new ServiceLocatorProvider(() => mock.Object));

                Assert.NotNull(new Class1());

                mock.VerifyAll();
            }
            finally
            {
                ServiceLocator.SetLocatorProvider(null);
            }
        }
    }
}

Tuesday, June 15, 2010

Cavity Unit Testing

I have started a new open source project on google code which I've named Cavity for no particular reason other than it's somewhat memorable: http://code.google.com/p/cavity/ and I plan on pushing up some of the code I use to accelerate and assist development, starting with an internal DSL for unit testing type and property definitions.

I’ve been doing TDD for about 9 years now and have, I admit, derived a somewhat idiosyncratic style which involves asserting all of the external characteristics of a type. I don’t agree with those who argue in favour of not testing properties (I disagree because properties have behaviour and thus ought to be verifiable). I also believe that interface implementations and attribute decorations should be verifiable (which also speaks to my belief in what I call intentional development). However there is a downside to this, which is that asserting type and property definitions is slower than not doing so (obviously) and so I use my unit test DSL to accelerate the process and thus mitigate the impedance. This has been living inside the SimpleWebServices project for a while now but I thought it was time to promote it to a more formal offering and so it is the first library available from Cavity.

To give you a flavour, here are a couple of examples of testing a class and a property:

[Fact]
public void type_definition()
{
    Assert.True(new TypeExpectations<Class1>()
        .DerivesFrom<object>()
        .IsConcreteClass()
        .IsUnsealed()
        .HasDefaultConstructor()
        .Implements<IFoo>()
        .IsDecoratedWith<CustomAttribute>()
        .Result);
}

[Fact]
public void value_definition()
{
    Assert.True(new PropertyExpectations<Class1>("Value")
        .TypeIs<string>()
        .DefaultValueIs("default")
        .Set("example")
        .ArgumentNullException()
        .ArgumentOutOfRangeException(string.Empty)
        .FormatException("invalid")
        .IsNotDecorated()
        .Result);
}

The binaries and source are zipped for download and to see more examples, please visit the wiki: