views:

55

answers:

3

For example:

// NUnit-like pseudo code (within a TestFixture)

Ctor()
{
 m_globalVar = getFoo();
}

[Test]
Create()
{
 a(m_globalVar)
}

[Test]
Delete()
{
 // depends on Create being run
 b(m_globalVar)
}

… or…

// NUnit-like pseudo code (within a TestFixture)

[Test]
CreateAndDelete()
{
 Foo foo = getFoo(); 
 a(foo);

 // depends on Create being run
 b(foo);
}

… I’m going with the later, and assuming that the answer to my question is:

No, at least not with NUnit, because according to the NUnit manual:

The constructor should not have any side effects, since NUnit may construct the class multiple times in the course of a session.

... also, can I assume it's bad practice in general? Since tests can usually be run separately. So the result of Create may never be cleaned up by Delete.

+6  A: 

Yes, it is bad practice. In all unit test frameworks I know, the execution order of test methods is not guaranteed, thus writing tests which depend on the execution order is explicitly discouraged.

As you also noted, if test B depends on the (side) effects of test A, either test A contains some common initialization code (which then should be moved into a common setup method instead), or the two tests are part of the same story, so they could be united (IMHO - some people stick to having a single assert per test method, so they would disagree with me on this), or test B should otherwise be made totally independent of test A regarding fixture setup.

Péter Török
I agree with this but not all do see TestNG http://testng.org/doc/index.html which is an improvement on jUnit in many ways but also allows dependent tests - especially see http://beust.com/weblog/2004/02/08/junit-pain/ for the authour's reasoning
Mark
@Mark, I am not familiar with TestNG, thanks for the link.
Péter Török
@Mark: The reasoning given in the second link is actually specious. For unit tests the database should be mocked anyway and so the cost of setup and teardown of resources is to be ignored, and for integration tests you can afford the expense (you also have to do things like putting the database into a known state and other things like that, which can have quite an impact in themselves).
Donal Fellows
@Donal - I agree - I thought I had better show there is a difference of opinion and with a major testing library on java
Mark
@Mark: I quite understand. I just happen to regard the argument on that page as being totally wrong-headed and missing the point. But then again it's only a point that you really get once you start trying to hunt down problems in a test suite where tests *aren't* isolated… Been there, done that, got the t-shirt a few times.
Donal Fellows
@Mark, now that I've read the discussion in the 2nd link, I agree with @Donal. Worrying about the cost of multiple object construction in unit tests is a strange and invalid argument - to me this actually looks as if some of those guys did not fully understand the concept of unit testing.
Péter Török
A: 

In general, it's good practice to make each of your tests test exactly one thing or one sequence of things. (They're different types of tests, but even so.) Except when you are testing the constructor or destructor themselves, they should be done as part of the test setup and teardown code, and not the tests themselves. It's OK to be inefficient about this; the important thing with a test is that it be clear exactly what is being tested, not that you minimize the number of auxiliary actions performed during the process.

Many testing harnesses also allow you to only run a subset of tests (minimally just one). This is great for when you're focussing in on a particular bug! But it does mean that the tests need to be written so as to have no dependencies or everything will be rather meaningless.

Personally, I'd put testing of constructors and destructors earlier in my test suite than testing of behavior of the constructed instances, but YMMV.

Donal Fellows
+1  A: 

Definately a bad idea. Unit tests should be lightweight, stateless, and have no dependencies on things such as file system, registry, etc.. This allows them to run quickly and to be less brittle.

If your tests require executing in a certain order, then you can't ever be sure (at least without investigation) whether a test has failed because of execution order or a problem with the code!

This will ultimately lead to a lack of confidence developing regarding your test suite and eventual abandonment.

Ben Cawley