Refactoring: Introduce SetUp Method


Tests in a TestFixture share common initialization code.

Create a method in the TestFixture, move common initialization code to the method, and execute the method prior to each test.   

Before:

[Test]
public void
UponCreationCountIsZero()
{
   BookmarkCollection collection = new BookmarkCollection
();
   Assert
.AreEqual(0, collection.Count);
}

[Test]
public void
AddBookmarkCountIsIncremented()
{
   BookmarkCollection collection = new BookmarkCollection
();
   collection.Add(
“Label”, new Uri(http://example.com
));
   Assert
.AreEqual(1, collection.Count);
}

After the Refactoring:

[TestFixture]
public class
BookmarkCollectionFixture
{
   private static BookmarkCollection
collection;

   [SetUp]
   public void
BeforeTest()
   {
      collection =
new BookmarkCollection
();
   }

   [Test]
   public void
UponCreationCountIsZero()
   {
      Assert
.AreEqual(0, collection.Count);
   }

   [Test]
   public void
AddBookmarkCountIsIncremented()
   {
      collection.Add(
“Label”, new Uri(http://example.com
));
      Assert
.AreEqual(1, collection.Count);
   }
}

The common code in this case is the creation of the BookmarkCollection in each test method. That code is moved to the [SetUp] method. NUnit insures that the method is executed prior to each test being executed.

This example demonstrates the need to keep the test code as clean as the production code. This means that if you see duplication it is your job to remove it, even in the test code. As a side note, I do agree with Brian Button that doing this refactoring does reduce the communication of the test code. His reasoning is that after the refactoring I have to look at the [SetUp] method and the individual [Test] methods to understand the full extent of the tests. This example illustrates the trade-off between removing duplication and code communication. I am interested in hearing opinions on the trade-off in this example and your everyday experience.

Lastly, there is another refactoring, named Introduce TearDown Method which removes common clean-up code from the tests to a method that is executed after the tests are run.

Comments (16)

  1. JP says:

    Wouldn’t this refactoring introduce execution sequenc dependencies? If the first test to run was AddBookmarkCountIsIncremented the second test UponCreationCountIsZero would fail.

  2. The [SetUp] method is called prior to each test being executed. This results in a new collection being created prior to the execution of each test.

  3. Ben Lowery says:

    Here’s a simple one: why make the collection static?

  4. Darron says:

    I agree with Ben, I wouldn’t make the collection static until it was needed to make a test pass. This would seem to follow the "simple design" rule of doing the least you can do to make the test pass.

  5. Kelly Summerlin says:

    In this simple case it’s not hard to see the "intent" of the setup. But I have seen this taken to the extreme where the setup was doing way too much. In complex setup scenarios it’s often hard to find/see the intent of a setup method. What’s is it setting up? How is it going about doing it? All questions I find myself asking a lot.

    I’ve also seen setup code doing setup stuff for 5 test methods but the other 30 test methods don’t need that piece of the setup. In those cases I advocate having a private method that is called first for the 5 methods that must have that functionality.

  6. Darrell says:

    Yes it does reduce the communication of the method, but no more so than code-interception style AOP. I think the price to pay is small enough that it doesn’t matter, especially if your test fixture is small enough.

    Also, I’m sure later you’ll want to add a certain number of items to the collection for various testing reasons. I usually break that functionality out into a separate private method, which, when well-named, doesn’t reduce the communication of the test.

  7. Tony Chow says:

    BTW, if you mark a class with TextFixtureAttribute all public methods will be treated as tests, there’s no need to mark each individual method with TestAttribute. I don’t know why everybody keeps doing it; it’s just not necessary.

    Also, your example just doesn’t illustrate the benefits of SetUpAttribute very convincingly. It’s hardly inelegant to write one line of instantiation code for each test method; indeed it makes the logic of each test harder to decipher.

    In most real tests, common code is shared by only a subset of tests in a test class, and it is far most logical to use an old-fashioned private method, which can be referred to by name in the host method. Therefore I expect the SetUpAttribute to be of limited usefulness, if not a hinderance, to code readability.

  8. I recently wrote hundreds of tests to cover our legacy business tier code. I created a TestBase class, and inherited all my tests from this class. In my base class, I had a virtual [SetUp]Init() that could be overridden if need be in my test fixture.

    There was a good deal of setup involved for each test, mostly setting up user principal objects to flow through the tiers, and this worked out really well. This probably obfuscates the intent of the tests to an even greater degree, but I agree with Darrell that it’s a small price to pay.

    About small fixtures, I think this should be a best practice, if it’s not already. One thing I wish I’d done was reduce the number of tests per fixture. Especially when using TestDriven.NET and "Test w/ Debugger". If I had 20 tests in a fixture, test w/ debugger would test them al. I’d have rather tested fewer if I had to resort to the debugger.

    All in all it was a great experience, I identified lots of dead and broken code, and now have a good baseline for refactoring.

    Thanks James!

  9. Tony,

    I don’t think that’s entirely true. If you name your method Test(something) then, yes, it will be loaded into NUnit, regardless of the [Test] attribute. But to me this is just a feature of NUnit. Using the attribute seems like it’s a much better way to write a test.

  10. Tony Chow says:

    Actually, my bad, all my test methods are prefixed with the words "Test", and therefore would not need the TestAttribute.

  11. I was reading the release notes for the next version of NUnit and I see that it will become a configuration option to recognize methods by name (i.e. "Test") as opposed to the attribute.

  12. John Watson says:

    I did what Brendan mentioned above as well. I took it a step further and have testSetup and testTearDown stored procedures that are invoked from the base UnitTest class’ Setup and TearDown methods. testTearDown truncates tables and uses DBCC to reset the identities to 1. testSetup (hard coded right now) does a bunch of inserts to various tables.

    The net effect is that before each test is run the database is in a known, clean, predicatable state. Each project has a different DB schema and such so each testSetup has to be unique and different.

  13. Robert Angers says:

    I think that Refactoring at all level should be applied. Eliminating dupblicate code is a goal every programmer should tend to, that for Production or Test code.

    I belive that communication is an issue, but should not stop you from using it. It should be implicit that [SetUp] should be executed before every test. Since it not today common knowledge for everyone, does not mean we should not use it. It will become common knowledge. From that point on, the communication won’t be an issue anymore.

    It’s like Design Patterns. Will you not use them because not all programmers know them? Of course not. The strategy is to use them and transmit the knowledge to your team.