I want the c++ unit test written in google test displayed in the VS 2019 test explorer.
The tests are setup correctly and can be executed. The results are shown in the VS debug console/commandline-like window. No error messages besides the test dependent messages are shown.
I want start the tests form the test explorer and want to create test play lists.
I installed the google test adapter provided by the VS Installer. I followed guidelines and the suggested troubleshooting at TestAdapterForGoogleTest.
Does another way exist to get the google test to be dispalyed in the test explorer?
What are other known incompatibilities with google test and the VS test explorer?
I had the same problem as you. I'm having a main CMakeLists.txt, and another two CMakeLists.txt files in the subdirectories: one for the static library I'm testing and one for the test project itself.
For making sure the tests appear in the Test Explorer I had to move enable_testing() from the test subdirectory into the main CMakeLists.txt.
option(MY_PROJECT_TESTS "Build unit tests" ON)
if(MY_PROJECT_TESTS)
enable_testing()
add_subdirectory("test")
endif()
Then in the test subdirectory, I'm setting up the GoogleTest environment, and adding test the following way:
set(GTEST_DIR "googletest/googletest" CACHE PATH "gtest directory")
include(GoogleTest)
set(gtest_force_shared_crt OFF CACHE BOOL "" FORCE)
add_subdirectory("googletest")
project(My_project_test)
if (WIN32)
add_library(qtpcre STATIC IMPORTED)
set_target_properties(qtpcre PROPERTIES
IMPORTED_LOCATION_DEBUG ${QT5_DIR}/lib/qtpcre2d.lib
IMPORTED_LOCATION_RELEASE ${QT5_DIR}/lib/qtpcre2.lib
)
endif()
set(CommonTestLib
Qt5::Core
My_project
gtest_main
)
if (WIN32)
list(APPEND CommonTestLib
Ws2_32.lib
version.lib
Netapi32.lib
Userenv.lib
Crypt32.lib
Winmm.lib
qtpcre
)
endif()
add_executable (My_project_test test_main.cpp test_cases.cpp)
target_precompile_headers(My_project_test REUSE_FROM My_project)
target_link_libraries(My_project_test ${CommonTestLib})
gtest_add_tests(TARGET My_project_test EXTRA_ARGS --arg1 "${CMAKE_CURRENT_SOURCE_DIR}/data")
The very last line is important. Instead of gtest_add_tests, you can also use add_test. It needs different parameters but that works too when your goal is showing test cases in VS2019's Test Explorer.
The reason the above solution helped:
When you add enable_testing() to your top-level CMakeLists.txt file, it will generate a top-level CTestTestfile.cmake file in your build directory. This is needed by the Test Explorer to roll up all the test cases generated during the build process. If you've got a certain CMake hierarchy within your code structure you should have a similar one for CTest.
My top-level CTestTestfile.cmake file content:
# CMake generated Testfile for
# Source directory: C:/Projects/myproject
# Build directory: C:/Projects/myproject/out/build/x86-Debug
#
# This file includes the relevant testing commands required for
# testing this directory and lists subdirectories to be tested as well.
subdirs("test")
The lower level CTestTestfile.cmake file content:
# CMake generated Testfile for
# Source directory: C:/Projects/MyProject/test
# Build directory: C:/Projects/MyProject/out/build/x86-Debug/test
#
# This file includes the relevant testing commands required for
# testing this directory and lists subdirectories to be tested as well.
add_test(Environment.TestCommandLineArgument "C:/Projects/MyProject/out/build/x86-Debug/test/MyProject_test.exe" "--gtest_filter=Environment.TestCommandLineArgument" "--arg1" "C:/Projects/MyProject/test/data/")
set_tests_properties(Environment.TestCommandLineArgument PROPERTIES _BACKTRACE_TRIPLES "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.19/Modules/GoogleTest.cmake;380;add_test;C:/Projects/MyProject/test/CMakeLists.txt;38;gtest_add_tests;C:/Projects/MyProject/test/CMakeLists.txt;0;")
add_test(MyProjectExampleCreatorDevice.TestCreateExampleImage "C:/Projects/MyProject/out/build/x86-Debug/test/MyProject_test.exe" "--gtest_filter=MyProjectExampleCreatorDevice.TestCreateExampleImage" "--arg1" "C:/Projects/MyProject/test/data/")
set_tests_properties(MyProjectExampleCreatorDevice.TestCreateExampleImage PROPERTIES _BACKTRACE_TRIPLES "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.19/Modules/GoogleTest.cmake;380;add_test;C:/Projects/MyProject/test/CMakeLists.txt;38;gtest_add_tests;C:/Projects/MyProject/test/CMakeLists.txt;0;")
...
for me upgrading from 1.8.1.3 to 1.8.1.4 using nuget broke my project.
It switched
Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.3
to
Microsoft.googletest.v140.windesktop.msvcstl.dyn.rt-dyn.1.8.1.3\build\native\Microsoft.googletest.v140.windesktop.msvcstl.dyn.rt-dyn.targets"
revert back to the previous worked for me. (test explorer is now back) I think just making sure you use the static version as opposed to the dynamic should work as well.
There are multiple extensions that seem like they should be used.
If you follow the advice of https://learn.microsoft.com/en-us/visualstudio/test/how-to-use-google-test-for-cpp?view=vs-2022
you use the TestAdapterForGoogleTest from microsoft ? ()
There is another from Google. (Google test adapter). I have a project that used old versions of gtest. I installed this extension and things stopped working.
uninstall it and restart. rebuild and things seemed to work again.
Related
I am trying to integrate GTest with CMake as seamlessly as possible. But the default build type for my test projects are /MDd and GTest defaults to /MTd. I am manually changing GTest project properties to emit debug DLL.
But every time I make changes to my CMakeLists.txt, GTest defaults back to /MTd. How do I stop this?
You can define gtest_force_shared_crt to ON before including gtest to achieve this. You can either do this via the command line:
cmake . -Dgtest_force_shared_crt=ON
or in your CMakeLists.txt:
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
I think a better option is #Fraser's answer - in that case, cmake + gtest 'just work'.
It's worth mentioning that in order to override the internal gtest option setting, you need to put the variable in the cmake cache:
set( gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" )
If Ted Middleton's answer doesn't work, try to use FORCE:
set( gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" FORCE)
It worked for me
We solved the problem by bypassing GTest's own build system and compiling GTest as a CMake object library from its unity build source file gtest-all.cc:
# compile Google Test as an object library
add_library(gtest OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.6.0/src/gtest-all.cc")
set_property(TARGET gtest PROPERTY INCLUDE_DIRECTORIES
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.6.0"
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.6.0/include")
That way GTest will always be compiled with the same options that we use for the project.
A test executable that uses GTest can then be built in the following way:
add_executable(test_executable ${TESTS_SRC} $<TARGET_OBJECTS:gtest>)
add_test(NAME test COMMAND test_executable)
I am trying to setup google test with visual studio 2019 and cmake.
This is my CMakeFileLists.txt content:
cmake_minimum_required(VERSION 3.0)
project(test_me)
# GTest
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
# Unit Tests
# Add test cpp file
add_executable( runUnitTests tests.cpp)
# Link test executable against gtest & gtest_main
target_link_libraries(runUnitTests ${GTEST_BOTH_LIBRARIES})
add_test( runUnitTests runUnitTests )
My tests.cpp file looks like this:
#include <gtest/gtest.h>
TEST(ABC, TEST1) {
EXPECT_EQ(true, true);
}
TEST(ABC, TEST2) {
ASSERT_TRUE(2 == 2);
}
this minimal example is from another stackoverflow question:
CMake file for integrated Visual Studio unit testing
Thats what I get after I have build the application:
a single Test with the name runUnitTests. However in the picture of the answer from the question above I would expect to see the name of each test function. Something like this:
runUnitTests
- ABC
- TEST1
- TEST2
I have tested it with a new visual studio solution and added a google unit test project. Pasting the test functions into this projects results into this picture:
So this works fine. It must have something to do with the open a local folder method which I am using to handle my cmake project.
Here is a possible answer to your question:
cmake_minimum_required(VERSION 3.10)
project(test_me)
enable_testing()
find_package(GTest REQUIRED)
include(GoogleTest)
add_executable(runUnitTests tests.cpp)
target_link_libraries(runUnitTests GTest::GTest GTest::Main)
gtest_discover_tests(runUnitTests)
The command that discovers the full list of tests in your test binary is gtest_discover_tests(), and it is part of the GoogleTest CMake module (you can see the docs locally with cmake --help-module GoogleTest). This module has been introduced with CMake 3.9, but the command gtest_discover_tests() was only added in CMake 3.10. You should note, however, that if your test binary has many test cases, this will slow things down significantly.
I'm learning CMake through a C++ hobby project using Visual Studio 2017, and the way I have it set up, I have one folder for source code and one folder for test code. I build the source code as a static library, and build the test code as an executable (using Catch2). The problem I have now is that these are two separate targets, and whenever one or both of these targets are rebuilt I want to run the testing executable. Now I can find out how to run a post-build event using ADD_CUSTOM_COMMAND, but that only works for a single target. Putting multiple targets after "TARGET" leads to only the last target being used (I tested this), and duplicating the custom command can lead to the tests being run twice, and also it seems like poor code style. Is there any way to do this elegantly? My CMake file looks like this:
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.8)
project ("SheepyEngine")
set (CMAKE_CXX_STANDARD 17)
set (HEADER_FILES 3rdParty/CImg/CImg.h)
set (SOURCE_DIRECTORY Source)
set (TEST_DIRECTORY Test)
# Include sub-projects.
add_subdirectory ("Source")
add_subdirectory ("Test")
# Include libraries
include_directories (
"${CMAKE_CURRENT_LIST_DIR}/3rdParty/CImg"
"${CMAKE_CURRENT_LIST_DIR}/3rdParty/Catch2/single_include"
)
add_library (SheepyEngine STATIC
"${SOURCE_DIRECTORY}/Game.cpp"
"${SOURCE_DIRECTORY}/Game.h"
"${SOURCE_DIRECTORY}/GameObject.h"
${HEADER_FILES})
target_include_directories(SheepyEngine PRIVATE ${CMAKE_CURRENT_LIST_DIR}/3rdParty/CImg/)
add_executable(SheepyEngineTest "${TEST_DIRECTORY}/test.cpp" "3rdParty/Catch2/single_include/catch.hpp")
target_include_directories(SheepyEngineTest PRIVATE ${CMAKE_CURRENT_LIST_DIR}/3rdParty/Catch2/)
# TODO: Add tests and install targets if needed.
if(${RUN_TESTS})
ADD_CUSTOM_COMMAND(
TARGET SheepyEngineTest SheepyEngine
POST_BUILD
COMMAND ${CMAKE_CURRENT_LIST_DIR}/Build/Debug/SheepyEngineTest.exe
)
endif()
The SheepyTestProgram target needs to be dependent on SheepyEngine:
target_link_libraries(SheepyEngineTest SheepyEngine)
Then the target of add_custom_command will be just SheepyEngineTest (add_custom_command accepts only a single target).
So firstly I'm new to testing frameworks and relatively new to C++ but am trying to wrap my head around GoogleTest. I'm working on a Windows machine, running "Git for Windows" (MSYS) and MinGW whilst using Sublime Text as my code editor. I am using make as my build tool, although the more I learn about cmake and its cross-platform focus makes me wonder if I should switch to let cmake create makefiles for me. (that's probably a whole other question)
What I'm struggling to understand is what precisly to do with the GoogleTest source package. I realise that I need to build the source into the library and then include that when compiling my tests, but how should I go about doing this? Google includes a cmake build script that generates env/compilier specific makefiles for building. Should I be using this? I feel like if i do so and it blindly works a lot of what is happening under the hood will go over my head. The readme file isn't eliviating my issues, as it implies that i should be building the library and my tests each time i wish the run them. Shouldn't a library be a standalone archive that needs compiling only once? I'm confused and I'm sure its my fault but i'd appreciate it if someone shed some light on this process for me.
You should keep in mind that make will not rebuild gtest if you don't change anything in gtest source code.
Below is my approach to the usage of cmake and gtest for unit testing.
You can add gtest source code by adding it as subdirectory in the root CMakeLists.txt file.
add_subdirectory(${CMAKE_SOURCE_DIR}/thirdparty/gtest ${CMAKE_CURRENT_BINARY_DIR}/gtest)
include_directories(${CMAKE_SOURCE_DIR}/thirdparty/gtest/include ${CMAKE_SOURCE_DIR}/thirdparty/gtest)
My application consist of individual modules containing test folder for unit testing. I have the following boilerplate loop to add each test to the global scope.
file(GLOB TEST_SRC_FILES *.cpp)
foreach(TEST_SRC_PATH ${TEST_SRC_FILES})
#get filename of your test without extension
get_filename_component(TEST_NAME ${TEST_SRC_PATH} NAME_WE)
add_executable(${TEST_NAME} ${TEST_NAME})
#here you link the test executable with gtest
target_link_libraries(${TEST_NAME} gtest gtest_main)
#-----------------------------
# you can link here your test to external libraries
#-----------------------------
add_test(${TEST_NAME} ${TEST_NAME})
#this is a list of all tests
set(PROJECT_TEST_NAMES ${PROJECT_TEST_NAMES} ${TEST_NAME})
endforeach()
#This assigns the list of tests to a property. This make the list available from the root scope.
get_property(UNIT_TESTS GLOBAL PROPERTY UNIT_TESTS)
set(UNIT_TESTS ${UNIT_TESTS} ${PROJECT_TEST_NAMES})
set_property(GLOBAL PROPERTY UNIT_TESTS ${UNIT_TESTS} )
Finally, in the root scope, I add a custom target named check which runs ctest on my unit tests.
#-----------------------------
# Running unit tests
#-----------------------------
get_property(UNIT_TESTS GLOBAL PROPERTY UNIT_TESTS)
if(DEFINED UNIT_TESTS)
add_custom_target(check COMMAND ctest -VV
DEPENDS ${UNIT_TESTS})
endif()
When I run make check, it runs unit tests from all modules, whereas make compiles without tests.
I use QtCreator to open CMake project. Some directories apart from CMakeLists.txt contains only headers files *.h and for those directories QtCreator in the project tree view shows only CMakeLists.txt. How to fix that ? I need to see all project files from QtCreator.
Viewing project as a file system is not a solution at all cause your project editor settings for example would not apply.
And I do not like to add headers to executable target, cause they do not actually belong there. You effectively cripple the project file to work nicely with one particular IDE... not good.
The cleaner option IMHO would be:
FILE(GLOB_RECURSE LibFiles "include/*.hpp")
add_custom_target(headers SOURCES ${LibFiles})
As a bonus you get your includes shown in a separate folder.
(borrowed from https://cmake.org/pipermail/cmake/2012-August/051811.html)
I would suggest you switching your project view to File System. This would display a view where you could view any file you want:
You might want to split your project view into two by clicking the second to right button, if you still desire the Projects mode.
You should add header files to the list of your source files: add_executable(${Executable} ${Sources} ${headers})
You can use GLOB_RECURSE if have many header files:
FILE(GLOB_RECURSE INC_ALL "headers/*.h")
include_directories("headers")
add_executable(main "main.cpp" ${INC_ALL})
Don't forget to run CMake again (Build>Run Cmake).
Based on another thread asking the same question, I found a generic solution to the problem, working for all IDE's (at least tested with QtCreator and Visual Studio).
Can be found here : https://github.com/sauter-hq/cmake-ide-support
# \brief adds for the given target a fake executable targets which allows all
# headers and symbols to be shown in IDEs.
# \param target_name Which target properties should be added to the IDE support target.
function(target_add_ide_support target_name)
if (NOT TARGET ${target_name})
message(FATAL_ERROR "No target defined with name ${target_name}, cannot target_add_ide_support it.")
endif()
set (target_for_ide "${target_name}_ide_support")
if (NOT TARGET ${target_for_ide})
file(GLOB_RECURSE target_for_ide_srcs "*.h" "*.hpp" "*.hxx" "*.c" "*.cpp" "*.cxx")
add_executable(${target_for_ide} ${target_for_ide_srcs})
set_target_properties(${target_for_ide} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()
get_target_property(dirs ${target_name} INCLUDE_DIRECTORIES)
target_include_directories(${target_for_ide} PRIVATE ${dirs})
endfunction(target_add_ide_support)
Usage is then for any targets in the CMakeLists, add the following call (can be made in top-most CMakeLists.txt after all add_subdirectory :
include(add_ide_support.cmake)
target_add_ide_support(some-target)
You can try CMakeProjectManager2. Code to display all files already propagated to upstream as a proof of concept. Concept applied but code can't be applied as-is for some reasons. So, simple wait feature in upstream.
There is a closed bug report about this issue: CMake project shows no files.
In that particular case the issue was with the chosen generator, Ninja, which is not well supported by QtCreator.
Please change that to "CodeBlocks - Ninja". Creator needs the CodeBlocks extra generator.
You should see a warning about that when hovering the kit (and the kit should have a warning icon in front of its name).
Using CodeBlocks - Ninja solved it for me too.
Overall, it may help to try up a few generators...