views:

145

answers:

4

I thought it will be a common question so I searched for a while but couldn't find it.

I am about to start a new project (C#, .net 3.5) and I was thinking about where I should I write the unit test code. I can create a unit test project and write all code there, or I can write the unit test code with the "class under test" itself.

What do you recommend and why? Things to consider before choosing an approach (caveats?)?

EDIT: About writing unit-test code with "code under test": Removing the test code from production assembly isn't difficult I guess. Thats what conditional compilation is for. Right?

Just throwing this point because answers are rejecting the second option just because production assemblies would be fatty.

+17  A: 

Separate project, same solution. Use InternalsVisibleTo if you want to access internals from the test code.

Separating out test from production code:

  • makes it more obvious what's what
  • means you don't need dependencies on test frameworks in your production project
  • keeps your deployed code leaner
  • avoids including test data files in your deployment assembly

Keeping the code in the same solution:

  • keeps the test cycle quick
  • makes it easy to hop between production and test code
Jon Skeet
+ for InternalsVisibleTo attribute- you can see Microsoft using this a lot with their own code (at least I see it often in Reflector). One gotcha is often the documentation regarding the use of the attribute is incorrect. Here's an example- http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute%28VS.85%29.aspx
RichardOD
+3  A: 

I always create a separate project in where I write my TestFixtures. I do not want to litter my domain model (or whatever) with Test classes.
I do not want to distribute my tests to customers or users of my application, so therefore I put them in a separate project (which also leads to a separate assembly).

If you have the rare case that you want to test internal methods, you can use InternalsVisibleTo. If you have the very rare case that you want to test private methods, you can use this technique, as explained by Davy Brion.

Frederik Gheysels
I am NOT advocating writing unit test case with "code under test" but obviously you wouldn't include the test code in release build. Too easy to wrap in DEBUG region...
Hemant
That litters the source code imho.
Frederik Gheysels
Yeah! I do agree with that!
Hemant
+2  A: 

I prefer the first approach - separating to unit test to its own project. placing the unit tests within the test subject will make it dirty. furthermore, you don't necessarily want to distribute your project with the unit tests which will make your dll's bigger and possibly expose things that you don't want to expose to the end user.

most of the open source projects that I saw had a different projects for unit tests.

Moshe Levi
+2  A: 

You shoul place the unit tests in a seperate project.

You should also write them in a way, so that the SUT (System under Test) is not modified in a way to make unittests possible. I mean you should have no helper classes in you main project that exist "only" to support you tests.

Mixing test and production code is allways a bad plan, since you dont want to deliver all that extra code out to your clients. Keep the clear separation that another project offers.

I dont think the "keep the tests quick" argument is a really strong one. Make a clear cut... Testing code does not belong into a production enviroment IMHO...

Edit:

Comment on Edit above:

EDIT: About writing unit-test code with "code under test": Removing the test code from production assembly isn't difficult I guess. Thats what conditional compilation is for. Right?

Yes, it is "easy" to remove the code with a conditional compilation flag, but you wont have tested the final assembly you created, you only tested the assembly you created with the code inside it, then you recompile, creating a new,untested assembly and ship that one. Are you sure all your conditional flags are set 100% correct? I guess not, since you cant run the tests ;)

Heiko Hatzfeld
Excellent point about condition compilation. Thanks.
Hemant