views:

586

answers:

3

I haven't worked much with Visual Studio before. I've started a personal project in my spare time and I would like to use test-driven development since it has been a huge benefit to me in my Java development. I started this project quite a while ago, and I used CppUnit. I know there are probably other frameworks that are better, but this is what's already in place.

My Visual Stuido 2005 solution has 2 projects in it. It worked fine when the unit tests resided right alongside the application code. As the project grew in size, this became quite cumbersome and inelegant. I created a new project under my solution to house the unit tests (so it now has 3 projects). Everything went fine until I tried to build the solution. Everything compiled, but the unit test project failed to link. The output gives me 51 "unresolved external symbol" errors (LNK2019) for what seems like every function that my tests call.

As far as I can deduce, the problem is the directory structure that Visual Studio creates. Each project gets its own directory, and then below that are the object files and executables that get created. I think the problem is that, while the header files are properly included in each unit test, the linker can't find the cpp files because they are in a different directory. When it fails to find the implementation of a called function, it gives me the 2019 error.

Am I right in my evaluation of the problem? How can I fix it? Do I need to completely reorganize my projects or is it a simple configuration of the linker?

Thanks

+1  A: 

Yes, your evaluation sounds pretty good. Try this: In the solution explorer, right click the name of the project that contains your tests and choose "Project Dependencies". Put a check by every project that it is dependent on. That should set up the linker settings so it automatically can find the correct files.

Joe
Thanks for the suggestion, but unfortunately that was one of the first things I tried, and it didn't work.
+1  A: 

It sounds like the functions/classes that your test project is using from your main projects aren't exported. If code isn't exported, then nothing outside of the DLL/exe that the code lives in can reference it.

A common way that we handle this is to add a define to the project (in the project settings, go to Configuration Properties -> C/C++ -> Preprocessor, the first line has the defines) called something like PROJECTNAME_IMPL (make sure you do this for both Debug and Release configurations!). Then there is a header file (called ProjectNameExport.h) that anything exported includes, which contains something like the following:

#ifdef PROJECTNAME_IMPL
    #define PROJECTNAME_API __declspec(dllexport)
#else
    #define PROJECTNAME_API __declspec(dllimport)
#endif

Then, when defining a class (for example):

#include "ProjectNameExport.h"

class PROJECTNAME_API Foo
{
};

This has the result of exporting the class when the header file is included in a file within the project, and importing the class when the header file is included in a file in another project (that links to the first project, of course).

Andy
A: 

I always add the code to be tested to a separate static .lib file, and have the main application EXE and unit tests EXE depend on this. New code is added the .lib project, and the dependency support ensure the EXEs link with no errors. You need to make sure the EXE projects can find the .lib headers, but this will depend on your directory structure. You also have to watch that that the .lib and the EXEs are using the same CRT/MFC library (for example, when using the CRT you can statically link with it or use a DLL).

I find using libs in this way easier to maintain than adding files/headers to multiple projects.

I am using the Boost test framework but I would structure this the same no matter the TDD framework.

A good article on a similar setup can be found here:

http://www.codeproject.com/KB/architecture/Designing_Robust_Objects.aspx

Rob