Dmitri Nesteruk Dmitri Nesteruk - 3 months ago 19
C++ Question

How to test an EXE with Google Test?

I have a C++ project in Visual Studio, and have added another project exclusively for testing. Both of these projects are EXEs (console apps). So how do I use the first project inside the second?

Just to clarify, the question here would be somewhat self-evident if the first project was a library that one could simply include in the second project but, being an EXE, this is where the problem lies.

Answer

Per your comments, you have a C++ console application (MyApp) for which you have developed some application-specific classes that you want to unit-test with googletest in Visual Studio. How?

As you say, if you wanted to unit-test a library the way to do it would be obvious. You would:

  • 1) Create a project to create a unit-testing application (UnitTest).
  • 2) Configure the include-search directories so that the compiler can find the library's headers.
  • 3) Configure the library-search directories so that the linker can find the library itself.
  • 4) Add the library itself to the linker inputs.
  • 5) Make the UnitTest project dependent on the library project, so that building UnitTest ensures MyApp is up-to-date.
  • 6) Code the UnitTest app per googletest docs.

But since the classes you want to unit-test are specific to MyApp, you don't have any library.

A drill-sergeant answer to that is: You don't have a library containing the classes you want to unit-test? So make one!

That way you use 3 projects:-

  • MyAppLib, generating library that contains all the functionality you want to unit-test.
  • MyApp, generating the same executable as at present, but linking MyAppLib
  • UnitTest, generating an executable that unit-tests MyAppLib, also linking MyAppLib

However if you don't like the drill-sergeant answer you can work around it.

From the usual build-system point of view (the one designed into Visual Studio), the important output of the MyApp project is the build-target - the .exe. The .obj files generated are just intermediate by-products. VS offers you no support for treating these by-products as automatic linker inputs of a dependent project, and if a dependent project was also an .exe of the same sort - as it is your case - then such automatic linkage would be impossible anyhow because the main entry point would be multiply defined.

But from the unit-testing point of view it's the other way round. The .exe is of no interest, whereas (some of) the .obj files wholly or partly contain the implementations of the classes you want to unit test. In the text-book case where class foo is defined in foo.h and implemented in foo.cpp, the object file foo.obj is needed in the linkage of UnitTest.

For simplicity, assume that MyApp employs just one application-specific class foo, defined in foo.h and implemented in foo.cpp. Then you have two options for building UnitTest.

  • a) You can add foo.cpp to the source files of UnitTest. Don't copy it of course. Just Add an existing item from the source folder of MyApp. Then you're done, but this course has the downside that foo.cpp is exposed to untoward editing within the UnitTest project.

  • b) You can treat foo.obj just like a static library required for the linkage of UnitTest and follow steps 1) - 6) above. This means in particular at step 3) that the {Debug|Release} build of UnitTest is configured with library-search directories that include \path\to\MyApp\{Debug|Release} (either in relative or absolute form).

In reality, for option b), there's very likely more than one .obj file from MyApp that you will have to link in UnitTest, and quite likely that their number will grow with time. Maintaining the right linkage of UnitTest could become a chore, and you might come to the conclusion that the drill-sergeant was right after all.