Google Test (GTest) setup with Microsoft Visual Studio for C++ unit testing


Introduction

[Links now include solution files for both 2008 and 2010 versions of Visual Studio]

I’m going to be nice with you today and save you some time. What I am about to describe to you took me the better part of two (half) workdays…. with a few hours sleep in between. Setting up Google Test with Microsoft Visual Studio can be a bit tricky, but if you really want unit testing for C++ in Visual Studio (and I hope you do) then this is for you. Most of the challenges can be overcome by configuring the compiler and linker correctly.

It’s worth mentioning that before settling on Google Test, or GTest as it’s also named, I did take a look at a few of the other unit test frameworks for C++, but I don’t think things seem any easier anywhere else. GTest doesn’t seem like a bad choice: its open source, used to test the Google Chromium Projects (Chrome) and more importantly, seems to be actively maintained.

There is a fair bit of documentation available on the project site, but sometimes you just want to get a feel for something before committing yourself to it. This posting should help you do that, but if you want more, the project has good documentation. In my quest for documentation I noticed several guides, a FAQ, a Wiki and a mailing list. In other words, there are good sources of information available if you choose to dive in.

Disclaimer

I suppose a disclaimer is in order for those wondering:

  • I only work with C++ in passing. It’s not something I do much of these days and my working knowledge of Microsoft Visual Studio for C++ is limited.
  • I used Visual Studio 2008 Profession Edition for this work. I also updated the project using Microsoft Visual Studio 2010 Professional Edition (see links below). Maybe the Express versions will work too?
  • I am not affiliated with Google in any way. The reason I am looking in to this particular framework is because I am currently maintaining some older C++ programs that I wrote 10 years ago. I want to introduce unit testing for them before making changes and GTest seems a good choice.

So, in this posting I want to share with you how I configured Visual Studio 2008 to work with the GTest framework. After spending a fair bit of time getting this to work, I want to write it all down while it’s still fresh in my mind.

The GTest binaries for unit testing

First thing’s first: you need to download the Google Test Framework. I use version 1.5.0 which seems to be the current stable release. I unpacked the GTest project to a folder named C:\Source\GTest-1.5.0\ which I then refer to from other projects in need of the unit testing library. I call this directory %GTest% in the text that follows. Be aware that I think I may have read that Google recommends adding the GTest project to your own solution and building them together with your own code, but this is how I do it for this sample project.

If you are coming from a Java world then this may be where you hit your first snag. It may be a bit different from what you have grown accustomed to with Eclipse, JUnit and all, but you will have to build the unit test binaries from the downloaded C++ source code. Yes, you will actually have to compile and build the GTest libraries yourself, but before you lose heart, let me add that it comes with project files for many popular C++ IDEs, Visual Studio being one of them (older version). In the msvc/ folder of the download you will find two Visual Studio solution files which VS 2008 will ask you to upgrade when you open them.

I had no trouble building the binaries. In fact, I can’t remember actually having to configure anything so don’t be put off by this step. However, there is an issue here: there are two solution files and you must choose the correct version to use with your project. The solution file with┬áthe -md suffix uses DLL versions of Microsoft runtime libraries, while the solution with no suffix uses static versions of the Microsoft runtime libraries. The important thing to note is that you must correctly set the C++ Code Generation setting for the Debug and Release configurations in your project to the exact same setting used when building GTest. If you experience linker problems somewhere down the line in your project then this might be the cause. Most of the trouble I have experienced while building has been due to this setting being incorrect. The project’s README file does a better job of explaining all this so be sure to have a look. For my code I am using the static versions of the runtime libraries, so for me that’s /MT for the Release configuration and /MTd for the Debug configuration. I use the GTest solution without the -md suffix.

In any case, if you plan on using both Debug and Release configurations in your own project then you should remember to also build the GTest solution for both Debug and Release configurations. Among other things, the Release configuration will build two files, gtest.lib and gtest_main.lib, and similarly, the Debug configuration will also build two files, namely gtestd.lib and gtest_maind.lib (notice the extra -d- character in the file names).

Project setup

Now that you have successfully generated the libraries for unit testing, we need to incorporate them in to a C++ project. The GTest documentation provided will show you some simple examples of how to create unit tests using the framework, but it won’t say much about how to set up a good project structure for unit testing. I guess, this is not to be expected since it could be very environment specific.

