Welcome to Atalasoft Community Sign in | Help

NUnit and TestDriven Differences in Unit Testing

One thing you should be aware of when working with NUnit and TestDriven.net is that they do not do the same things in the same order.

We have automated build scripts on our system that run NUnit to run the tests.  Developers have access to NUnit, but most of us use TestDriven as the ability to run one test in isolation is a great time saver, especially when debugging.  I also use TestDriven to run all of the tests in a file before I check in changes or changed tests.

Several times in the past release I've written tests that I've written that side-effect a common object.  When run by TestDriven, the tests are correct, when run by NUnit, they fail because of the change in order.

In theory, the best practice would be to isolate the common object into a common factory method and then each method should use that instead of the common object.  It turns out that two of the cases where this turned up, the theory would not have helped.

In one case, the overhead of creating this common object is significant and making more than one significantly affects the time to run the tests.  In a test suite that includes hundreds and hundeds of unit tests, when a single test contributes to more than 5% of the total execution time of all tests, you don't want to make it any worse.

In another case, the tests were operating on a static class property and since there was only one instance of the property, any changes in it get inherited by everybody else.

This would also be the case if you implement any singleton classes.

I fixed both of these cases by using a try/finally block around the test itself and used the finally to clean up any side-effects in the try block.

As a long time software engineer, I have a love/hate relationship with unit testing, but it's definitely balanced on the love side.  When you solidly adopt the practice of writing a unit test that reproduces a bug and then fixing the bug, you can practically eliminate recidivism.  In addition, a well-planned feature test will catch future bugs.  An example of this is that I tried to make as many ImageCommand descendents in dotImage serializable.  This provides us with a great deal of power in treating image processing commands as uniformly manipulable objects.  I wrote a unit test that went through all ImageCommands and serialized them and made sure that all public properties were serialized.  Then I made similar tests that check all the round trip values.

This unit test caught my own bugs of refactoring, but it also caught bugs in new ImageCommands as they were implemented.

ISerializable is programming by contract, and that's all well and good as long as the programmer is aware of the contract.
Published Thursday, August 03, 2006 11:40 AM by Steve Hawley


No Comments
Anonymous comments are disabled