views:

203

answers:

2

I have a Visual Studio 2005 C++ project, it is a console application.

I want to start getting bits of the code under a test harness but I've run into some issues that I don't know how to best handle.

I don't want most of my testing code to end up in the normal .exe in production so I thought would be best to create a separate project for my tests. First issue, how is this new project going to call into the rest of the code? Should I make my legacy code a .lib or .dll with a single entry point and create a separate project that calls the main of my legacy code?

Should I go for the ugly hack of putting all my tests in files that are entirely #ifdef TESTING so that the code doesn't end up in my production .exe? If so how should I conditionally load my testing framework? Use a separate Properties Configuration for testing?

I'm basically looking for any suggestions on how to go about getting a test harness on a legacy .exe project in Visual C++

A: 

I think having most of the code that is tested be in a library is best, but not necessarily practical in all cases.

One solution is to have a separate project configuration (e.g., Debug, Release and Test) and have your test code in separate files which are marked as "Excluded From Build" under the Debug and Release configurations. You can either have the simple code to initiate the tests within an #ifdef or have a stub version of the test runner that's included in non-Test builds.

Another option (though it's rather hack-ish) is to have your test code run from WinMain and your production code run from regular old main. When you build using the "Windows" subsystem your tests will run, and when you build for the Console subsystem your production code will run. I don't know off-hand whether the linker will drop the un-called test functions from the production build, though.

Tim Sylvester
+4  A: 

First, I'd strongly recommend Michael Feather's book "Working Effectively with Legacy Code". It's all about how to add automated unit tests to a legacy app that has no tests. If you're wondering "how do I even start testing this pile of code" then this book is for you.

Michael is also the author of CppUnit, an Open Source NUnit-like testing framework for C++ code. You can find it here: http://sourceforge.net/projects/cppunit/.

One quick-and-dirty way to add tests is to add a UnitTest configuration to your solution. This configuration would compile your code, but instead of linking it to your main.CPP, you exclude your main.cpp from the build and include UnitTestMain.cpp, where you would place the calls to execute the unit tests. You end up spending a lot of time including and excluding all the various testMyCode.cpp modules to the various configurations, though, and it gets tiring after a while. We found that developers didn't like that approach too much.

A better approach is to add a UnitTest project to your solution, dependent upon your main.vcproj. The UnitTest project would contain just your test code, and it would link your compiled myCode.obj modules. When you execute that solution, it would run the test harness instead of loading your main(). We actually placed a call to execute the test code as a post-build step, which automatically runs the unit tests as a part of the build.

Again, I highly recommend CppUnit. We use it for testing our main app and a lot (80+) of COM modules. If you use the CompilerOutputter to format the test results, it even generates Visual Studio compatible error messages that you can double-click to take you directly to the line of the failing test.

John Deters
Your 4th paragraph is exactly what I was looking for, I hadn't thought of linking directly to the .obj files of the other project.I have WEwLC up on my screen, also have CppUnitLite ready at hand.
thelsdj
That's an excellent idea. I also recomment CxxTest. http://gamesfromwithin.com/?p=29
Tim Sylvester