My preference is to avoid making the unit tests part of the resulting binary (EXE file), and I don’t want to have to restructure my existing project (too much) to add unit testing. I simply want to add unit tests to my project, but avoid making my existing project code aware that it’s now being unit tested. So, my solution is based on what I’ve grown accustomed to with Java development with Eclipse, or C# development with Visual Studio. Maybe this is also the norm in other C++ projects? The idea is to split the solution in to three separate projects:

  1. One project containing the base code which will function as a library for the others
  2. One project used for running main(), the application entry point, which makes calls to functionality in the library
  3. One project for running unit tests which also makes calls to the same library functionality. In GTest the main() function entry point can be optional if you use gtest_main.lib.

The screenshot below shows what this may look like in Visual Studio:

Solution view in Visual Studio 2008

This setup requires the BaseCode project to be built as a library (LIB) file. The two others projects will build as EXE files that both depend on the LIB file so their project’s dependencies must be set up to both individually depend on the BaseCode project. When attempting to build the solution using this project structure, these are the things to watch for:

  • The BaseCode project must be configured to build as library. For both configurations, Release and Debug, you must set the project’s Configuration Type to Static Library (.lib). It’s Code Generation must be set to Multi-threaded (/MT) for the Release configuration and Multi-threaded Debug (/MTd) for the Debug configuration (must be identical to the GTest project explained earlier).
  • The RunBaseCode project is used to create the EXE for the resulting application so it’s Configuration Type is set to Application (.exe) which is the default. It depends on the BaseCode library so it’s project dependency must be set to depend on the BaseCode project. The Code Generation should also be set as explained above.
  • The TestBaseCode project is also used to create an EXE, but only for running the test cases – it’s not something you ship. It also depends on the BaseCode library so it’s project dependency must be set to depend on the BaseCode project. As before, it’s Code Generation should be set as explained above.
  • Since the TestBaseCode project needs to run the unit tests it must refer to the GTest libraries. Of the three projects, it is the only project which needs this. Therefore, for both Release and Debug configurations, set the Additional Include Directory setting to refer to the %GTest%\include directory.
  • The TestBaseCode Release configuration’s Additional Library Directories setting should refer to the %GTest%\msvc\gtest\Release directory. The Additional Dependencies setting should list the libraries gtest.lib and gtest_main.lib. Similarly, for the Debug configuration the Additional Library Directories setting should refer to the %GTest%\msvc\gtest\Debug directory and the Additional Dependencies should list the libraries gtestd.lib and gtest_maind.lib (notice the extra -d- character in the file names). Of course, if you have set up you GTest libraries somewhere else then it you have to refer to these directories instead.
  • The Command Line setting for TestBaseCode‘s Post-Build Event can be set to “$(TargetDir)$(TargetFileName)” for both Release and Debug configurations. This will run the unit tests automatically and display the results in the Build output window after building the project.

If you are successful, the build output should look something like this:

Screenshot of the build log

You will notice that the unit tests are run automatically and results displayed. The build creates two EXE files as expected, one for the application and one for the unit tests:

Screenshot of running the code and tests

If you get this far you might also want to check out gtest-gbar project which is a graphical UI for the unit tests. It’s a simple, one-file .NET application. By pointing it at the unit test EXE file you can get output like this:

Screenshot of gtest-gbar

Closing

For simplification, I’m linking to the Visual Studio 2008 solution I used to create the example so you can have a look at my solution settings. If you are using Visual Studio 2010 then use this solution. Have a look, build it and see if it works for you! You will also need to download, build and refer to the GTest framework LIB files and include folder as described above. Tell me how you get on and what Visual Studio version you were using (2008, 2010, Express etc). Your feedback would be greatly appreciated!!

Now that I’ve got this set up the next step for me is to incorporate GTest unit testing in to my current C++ projects. There’s a lot to learn…

About these ads

