Wednesday, February 3, 2010

Building Integration Tests With Workflow Components

A lot of blood, sweat, and tears have been shed over the use and design of unit tests, but what about the red-headed stepchild of automated testing, integration tests? They have fallen out of vogue lately in popular discussion, but they can be just as useful as unit tests. Just search for unit test best practices and integration test best practices; the unit test search has almost twice the results.

One of the biggest stumbling blocks I have found with integration tests is internal dependencies (external ones, like databases and webservices, are also a pain, but you’re on your own for them). If you have to test an “Approve” action, you probably first need to “Create” the object before you can approve it. You’ve written your “Create” integration tests, so do you make your “Approve” tests inherit from the “Create” tests? That seems kind of ugly. But you don’t want to have duplicate code, even if it’s just in the tests.

A better solution is to split your integration tests into “workflow” classes. Each workflow class represents an action you want to test, “Create” in this case.

public class CreateResults   
{
//data to return
}

public class CreateWorkflow
{
public CreateResults DoAction()
{
//Do the action, return the results
}
}

You can use this code for your “Create” tests, but even cooler, your “Approve” workflow can consume the “CreateResults” object:

public class ApproveResults 
{
//data to return
}

public class ApproveWorkflow
{
public ApproveResults DoAction(CreateResults results)
{
//Do the action, using the data from the create test, return the results
}
}

How cool is that?

Well, what if you want to have a workflow with various options? We can do that:

public class CreateOptions   
{
//inputs to the workflow

public class CreateWorkflow
{
public CreateResults DoAction(CreateOptions options)
{
//Do the action using the provided options, return the results
}
}

You can experiment with using the “Options” and “Results” objects in different ways. YMMV. This may not solve all the problems with integration tests (and it’s not revolutionary, and someone else probably already did it), but it can make for some pretty modular tests and make your life easier.

No comments:

All rights reserved. Take that!