TestFixture attribute – just because R# doesn’t care, doesn’t mean you shouldn’t

Recently I noticed ReSharper’s built-in test runner doesn’t require you to decorate your fixtures as TestFixture — it’s smart enough to locate Test methods regardless. My team noticed this too, and as a result we’ve started to omit TestFixture entirely.

Turns out this is a big mistake. NUnit itself requires them — in our case, we discovered our build server (which calls NUnit directly) was ignoring a large number of tests (including some that were failing), and was reporting much lower code coverage results than expected.

So, somehow we need to enforce that the TestFixture attribute is applied everywhere it should be, so us lazy ReSharper developers don’t miss anything. Not to worry… we can write a test for that!

[TestFixture]
public class MissingTestFixtureAttributeTests
{
    [Test]
    public void All_test_fixtures_must_have_test_fixture_attribute()
    {
        IEnumerable<Type> badFixtures =
            from t in Assembly.GetExecutingAssembly().GetTypes()
            where HasTests(t)
            where IsMissingTestFixtureAttribute(t)
            select t;

        ErrorIfAny(badFixtures);
    }

    static bool HasTests(Type type)
    {
        var testMethods =
            from m in type.GetMethods()
            from a in m.GetCustomAttributes(typeof (TestAttribute), true)
            select m;

        return testMethods.Any();
    }

    static bool IsMissingTestFixtureAttribute(Type type)
    {
        var attributes =
            from a in type.GetCustomAttributes(typeof (TestFixtureAttribute), true)
            select a;

        return !attributes.Any();
    }

    private static void ErrorIfAny(IEnumerable<Type> fixtures)
    {
        if (!fixtures.Any())
            return;

        var sb = new StringBuilder("The following types are missing [TestFixture] attributes:");
        sb.AppendLine();
        foreach(Type type in fixtures)
        {
            sb.AppendLine();
            sb.Append(type);
        }

        throw new Exception(sb.ToString());
    }
}
May 13, 2010

2 Comments

Bevan Arps on May 14, 2010 at 8:42 am.

I like it – a good example of a unit test to enforce team conventions.

Scott on May 17, 2010 at 2:10 am.

Hah – a test to test tests! Nice!

Leave a Reply