38 thoughts on “Google Test (GTest) setup with Microsoft Visual Studio for C++ unit testing

  1. I’ve used it with Visual Studio 2010 and it’s nice to see the test results in the output pane. Thank you for making it clear and simple.

  2. Couldn’t get it to work following your instructions (various fails), but your solution works fine when I build it, so thanks very much!

  3. Thanks for the great walk-through. I got everything working for my project within an hour or so. There was only one glitch: testing a particular member function from my old project (now a .lib) did not work anymore from my new test project (the .exe). The reason: the particular member function creates a bunch of std::shared_ptr. The creation was done through std::make_shared, and I didn’t have to do new/delete explicitly before. All other member functions could be tested just fine.

    Did you ever successfully test functions creating a shared_ptr across a library boundary?

  4. Hey Lee… really fantastic walk-through. worked very first time. Do you have any plans to make advanced topics in future ? please keep up the good work.
    Thanks
    Abi

  5. Thank you! got gtest successfully working and ran my first unit test. Now I’m trying to incorporate googlemock (gmock) with this and I’m back to getting linking errors:

    For example:
    >msvcprtd.lib(MSVCP100D.dll) : error LNK2005: “public: virtual __thiscall std::basic_iostream<char,struct std::char_traits >::~basic_iostream<char,struct std::char_traits >(void)” (??1?$basic_iostream@DU?$char_traits@D@std@@@std@@UAE@XZ) already defined in gmock.lib(gtest-all.obj)
    …cut a lot linker errors…
    2>LINK : warning LNK4098: defaultlib ‘MSVCRTD’ conflicts with use of other libs; use /NODEFAULTLIB:library
    2>LINK : warning LNK4098: defaultlib ‘LIBCMTD’ conflicts with use of other libs; use /NODEFAULTLIB:library

    2>Hello.Tests.obj : error LNK2019: unresolved external symbol “public: virtual __thiscall Hello::~Hello(void)” (??1Hello@@UAE@XZ) referenced in function “private: virtual void __thiscall `anonymous namespace'::Hello_GetString_WhenCalled_LengthGreaterThanTen_Test::TestBody(void)” (?TestBody@Hello_GetString_WhenCalled_LengthGreaterThanTen_Test@?A0x1bc91c79@@EAEXXZ)

    Any ideas or posts about using gmock with gtest?

    • To answer my own question, I had googlemock built with Code Generation -> Runtime Library set to “Multi-threaded Debug (/MTd)” rather than “Multi-threaded Debug DLL (/MDd)” (which is what my project is set to). I changed that setting and rebuild googlemock and now all the “already defined” errors are gone. Also didn’t need gtest.lib because gmock.lib apparently includes it. Still working on that last error though…

  6. Thank you so much! Your instructions worked like magic.
    This is probably the most comfortable experience I have had integrating some major external library into Visual Studio

  7. An alternate command-string for the post-build event:
    start cmd.exe /k $(TARGETPATH)
    Launches a CMD window with the test executable, rather than dumping the output into the window. If for no other reason, to see the results in green or red. You do have to close the cmd window to complete the build, tho, which could be annoying.

  8. Hello Lee,

    I downloaded the solution for VS 2010 but I get the following error:

    LINK : fatal error LNK1104: cannot open file ‘gtestd.lib’

    Can you please help me out?

    Cheers

    Chintan

  9. Lee, thought you’d like to know your solution works great with google test 1.6.. Thought I’d also point out something that is probably quite obvious to the experienced c++ developer but tripped me up…

    If you are including a static library in visual studio (BaseCode), in addition to adding the “additional include directory”, and the “additional library directory”, you must add the BaseCode project under as a reference under the “framework and references.” (Visual Studio 2010) So that would apply to the Run and Test projects.

    Thanks for a great tutorial!!

  10. Pingback: Google Test in Visual Studio 2008 | La Vie est Belle

  11. Lee, this may be a dumb question but if your BaseCode is a dll, do you need to export every function that you plan to test?

      • If anyone else read this and had the same question… Talked to some colleagues about this. Best solution (and simple) I can arrive at is build all code into a static library. Build a dll using a very thin interface for dll entry points and linking in the static library. Then write tests against the functionality of the static library. If necessary write separate tests against the dll interface. This was pretty simple for my project and gives me the ability for great coverage without forcing exposure of the internals of the dll.

  12. Thanks, Lee!

    I did have to use the GTest CMake build solution for VS2010, and that produces debug libraries without the “d” suffix, but it’s still a great walkthrough!

  13. Pingback: Getting started about GTest/GoogleTest on Visual Studio 2012 | franklin gujunchao

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s