GoogleTest Using CMake

Introduction

GoogleTest is widely used for C++ unit testing and CMake is a popular build system for C++ projects.

In this blog post, I will quickly demonstrate how to add GoogleTest unit tests to a C++ project using CMake and run the tests using CTest.

GoogleTest Using CMake

In this example, we created a simple C++ math library project and added GoogleTest unit tests using CMake. The example could be found at GoogleTest-CMake-Examples on GitHub.

Project Layout

Normally, a C++ project layout could be organized as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.
├── CMakeLists.txt
├── docker
│ └── googletest.Dockerfile
├── examples
│ ├── CMakeLists.txt
│ └── math
│ ├── CMakeLists.txt
│ ├── include
│ │ └── math.hpp
│ ├── src
│ │ └── math.cpp
│ └── tests
│ ├── add_test
│ │ ├── add_test.cpp
│ │ └── CMakeLists.txt
│ ├── CMakeLists.txt
│ └── subtract_test
│ ├── CMakeLists.txt
│ └── subtract_test.cpp
├── LICENSE
└── README.md

Build Unit Tests

At the root level of the project, we need to add the following CMakeLists.txt file.

The installed GoogleTest package could be found using find_package(GTest REQUIRED).

The enable_testing() command is used to enable testing at the root level so that we could run all the tests at once using CTest.

CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cmake_minimum_required(VERSION 3.28)

project(GoogleTest-Examples VERSION 0.0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find GoogleTest
find_package(GTest REQUIRED)

# Enable testing at the root level so that we could run all the tests at once
enable_testing()

add_subdirectory(examples)

The GoogleTest C++ unit tests and CMakeLists.txt are straightforward to write.

add_test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <gtest/gtest.h>

#include "math.hpp"

TEST(AddTest1, BasicAssertions)
{
// Expect equality.
EXPECT_EQ(1 + 2, add(1, 2));
}

TEST(AddTest2, BasicAssertions)
{
// Expect equality.
EXPECT_EQ(3 + 4, add(3, 4));
}
CMakeLists.txt
1
2
3
4
5
6
7
8
cmake_minimum_required(VERSION 3.28)

find_package(GTest REQUIRED)

add_executable(add_test add_test.cpp)
target_link_libraries(add_test GTest::gtest GTest::gtest_main math)

add_test(AllAddTests add_test)

After all the unit tests have been created, we could build the project using CMake.

1
2
$ cmake -B build
$ cmake --build build --config Release --parallel

Run Unit Tests

At root of the build directory, we could see CTestTestfile.cmake which is the entry point for CTest to run all the tests.

1
2
3
$ ls build/
CMakeCache.txt cmake_install.cmake examples Testing
CMakeFiles CTestTestfile.cmake Makefile

To run all the tests, we could use the following command.

1
$ ctest --test-dir build/ --verbose

In our case, we could see the following output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
$ ctest --test-dir build/ --verbose
Internal ctest changing into directory: /mnt/build
UpdateCTestConfiguration from :/mnt/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/mnt/build/DartConfiguration.tcl
Test project /mnt/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
Start 1: AllAddTests

1: Test command: /mnt/build/examples/math/tests/add_test/add_test
1: Working Directory: /mnt/build/examples/math/tests/add_test
1: Test timeout computed to be: 10000000
1: Running main() from /tmp/googletest-1.15.2/googletest/src/gtest_main.cc
1: [==========] Running 2 tests from 2 test suites.
1: [----------] Global test environment set-up.
1: [----------] 1 test from AddTest1
1: [ RUN ] AddTest1.BasicAssertions
1: [ OK ] AddTest1.BasicAssertions (0 ms)
1: [----------] 1 test from AddTest1 (0 ms total)
1:
1: [----------] 1 test from AddTest2
1: [ RUN ] AddTest2.BasicAssertions
1: [ OK ] AddTest2.BasicAssertions (0 ms)
1: [----------] 1 test from AddTest2 (0 ms total)
1:
1: [----------] Global test environment tear-down
1: [==========] 2 tests from 2 test suites ran. (0 ms total)
1: [ PASSED ] 2 tests.
1/2 Test #1: AllAddTests ...................... Passed 0.02 sec
test 2
Start 2: AllSubtractTests

2: Test command: /mnt/build/examples/math/tests/subtract_test/subtract_test
2: Working Directory: /mnt/build/examples/math/tests/subtract_test
2: Test timeout computed to be: 10000000
2: Running main() from /tmp/googletest-1.15.2/googletest/src/gtest_main.cc
2: [==========] Running 2 tests from 2 test suites.
2: [----------] Global test environment set-up.
2: [----------] 1 test from SubtractTest1
2: [ RUN ] SubtractTest1.BasicAssertions
2: [ OK ] SubtractTest1.BasicAssertions (0 ms)
2: [----------] 1 test from SubtractTest1 (0 ms total)
2:
2: [----------] 1 test from SubtractTest2
2: [ RUN ] SubtractTest2.BasicAssertions
2: [ OK ] SubtractTest2.BasicAssertions (0 ms)
2: [----------] 1 test from SubtractTest2 (0 ms total)
2:
2: [----------] Global test environment tear-down
2: [==========] 2 tests from 2 test suites ran. (0 ms total)
2: [ PASSED ] 2 tests.
2/2 Test #2: AllSubtractTests ................. Passed 0.00 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) = 0.03 sec

References

Author

Lei Mao

Posted on

11-08-2024

Updated on

11-08-2024

Licensed under


Comments