Showing posts with label xUnit. Show all posts
Showing posts with label xUnit. Show all posts

Wednesday, January 5, 2011

Separating Integration Tests from Unit Tests with xUnit

How often do you find that you’ve written a very useful test that crosses a process boundary, or makes changes to another system (file system, database) which by definition of a Unit Test shouldn’t be tested as part of your code coverage, but its highly useful.

Here are some attributes that you can use to mark up your (these are inspired by several other posts out there on the internet).

public sealed class IntegrationFactAttribute : FactAttribute
{
protected override IEnumerable EnumerateTestCommands(IMethodInfo method)
{
var attrs = method.MethodInfo.GetCustomAttributes(typeof(IntegrationAttribute), true).Cast();

if (Skip == null && attrs.Any(x => x.ShouldRunTest))
{
return base.EnumerateTestCommands(method);
}

return new[] { new SkipCommand(method, method.Name, "Integration method skipped") };
}
}
The abstract class below defines a simple Boolean property in which we can define the circumstances under which we want to execute the method.
public abstract class IntegrationAttribute : Attribute
{
public abstract bool ShouldRunTest { get; }
}
Below is an example class that tests to see if there is a debugger attached, and if so, it returns true for the ‘ShouldRunTest’ property. When this is evaluated in the EnumerateTestCommands in the IntegrationFactAttribute it will run the marked test method.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class WhenInDebuggerAttribute : IntegrationAttribute
{
public override bool ShouldRunTest
{
get { return System.Diagnostics.Debugger.IsAttached; }
}
}
Example using both attributes. This test which tests through to the database will only be run if it was executing inside of the debugger. If you are using Resharper or TestDriven.NET then you can execute the test while debugging but no longer need to worry need to be concerned that your continuous build environment will be testing code depends on a shared resource.
[IntegrationFact, WhenInDebugger]
public void CheckLiveRepositoryOnClinicianByOrganizationID()
{
const int idToMatch = 1;

// Create LS2 Repository
var repository = CreateRepository();

// Use a Specification to retrieve results
var clinicians = repository.Find(ClinicianSpecs.ByOrganizationID(idToMatch)).ToList();

// Assert valid
clinicians.Should().Not.Be.Null();
}
Note that I’m using the Should Assertion Library instead of the Assert.NotNull(). If you’re interested in more behavior driven development then this library makes your assertions read well.