1 February 2008

The different flavors of tests

by mo

If you’re going to practice any form of unit testing you need to learn about the different types of tests. I have yet to read XUnit Test Patterns, but I’m sure this will offer a great deal more detail then this post. Also, I’m anxiously awaiting “The Art Of Unit Testing”.

Unit Tests

Unit tests are blocks of code that exercise very specific areas of a code base to ensure the it is meeting it’s responsibility (NOT responsibilities in the plural sense. See Single Responsibility Principal). At it’s core its asserting that a very specific result or behavior is met. Unit tests can be broken down into two types.

Black Box Testing (State Based)

The first is the traditional state based (black box) unit tests. These are unit tests that assert that components of the system exert a behavior that expected from the perspective of a client component. It cares less about the actual implementation of the component and more about the result. These types of tests tend to be easier to refactor and are a great way to start learning about test driven development or unit testing in general. The unit tests give you the confidence to go in to the trenches and make significant changes to the underlying implementation. This allows you to evolve a code base with confidence and precision. Software development is an evolutionary process. Using the same architecture and tools that you did from several years ago could indicate a smell.

For example:

  public void Should_be_able_to_lease_a_slip() 
    ICustomer customer = CreateSUT();
    ISlip slip = ObjectMother.Slip();
    ILeaseDuration duration = LeaseDurations.Monthly;

    customer.Lease(slip, duration);

    Assert.AreEqual(1, ListFactory.From(customer.Leases()).Count);

White Box Testing (Interaction Based)

This type of unit test is more focused on the interaction of components then the result. It’s verifying expectations that components are working as expected with it’s dependencies under different conditions. It’s a way to simulate different environment conditions without actually having to exercise the component in that environment. The canonical example is to mock or stub out an interaction with a database or third party component.

It’s called white box testing because it’s like you can see clearly through the box to see what’s going on inside. It might make more sense to refer to this as glass box testing.

For example:

  public void Should_leverage_task_to_retrieve_all_registered_boats_for_customer()
    long customerId = 23;
    IList<BoatRegistrationDTO> boats = new List<BoatRegistrationDTO>();

    using (_mockery.Record())

    using (_mockery.Playback())

Integration Tests

Integration tests are tests that sweep across a system. They exercise the system from top down, to ensure that it is behaving as expected in a production like environment. This is a great place to weed out contracts that have not been implemented, and help to identify different environment scenarios that may need further unit testing. These tests actually hit the third party components and exercise the full system. These tests typically take a little longer depending on the environment conditions such as hitting a database.

There are frameworks available, such as Fit, that allow business analysts to define test criteria that can then exercise the system top down. The problem with some of these frameworks is that they can implicitly allow the BA to start designing how the system is implemented if taken as a literal design spec. I much prefer writing top down tests rather then implementing fit-like fixtures.

agile tdd csharp