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 buildingUnitTest
ensuresMyApp
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 linkingMyAppLib
UnitTest
, generating an executable that unit-testsMyAppLib
, also linkingMyAppLib
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 ofUnitTest
. Don't copy it of course. Just Add an existing item from the source folder ofMyApp
. Then you're done, but this
course has the downside thatfoo.cpp
is exposed to untoward editing within
theUnitTest
project.b) You can treat
foo.obj
just like a static library required for the linkage ofUnitTest
and follow steps 1) - 6) above. This means in particular at step 3) that the {Debug|Release} build ofUnitTest
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?
- Start with a clean directory:
/home/user/Desktop/projects/cpp/ # your project lives here
- 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
- Clone and add
googletest
to this directory:
└─cpp/
├─ googletest/
├─ CMakeLists.txt
├─ myfunctions.h
└─ mytests.cpp
- 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
- Contents of
myfunctions.h
for the example:
#ifndef _ADD_H
#define _ADD_H
int add(int a, int b)
{
return a + b;
}
#endif
- 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.
Building Google test itself
Using terminal:
- Go into the dir
/home/user/Desktop/projects/cpp/googletest
- Create
build/
inside it so that it looks like following:
└─cpp/googletest/
├─ build/
├─ ...other googletest files
cd build
- Run:
cmake -Dgtest_build_samples=ON -DCMAKE_BUILD_TYPE=Debug ..
make -j4
./googletest/sample1_unittest
Using VS-Code
- Open the
googletest
folder into VS Code - CMake extension will prompt for configuration, allow it
- You will see a
.vscode
directory. Inside it issettings.json
file, open it, and add the following to it:
"cmake.configureSettings": { "gtest_build_samples": "ON" }
- Build and run from the buttons in the bottom bar
Gtest test project link to other executable
Fixes:
- In SimpleCalc (debug), change
Project | Properties | General | Configuration type
toStatic Library
. This is why Release worked but Debug didn't. - For SimpleCalcWrapper, select
Project | Add reference...
and add SimpleCalc. This is why SimpleCalcWrapper didn't work. - For SimpleCalcTest (release), reset to default
Project | Properties | Linker | Advanced | Import Library
or SimpleCalcTest.exe will not compile. - 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. - 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. - For SimpleCalcWrapper, change
Project | Properties | C/C++ | Additional Include Directories
to$(SolutionDir)\SimpleCalc;%(AdditionalIncludeDirectories)
- 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:
- Build the solution/projects using
msbuild.exe
- 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:
- Get all testcases by running tests with
--gtest_list_tests
- Parse this data into your GUI
- Select test cases you want ro run
- Run test executable with option
--gtest_filter
Related Topics
Do I Have to Use Atomic<Bool> for "Exit" Bool Variable
C++ Concatenate Two Int Arrays into One Larger Array
"Step Over" When Debugging Multithreaded Programs in Visual Studio
Problems with Running Exe File Built with Visual Studio on Another Computer
How to Add Static Libraries to a Visual Studio Project
Convert a C++ Program to a Windows Service
Adding Static Libcurl to Code::Blocks Ide
Validate Authenticode Signature on Exe - C++ Without Capicom
How to Call Memcpy() and Memmove() with "Number of Bytes" Set to Zero
What Should a C++ Getter Return
How to Get Current CPU and Ram Usage in C++
How to Cast Simple Pointer to a Multidimensional-Array of Fixed Size
How to Clone Object in C++? or Is There Another Solution
Creating Array of Objects on the Stack and Heap