Why variables in NUnit [TestFixture] classes should be static?


In a previous post Ben Lowery asked the question? Why is the collection in your test fixture class static? Here is the code from the previous post:

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

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

   // …
}

The reason that I do this is not so subtle, so let me explain. I think one of the biggest screw-ups that was made when we wrote NUnit V2.0 was to not create a new instance of the test fixture class for each contained test method. I say “we” but I think this one was my fault. I did not quite understand the reasoning in JUnit for creating a new instance of the test fixture for each test method. I look back now and see that reusing the instance for each test method allows someone to store a member variable from one test and use it another. This can introduce execution order dependencies which for this type of testing is an anti-pattern. It is much better to fully isolate each test method from the other. This requires that a new object be created for each test method.

Back to the question at hand… Since it would be difficult to change the way that NUnit works now, too many people would complain, I now make all of the member variables in test fixture classes static. It’s almost like truth in advertising. The result is that there is only one instance of this variable no matter how many test fixture objects are created. If the variable is static then someone who may not be familiar with how NUnit executes would not assume that a new one is created before each test is executed. This is the closest I can get to how JUnit works without changing the way that NUnit executes test methods.

For a great discussion of this topic see Martin Fowler’s bliki entry: JUnitNewInstance

Comments (25)

  1. Eric Newton says:

    Why not bite the bullet and fix it to do it right?

    I get all over Microsoft people about this…

  2. I’m not familar with NUnit at all, but I’ve assumed you’ve used a Test interface ala JUnit.

    If so, couldn’t you take the approach of introducing a second TestCase implementation? If it’s all interfaces, all you’ll need to modify would be the creation code.

  3. Cedric says:

    When did dependency of test methods become an anti-pattern? Anybody who does some serious testing (not just unit testing) needs to have test methods that depend on each other. That’s exactly what setUp() is, BTW, a method that needs to be invoked before any other test method. It’s not hard to see the importance of extending this concept to test methods themselves. TestNG implements this with dependent methods and "skips", see http://beust.com/testng for more details.

    If you want truly independent test methods, put them in different classes.

  4. I am no longer the admin of NUnit so I cannot fix it. I can recommend to Charlie that he fix it. A big problem would be backwards compatibility but that is Charlie’s decision.

  5. Cedric, I think we will agree to disagree. SetUp runs prior to every test being executed. That is different than test-1 storing a result that test-2 depends upon. That case is what I would call an anti-pattern for unit testing. In other forms of testing it can be useful but for the types of testing that I use NUnit for I would not want to do that.

  6. Darren Oakey says:

    Take a vote!

    – I think most people would rather you just fixed the problem. Anything it breaks should always have been broken anyway.

  7. Cedric says:

    James, I’m okay with invoking setUp() before each test method, but that’s redundant with reinstantiating the test each time and it forces you to use statics just to work around this "design decision".

    What would you think of a framework that forces you to declare all your fields static?

  8. Hi,

    Initially MbUnit would create a new fixture for each new test as in JUnit, but after facing a few problems, I finally went for the ‘1 fixture instance for all’ solution for a number of reasons (although it breaks the axiom of atomicity between tests):

    – TestFixtureSetUp and TestFixtureTearDown would have to be static which would seriously break exisiting code. This was the main why I move to ‘1 fixture’ solution. You cannot expect people to use static variables in TestFixtureSetup unless you explicity enforce it static. If you don’t enforce it static, people forget to use static variable and start to see some strange results, etc…

    – I kind like to write ‘this.’ on the editor and choose the variable from the intellissense. With static variables, you just loose this cool feature. It’s defail but after it’s all about details.

    Cheers,

    Peli.

  9. Thomas Eyde says:

    I really don’t see why it matter. A new coder will soon learn how the testfixtures work when he sees tests that run and tests which don’t. The static will not remove the potential dependencies.

  10. AndrewSeven says:

    There seems to be a reasonable concensus about how it should be, so why not make the change and keep a flag that allows people to keep the old behavior.

  11. James says:

    Yeah, I hate non-static nunit classes. Nice article!

  12. Google just alerted me about this thread… I invite everyone who cares how NUnit ought to do it to post on the nunit-developer list. That way, a number of folks who routinely put in their 2 cents about the direction of NUnit will get to see and comment on it.

    FWIW, I don’t see this as a difficult change to make, if people think it’s the right thing to do.

  13. 上个月,NUnit的作者James Newkirk 宣布推出 了新的单元测试框架, xUnit.net 。他列出了从以前的单元测试框架得到的教训后所做的改动: 每个测试方法都对应一个新对象实例。 为提高测试的隔离性

  14. I'll be back on LINQ architecture after the holidays, but in the meantime, I wanted to share some