Adventures in NUnit test categorization

As new tests are added to a code base, the build time will invariably increase. As I have written about before, a process of copasetic test categorization can be employed to help manage build times and thus, test frequencies. As it turns out, test categorization is easy to implement in NUnit using the aptly named Category attribute.

While a particular nomenclature isn’t terribly important, I do believe it essential to standardize on a common vocabulary and understand the neat-o concepts related to each. Briefly, I recommend the following three hip categories:

  • Unit tests verify the behavior of small elements in a software system, which are most often a single class. A unit test should run to completion (successfully) in a fraction of a second and should be run anytime a build is run.
  • Component tests test portions of a system and may require a fully installed system or a more limited set of external dependencies, such as databases or file systems to name a few. Because these smokin’ tests usually have multiple dependencies, they take a bit longer to run and should be run at regular intervals.
  • System tests exercise a complete software system. Because these tests exercise an entire system, they are often created towards the latter cycles of development; furthermore, these tests have the tendency to have lengthy run times, in addition to prolonged set up times.

NUnit’s tripping category attribute can be applied to both classes (i.e a TestFixture) and test methods (i.e. a Test). For example, the following C# test, which verifies an object’s Equals implementation, has been categorized as belonging to the unit group.

[Test]
[Category("unit")]
public void VerifyEquals()
{
  Word wrd1 = new Word();
  wrd1.Spelling = "cerebration";
  wrd1.PartOfSpeech = "noun";

  Word wrd2 = new Word();
  wrd2.PartOfSpeech = "noun";
  wrd2.Spelling = "cerebration";

  Assert.IsTrue(wrd1.Equals(wrd2), "words were not equal!");
}

Additionally, an entire class can be associated with a group by declaring the Category attribute at the TestFixture level as demonstrated below:

[TestFixture]
[Category("component")]
public class WordsTest
{
  //.....
}

Once tests have been grouped accordingly, various NUnit runners can be configured to run a selected group or set of groups. For example, configuring a desired group to execute via NAnt is as easy as creating four targets (each relating to a particular group, plus one for all three).

Below, the logic for running all component tests is captured in the <categories> sub-element of NUnit’s <test> element.

<target name="component-test" depends="build">
 <nunit2 failonerror="false">
  <formatter type="Xml" usefile="true" extension=".xml"
       outputdir="${build.dir}/results/component/" />
  <test assemblyname="${build.dir}\bin\${build.config}\words.dll"
        appconfig="mydefaulttest.config">

    <categories>
      <include name="component" />
    </categories>

  </test>
 </nunit2>
</target>

As part of integrating this categorization within a CI system, the frequencies from above are mapped to a particular target- for instance, the unit-test target (which runs unit tests) can be run anytime the CM system changes (i.e. someone checked something in).

Test categorization within NUnit couldn’t be simpler and by segregating tests into logical groups defined by how long they take to run, build times can be kept manageable as a code base’s tests grow. Dig it?

Post to Twitter

Related odds and ends
 

5 Responses to “Adventures in NUnit test categorization”

  1. on 11 Jun 2006 at 4:13 pm Jonathan Cogley

    Andy,

    Great post!

    This is exactly what we use! We use the Category attribute to differentiate between database read and DatabaseWrite tests (as DatabaseWrite tests are much more costly since the database needs to be reset) – we also mark Mock tests since they run much more quickly. This gives us a quick way to separate tests based on their execution speed without splitting up their logical organization – for example, having the tests for Authentication split across multiple unit test projects makes it difficult to navigate when adding new features.

    J


  2. [...] The newest version of JUnit does not contain a category annotation, like its rival TestNG or its distant cousin NUnit; however, this doesn’t mean you can’t easily categorize your tests. Much like pre-JUnit 4, the solution involves the use of suites; however, as anyone who is actually using JUnit 4 knows, suites, as we used to them, are history– they’ve been replaced with annotations. [...]

  3. on 27 Sep 2007 at 12:25 pm Greg Finzer

    This is a great article. Categories are especially useful when your code base matches more closely with the database model than the domain model. Our current project is like this since we have generated most of our code and we are using a table-class to interact with NHibernate. We are using a tool to generate our NUnit tests as well.

    http://www.kellermansoftware.com/p-30-nunit-test-generator.aspx

  4. on 27 Sep 2007 at 3:09 pm Andy

    Thanks, Greg! This generator is slick.

  5. on 28 Sep 2007 at 4:17 pm Greg Finzer

    Thanks Andy, any feedback is appreciated. The next version of the NUnit Test Generator will have the ability to create min/max/null testing.