I'm having trouble integrating googletest into my existing project. I put together a simple project to represent my project's structure:
Project Structure
CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
project(TestTester)
set(CMAKE_CXX_STANDARD 14)
include_directories(existing_source)
add_subdirectory(existing_source)
add_subdirectory(new_test_source)
existing_source/CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
project(Test_TestTester)
set(CMAKE_CXX_STANDARD 14)
add_executable(TestTester main.cpp existing.h)
new_test_source/CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
project(Test_TestTester)
set(CMAKE_CXX_STANDARD 14)
find_package(PkgConfig REQUIRED)
pkg_check_modules(gtest REQUIRED gtest>=1.8.1)
SET(CMAKE_CXX_FLAGS -pthread)
enable_testing()
include_directories(${gtest_INCLUDE_DIRS})
add_executable(Test_TestTester main_test.cpp ../existing_source/existing.h)
target_link_libraries(Test_TestTester ${gtest_LIBRARIES})
add_test(NAME Test COMMAND Test_TestTester)
existing_source/existing.h
#ifndef TESTTESTER_EXISTING_H
#define TESTTESTER_EXISTING_H
int sample() {
return 1;
}
#endif //TESTTESTER_EXISTING_H
existing_source/main.cpp
#include <iostream>
#include "existing.h"
int main() {
std::cout << "sample() output = " << sample() << std::endl;
return 0;
}
new_test_source/main_test.cpp
#include <gtest/gtest.h>
#include "../existing_source/existing.h"
TEST(SampleTestCase, TestOneIsOne) {
EXPECT_EQ(1, 1);
}
TEST(ExistingCodeTestCase, TestSample) {
EXPECT_EQ(1, sample());
}
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from %s\n", __FILE__);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Goal:
Building with CMake will create two executables, one, TestTester, and another called Test_TestTester (sorry for the odd name, it looks like I could have chosen a better project name!).
TestTester will be the main project executable which will run the code from existing_course/main.cpp and output sample() output = 1
.
Test_TestTester should be the unit tests from main_test.cpp which tests that 1 == 1
and 1 == sample()
. This should run when the project is built.
Attempts:
I've tried using CMake's add_subdirectory() to expose a second CMakeLists.txt in the test subdirectory which has its own add_executable() with the name of the test program, however I cannot find any output related to the test program. Using enable_testing() followed by add_test() is also failing to produce any changes.
Update:
I realized some problems and assumptions were wrong.
cmake --build ... --target all
) must be invoked to build the other executables.I updated the CMakeLists files with my changes. Using --target all
builds everything appropriately, but I still can't get the tests to run when the project is built.
Add a subdirectory to the build. Adds a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.
There's very little wrong with the specimen project you've posted.
It seems you've mistakenly assumed that:
add_test(NAME Test COMMAND Test_TestTester)
in your new_test_source/CMakeLists.txt
is all it takes to get your Test_TestTester
executed by make
.
In fact, as declared by the first line of the add_test
documentation:
Add a test to the project to be run by ctest(1).
your add_test
command only suffices to get Test_TestTester
run when,
after make
, you run ctest
in the build directory of the Test_TestTester
sub-project.
Furthermore, even this will only happen if you enable ctest
testing for that sub-project
by invoking enable_testing()
in new_test_source/CMakeLists.txt
, which you don't. You say you did
that later:
Using enable_testing() followed by add_test() is also failing to produce any changes.
But that's because you still haven't done anything but create tests that you can run with ctest
,
and still haven't run ctest
.
So assume I've got your specimen project in my working directory (which I have), and that
I've just changed new_test_source/CMakeLists.txt
by changing:
project(Test_TestTester)
to:
project(Test_TestTester)
enable_testing()
Then:
$ mkdir build
$ cd build
$ cmake ..
generates the build system, and:
$ make
Scanning dependencies of target TestTester
[ 25%] Building CXX object existing_source/CMakeFiles/TestTester.dir/main.cpp.o
[ 50%] Linking CXX executable TestTester
[ 50%] Built target TestTester
Scanning dependencies of target Test_TestTester
[ 75%] Building CXX object new_test_source/CMakeFiles/Test_TestTester.dir/main_test.cpp.o
[100%] Linking CXX executable Test_TestTester
[100%] Built target Test_TestTester
builds everything, and:
# We're still in `./build`
$ cd new_test_source/
$ ctest
Test project /home/imk/develop/so/scrap2/build/new_test_source
Start 1: Test
1/1 Test #1: Test ............................. Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.00 sec
runs your tests. The complete test log is saved at:
$ cat ./Testing/Temporary/LastTest.log
Start testing: Feb 12 19:23 GMT
----------------------------------------------------------
1/1 Testing: Test
1/1 Test: Test
Command: "/home/imk/develop/so/scrap2/build/new_test_source/Test_TestTester"
Directory: /home/imk/develop/so/scrap2/build/new_test_source
"Test" start time: Feb 12 19:23 GMT
Output:
----------------------------------------------------------
Running main() from /home/imk/develop/so/scrap2/new_test_source/main_test.cpp
[==========] Running 2 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from SampleTestCase
[ RUN ] SampleTestCase.TestOneIsOne
[ OK ] SampleTestCase.TestOneIsOne (0 ms)
[----------] 1 test from SampleTestCase (0 ms total)
[----------] 1 test from ExistingCodeTestCase
[ RUN ] ExistingCodeTestCase.TestSample
[ OK ] ExistingCodeTestCase.TestSample (0 ms)
[----------] 1 test from ExistingCodeTestCase (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 2 test suites ran. (0 ms total)
[ PASSED ] 2 tests.
<end of output>
Test time = 0.00 sec
----------------------------------------------------------
Test Passed.
"Test" end time: Feb 12 19:23 GMT
"Test" time elapsed: 00:00:00
----------------------------------------------------------
End testing: Feb 12 19:23 GMT
If you'd like to see all that on your console at the time when you run ctest
, you can run
it in verbose mode ctest -V
. Or if you'd like only to see the details if the
tests fail, ctest --output-on-failure
.
Everything's working as it should, and maybe you're happy with that, knowing how
it works. If you still want to your tests to be run automatically by make
- which
is not conventional - then you'll need to add a custom post-build command to the
Test_TestTester
target to run ctest
automatically. Just append, e.g.
add_custom_command(TARGET Test_TestTester
COMMENT "Run tests"
POST_BUILD COMMAND ctest ARGS --output-on-failure
)
to new_test_source/CMakeLists.txt
. Then the output of a clean make
is:
$ make
Scanning dependencies of target TestTester
[ 25%] Building CXX object existing_source/CMakeFiles/TestTester.dir/main.cpp.o
[ 50%] Linking CXX executable TestTester
[ 50%] Built target TestTester
Scanning dependencies of target Test_TestTester
[ 75%] Building CXX object new_test_source/CMakeFiles/Test_TestTester.dir/main_test.cpp.o
[100%] Linking CXX executable Test_TestTester
Run tests
Test project /home/imk/develop/so/scrap2/build/new_test_source
Start 1: Test
1/1 Test #1: Test ............................. Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.00 sec
[100%] Built target Test_TestTester
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With