Geeks With Blogs
Ontological Reciprocity Contributions to Our Influences

Recently I’ve been able to extend my unit test code coverage as I’ve been introducing more features into our code base. I know this is something that should always be done, but for whatever reason, that’s not the case. What I’ve come to notice is our current method of organizing our unit test makes adding new features and test for new features awkward.

Currently our unit tests align perfectly with the class they test. So for example, if we have a class:

namespace MyCompany.Domain{
     public class Foo{}
}
 

We have, or should have, a test fixture in a separate assembly that looks like this:

using MyCompany.Domain;
using NUnit.Framework;
namespace MyCompany.Domain.Tests{
    [TestFixture]
    public class FooTests{}    
}
 

This is probably a pretty typical strategy for organization. It is intuitive where to find tests for a type. Were I’m loosing my taste for this method is as the solution grows to several assemblies or layers, adding new unit tests for a specific feature becomes a scattered mess of changes. If I need to add a new field, I add new tests in the UI.Tests, the Domain.Tests, Repository.Tests, Core.Tests, etc.  Makes sense though right? You have to pass that new field through all the layers. I’m ok with the number of tests I need to write, but I don’t like having to go to eight different places to run them when I want to test my feature. It would be nice to align them them to the feature, or tag them in such a way I could find them easily. It could be that we are over layered and that is the real problem. We could be an onion.

Shrek: Example? Okay, er... ogres... are... like onions.
Donkey: [sniffs onion] They stink?
Shrek: Yes...NO!
Donkey: Or they make you cry.
Shrek: No!
Donkey: Oh, you leave them out in the sun and they turn brown and start sproutin' little white hairs.

We are definitely an onion….or an ogre, but that’s a whole different analogy.

There is a nice article in CoDe Magazine by Scott Bellware that talks about BDD. Most of it I didn’t see as valuable to my every day activities until he started talking about SpecUnit .Net. It was, in theory, what I’ve been looking for. Align my tests with my features/defects/requirements / whatever. SpecUnit .Net does some nice human readable report generation that I don’t need, but why would I need a new tool when I could just categorize my tests in folders that line up with my real world problems.

That gets me close, but there is no way to run the entire category without using the command line. Still doable, but not as nice as ReSharper’s unit test runner. It would be nice to get a Run all tests in this category from the context menu, but I’m not sure if that would be easy to do across the different frameworks. Again it would be nice to save my unit test session so I don’t loose it every time I close the IDE.

While we’re dreaming, Maybe we could invert the relationship and make the class under test and attribute and the tests themselves could align directly with the requirements. Something like this for example:

[Test][TypeUnderTest(typeof(Foo))] public void Correctly_Calculates_Bar(){
    //...
}

 

Or we could even get fancy with generics:

[Test<Foo>] public void Correctly_Calculates_Bar(){
    //...
}
 
The IDE, ReSharper or someone could let me run all the tests for Foo if I wanted. 

 

After Josh’s comments I thought I would add a couple screen shots of using the Category attribute to group the tests as needed. You can apply the Category attribute to the method or to the TestFixture.

    [TestFixture]   
    public class MyClassTests {
        
        [Category("Add the ability to do work")]
        [Test] public void DoWork_WithNoArgs_DoesWork(){  }

        [Category("Add the ability to do additional work ")]
        [Category("Add the ability to do work")]
        [Test]
        public void DoWork_WithAllArgs_DoesWork() {   }
    }

 

You can select Categories from the unit test runner’s Group by: combo box.

image

It then will group your tests by their category. I did find the UI a bit buggy. At first it wasn’t applying the grouping, but after a couple attempts they started to show up.

image

Thanks again Josh. That will keep me content for the time being. Now if I could only inspect the entire solution for tests in the category I would really happy.

Posted on Monday, June 30, 2008 6:19 PM Unit Testing | Back to top


Comments on this post: Unit Tests Everywhere

# re: Unit Tests Everywhere
Requesting Gravatar...
Check out NUnit's [Category()] attribute. It's like adding a 'tag' to a test. The R# TestRunner will allow you to group and run tests by the category values.
Left by Josh Buedel on Jun 30, 2008 8:35 PM

# re: Unit Tests Everywhere
Requesting Gravatar...
Thanks Josh! That's awesome. I knew about the [Category] attribute, but didn't look far enough right to see it could group by it!
Left by Mark on Jun 30, 2008 8:52 PM

# re: Unit Tests Everywhere
Requesting Gravatar...
> If I need to add a new field, I add new tests in the UI.Tests, the Domain.Tests, Repository.Tests, Core.Tests, etc. Makes sense though right?

What you're saying is that this field cuts across your modular boundaries {UI, Domain, Repository, Core, ...}. If that happens too often, then maybe you should rethink your modularization.

I wonder if the problem might be less that you have too many layers, and more that the layers have the wrong shape.

> Maybe we could invert the relationship and make the class under test and attribute and the tests themselves could align directly with the requirements

The compiler knows fairly well what classes are used by a method. As long as we're dreaming, let's dream about giving you the ability to ask "what tests use this type?" without adding any additional notation to your code. Wouldn't it be great if your test runner could take input from ReSharper's Find Usages feature?
Left by Sean on Jul 01, 2008 7:38 PM

Your comment:
 (will show your gravatar)


Copyright © Mark Borcherding | Powered by: GeeksWithBlogs.net