How to Test an Exe with Google Test

How to test an EXE with Google Test?

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.

Visual Studio C++: Unit test exe project with google test?

Either put the functionality you want to test into a static library which is linked into both your test project and your MFC project, or put your files in both projects. The first is more complicated, but the second will cause you to compile everything twice....

Setting up GoogleTest to run all tests in one executable

It is unnecessary to have an executable per each file. Build one executable for all tests and learn the gtest option --gtest_filter. You can run each test individually:

all_tests --gtest_filter=Element.Test

Or you can run all Element tests like the macro add_test_l does it:

all_tests --gtest_filter=Element.*

More info about command line options is available:

all_tests --help

One of the useful commands:

all_tests --gtest_list_tests

How to run tests and debug Google Test project in VS Code?

  1. Start with a clean directory:
/home/user/Desktop/projects/cpp/ # your project lives here

  1. Add your cmake file(CMakeLists.txt), your source files, and test file. The directory now looks like this:
└─cpp/
├─ CMakeLists.txt
├─ myfunctions.h
└─ mytests.cpp

  1. Clone and add googletest to this directory:
└─cpp/
├─ googletest/
├─ CMakeLists.txt
├─ myfunctions.h
└─ mytests.cpp

  1. Open your CMakeLists.txt and enter the following:
cmake_minimum_required(VERSION 3.12) # version can be different

project(my_cpp_project) #name of your project

add_subdirectory(googletest) # add googletest subdirectory

include_directories(googletest/include) # this is so we can #include <gtest/gtest.h>

add_executable(mytests mytests.cpp) # add this executable

target_link_libraries(mytests PRIVATE gtest) # link google test to this executable

  1. Contents of myfunctions.h for the example:
#ifndef _ADD_H
#define _ADD_H

int add(int a, int b)
{
return a + b;
}

#endif

  1. Contents of mytests.cpp for the example:
#include <gtest/gtest.h>
#include "myfunctions.h"

TEST(myfunctions, add)
{
GTEST_ASSERT_EQ(add(10, 22), 32);
}

int main(int argc, char* argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

Now you just have to run the tests. There are multiple ways to do that.

In the terminal, create a build/ dir in cpp/:

mkdir build

Your directory should now look like this:

└─cpp/
├─ build/
├─ googletest/
├─ CMakeLists.txt
├─ myfunctions.h
└─ mytests.cpp

Next go into the build directory:

cd build

Then run:

cmake ..
make
./mytests

Alternative way:

  • Install the CMake Tools extension for VS Code
  • In the bottom bar, you can see the current target (in square brackets Build [mytest] and Run [mytest])you want to build / run:
  • Then just click the run button.

Sample Image



Building Google test itself

Using terminal:

  1. Go into the dir /home/user/Desktop/projects/cpp/googletest
  2. Create build/ inside it so that it looks like following:
└─cpp/googletest/
├─ build/
├─ ...other googletest files

  1. cd build
  2. Run: cmake -Dgtest_build_samples=ON -DCMAKE_BUILD_TYPE=Debug ..
  3. make -j4
  4. ./googletest/sample1_unittest

Using VS-Code

  1. Open the googletest folder into VS Code
  2. CMake extension will prompt for configuration, allow it
  3. You will see a .vscode directory. Inside it is settings.json file, open it, and add the following to it:
    "cmake.configureSettings": { "gtest_build_samples": "ON" }

  1. Build and run from the buttons in the bottom bar

Gtest test project link to other executable

Fixes:

  1. In SimpleCalc (debug), change Project | Properties | General | Configuration type to Static Library. This is why Release worked but Debug didn't.
  2. For SimpleCalcWrapper, select Project | Add reference... and add SimpleCalc. This is why SimpleCalcWrapper didn't work.
  3. For SimpleCalcTest (release), reset to default Project | Properties | Linker | Advanced | Import Library or SimpleCalcTest.exe will not compile.
  4. For SimpleCalcTest, change Project | Properties | C/C++ | Additional Include Directories to $(SolutionDir)\gtest\include;$(SolutionDir)\SimpleCalc;%(AdditionalIncludeDirectories). This will have them relative to the project.
  5. For SimpleCalcTest, change Project | Properties | Linker | Additional Library Directories to $(SolutionDir)\gtest;%(AdditionalLibraryDirectories) - you don't need SimpleCalc directory because the project is added to references.
  6. For SimpleCalcWrapper, change Project | Properties | C/C++ | Additional Include Directories to $(SolutionDir)\SimpleCalc;%(AdditionalIncludeDirectories)
  7. For SimpleCalcWrapper, reset to default Project | Properties | Linker | Additional Library Directories - you don't need SimpleCalc directory because the project is added to references.

Automated unit tests build and run on commandline with Visual Studio solution

Build

Building a Visual Studio solution/project through the command line is done with msbuild.exe. It works best to add the path of MSBuild to the PATH environment variable.

MSBuild is usually installed somewhere in the Visual Studio folders. E.g. on my machine the path is as follows:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe

Build the solution containing all your projects as follows:

msbuild.exe Example.sln

# Or if you want to build a release version or add additional arguments
msbuild.exe Example.sln /property:Configuration=Debug

See MSBuild CLI Docs for more options.

Side Note: Jenkins has a msbuild plugin you can use with a build step called "Build a Visual Studio project or solution using MSBuild" (Important: this does not install MSBuild, it only provides a GUI to use MSBuild in a build plan).

Run Tests

To run the tests you have two options:

  • Run each project's executable in your build pipeline and the executable's exit code will indicate the success/failure of the unit tests for that project. However, you will need to call each executable separately; or
  • Use the vstest.console.exe in combination with the Google Test Adapter

You can use the Google Test Adapter the same way in which Visual Studio uses it when you click Test -> Run -> All tests to discover & execute tests in your projects.

In my environment, vstest.console.exe is located here:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\TestPlatform\vstest.console.exe

You also need to provide the path to the test adaptor. Then execute all the tests as follows:

# Assuming vstext.console.exe is included in the PATH
# and the current working directory is the relevant project executable
# output folder:
vstest.console.exe Project1.exe Project2.exe Project3.exe /TestAdapterPath:"<path to adapter>"

Once again the path is hidden somewhere in the Visual Studio Folders. I found it through searching for GoogleTestAdapter.TestAdapter.dll. On my machine it is located in:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\drknwe51.xnq

Conclusion

Thus, an automated way to build and run GoogleTest unit tests, which are split over multiple projects, with the commandline can be performed in these two steps:

  1. Build the solution/projects using msbuild.exe
  2. Run the tests using vtest.console.exe in combination with the Google Test Adapter

How to run specific test cases in GoogleTest

You could use advanced options to run Google tests.

To run only some unit tests you could use --gtest_filter=Test_Cases1* command line option with value that accepts the * and ? wildcards for matching with multiple tests. I think it will solve your problem.

UPD:

Well, the question was how to run specific test cases. Integration of gtest with your GUI is another thing, which I can't really comment, because you didn't provide details of your approach. However I believe the following approach might be a good start:

  1. Get all testcases by running tests with --gtest_list_tests
  2. Parse this data into your GUI
  3. Select test cases you want ro run
  4. Run test executable with option --gtest_filter


Related Topics



Leave a reply



Submit