Fog Creek Software
Discussion Board




A question on unit tests

We use NUnit here with our C# projects and we normally create a separate project that contains our unit tests, rather than including them in the main project itself.

This means that for our unit test project, we have to share all of the source code from the main project. No biggie, but I've begun to wonder if I should just include my unit test in my main projects itself.

How do other JOS'ers handle their unit tests? In the original project or create separate projects for them?

Thanks for any info.

Mark Hoffman
Thursday, July 31, 2003

The last major unit test I created was a separate project that just included many of the same files.

Joel Spolsky
Thursday, July 31, 2003

We use #ifdef to separate the unit test code from the other code. The unit test classes are separate classes, but they reside in the same assembly so they can test interfaces marked as "internal".

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, July 31, 2003

You can use the conditional attribute...

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfcsharpspec_17_4_2.asp

GiorgioG
Thursday, July 31, 2003

We prefer to keep to keep the unit tests for a component *with* the component's implementation - in the same source file.

Following on from a previous reply, we also use the preprocessor to ensure that the unit tests don't make it into the shipped builds of the product.

Our reason for this approach is that it is easy to find each component's tests when trawling through the codebase - this is a frequent occurrence, as a common question at our place is along the lines of: "What is the precise behaviour of an instance of such-and-such a class?".

The answer is often "I don't know exactly, let's have a look at its unit tests...".

The idea behind this is to replace extensive commenting within a component's interface with extensive unit testing of the component's interface. We want to force ourselves to read the unit tests to gain a better understanding of the confirmed behaviour of a component, not what a possibly unmaintained or unconfirmed comment says we *believe* it does.

Having said that, we do try to place comments in the unit tests to make their intent clearer: these are probably the most highly commented parts of our source codebase, and as I mentioned in a previous post, also the most highly reviewed / pair-programmed, as these form a potential achilles heel of this approach.

In addition, we still write summary comments that describe each component's interface as a whole: these tend to change much more slowly over the development life-cycle.

If you are involved in shipping a library API rather than a shrink-wrapped product, I imagine you would have to start to move from this 'unit-tests as documentation' idea to having extensive documentation of interfaces that belong to the published API, although your unit tests might serve as a starting point for explanatory code snippets for the end-user's benefit.

Anyway, I'll stop enthusing now as I'm drifting off-topic!

Gerard
Friday, August 01, 2003

I use a different approach for the web-based PHP application I develop.

All of the actual functionality in my application is in files in a separate sub-directory of the root development directory.  In a non-web app, the root development directory would hold my main(), as well as files for OS hooks.  But they would all call functions in this sub-directory (called "functions/" in my case).  *All* significant functionality is implemented in code residing in the functions/ directory.

My Unit Tests are in another sub-directory under root ("tests/", oddly enough).  The test files just #include the appropriate files in the functions/ subdirectory.

For a big application, that may need to be complicated somewhat, but it works nicely for me.

Example:

/
/main.cpp
/MainWindow.cpp
/SettingsWindow.cpp
/functions/email.cpp
/functions/weapons.cpp
/functions/scooter.php
/tests/email.cpp
/tests/weapons/cpp
/tests/scooter.php

The Pedant, Brent P. Newhall
Friday, August 01, 2003

Brad, Giorgio: I like the idea of including the unit tests in the same module as the code; it allows testing interfaces which are marked "internal".

I see how you conditionally include the tests using #ifdef or a conditional attribute.

But how do you ensure that your testing framework (nunit.framework.dll) isn't referenced by your release build? I see no way to do that in Visual Studio.NET. Maybe you use NANT or maybe you manually remove the reference before compiling release (shudder)?

Nate Silva
Monday, August 04, 2003

Yes, another indication of the immaturity of the VS.NET build system. NAnt is your friend. :-D

Brad Wilson (dotnetguy.techieswithcats.com)
Friday, August 08, 2003

*  Recent Topics

*  Fog Creek Home