Using google tests with CMake/Ctest with the new command gtest_discover_tests
Asked Answered
A

1

18

I am trying to use googletest with CMake/Ctest. I have several sources files for my tests (each one containing many TEST/TEST_F/... commands) which are located in several directories. I want that the tests related to a given source are executed in the same directory as their source file. Also, I prefer that the build process of a test source file is a test by itself. So I made something like:

file(GLOB_RECURSE test_srcs
     RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
     "tests/*.cpp")
foreach(test_src ${test_srcs}) 
  get_filename_component(test_dir ${test_src} DIRECTORY)
  get_filename_component(test_exe ${test_src} )NAME_WE)
  add_executable(${test_exe} EXCLUDE_FROM_ALL tests/gtest_main.cpp ${test_src})
  set_target_properties(${test_exe}                                       
    PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${test_dir}                                     
    )
  target_link_libraries(${test_exe} gtest)
  add_test(NAME build_${test_exe} COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target ${test_exe})
  set_tests_properties(build_${test_exe} PROPERTIES FIXTURES_SETUP ${test_exe})
  gtest_discover_tests(${test_exe}
    TEST_LIST list
    WORKING_DIRECTORY ${test_dir}
    PROPERTIES DEPENDS build_${test_exe}
    PROPERTIES FIXTURES_REQUIRED ${test_exe}
    )
endforeach()

But it seems that the dependencies I am trying to declare between the tests are not taken into account: the build of the tests does not necessarily occurs before the execution of the underlying tests...

If I use the old gtest_add_tests as in the following instead of gtest_discover_tests, it works:

gtest_add_tests(
  TARGET ${test_exe}
  SOURCES ${test_src}
  WORKING_DIRECTORY ${test_dir}
  TEST_LIST tlist
  )
set_tests_properties(${tlist} PROPERTIES FIXTURES_REQUIRED ${test_exe})

Am I missing something with gtest_discover_tests?

Afloat answered 14/6, 2018 at 16:0 Comment(0)
A
22

After having started the bounty, I re-started the research on my own. I found out, the simplest method out there is to have googletest installed system-wide.

So, first install the package. On Ubuntu 18.04, that was supt apt install googletest.

For some reason, I had to build the library (perhaps not necessary somehow though?):

cd /usr/src/googletest
mkdir bin && cd bin
cmake ..
make && make install

After that I have been able to compile and run a test case. My CMakeLists.txt testing section looks like this:

enable_testing()
find_package(GTest REQUIRED)
include(GoogleTest)

add_executable(tests tests/foo_test.cpp tests/bar_test.cpp)
target_link_libraries(tests GTest::GTest GTest::Main)
gtest_discover_tests(tests)

A minimal test case file looks like this in my project:

// tests/foo_test.cpp

#include "gtest/gtest.h"

TEST(Foo, Sum)
{
  EXPECT_EQ(2, 1 + 1);
}

Compiling is as easy as:

mkdir bin && cd bin
cmake ..
./tests
Aceves answered 26/11, 2019 at 22:26 Comment(5)
This is the best minimal example I've found on the internet so far about using CMake and GoogleTest. Most examples are really noisy with multiple download&install methods, sophisticated use cases and custom build flags.Triliteral
Thank you! If you found this useful, please do not forget to upvote.Aceves
I should add I got tripped by the find_package() not finding what it needed. That happened in Windows 7 using a manually compiled and installed GTest. Then everything worked by calling set(GTEST_ROOT "my/custom/gtest/install/dir" CACHE PATH "Path to googletest") before find_package(), as per the suggestion in this specific comment: Where to point find_package to find GTest? #702#issuecomment-340676202.Triliteral
For me, the problem was forgetting enable_testing(). Having defined that, ctest runs successfully.Exuviate
“For some reason, I had to build...”—a common google{test,mock} usage pattern on a *NIX-like system is compiling it directly into your test as sources, compiling gtest-all.cc (ditto gmock-all.cc) along with test sources into the test executable. The docs refers to this practice as "fused mode." The philosophy behind this is to introduce as few unknown dependencies into tests as feasible, and the compiler/ABI used to build a packaged library is one such dependency. This may explain why the package comes without a library. And thanks for the detailed answer!Grout

© 2022 - 2024 — McMap. All rights reserved.