I wanted to get started with GoogleTest, and while searching for information, I came across this solution. I hope it can save you some time in your search.
Prerequisites
- A compatible operating system (e.g. Linux, macOS, Windows).
- A compatible C/C++ compiler
- CMake installed
Set up the project
To get started with GoogleTest, follow these steps to set up your project structure. Below is the folder tree we'll use and a brief explanation of each component:
Folder tree
googletest-boilerplate # Root directory of your project ├── CMakeLists.txt # Top-level CMake configuration file ├── src # Directory for source code │ ├── CMakeLists.txt # CMake configuration for source files │ ├── example.c # C source file with implementation code │ ├── example.h # Header file for example.c │ └── main.c # Main source file └── tests # Directory for test code ├── CMakeLists.txt # CMake configuration for test files ├── test_example.cpp # C++ file containing test cases └── test_main.cpp # C++ file that sets up GoogleTest and runs tests
Let’s start with the top-level CMakeLists.txt
file. This file configures the overall project and includes the subdirectories for source and test files. Here’s what the content will look like:
cmake_minimum_required(VERSION 3.14) # Minimum CMake version required project(googletest-boilerplate VERSION 0.1.0 LANGUAGES C CXX) # Project name and version, specifying C and C++ languages # Set the C and C++ standards set(CMAKE_C_STANDARD 11) # Set C standard to C11 set(CMAKE_C_STANDARD_REQUIRED True) # Ensure the C standard is required set(CMAKE_CXX_STANDARD 14) # Set C++ standard to C++14 set(CMAKE_CXX_STANDARD_REQUIRED True) # Ensure the C++ standard is required # Add subdirectories for source and test files add_subdirectory(src) # Includes the src directory add_subdirectory(tests) # Includes the tests directory include(CTest) # Include CTest module for testing support
Followed by tests/CMakeLists.txt
:
include(FetchContent) # Fetch GoogleTest FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.11.0 ) FetchContent_MakeAvailable(googletest) # Collect C++ source files recursively file(GLOB_RECURSE CXX_FILES "${CMAKE_CURRENT_LIST_DIR}/*.cpp") add_executable(unit_tests ${CXX_FILES}) # Link GoogleTest libraries target_link_libraries(unit_tests PRIVATE gtest_main ${PROJECT_NAME}_lib # Link to the main project library ) # Include directories (including where GoogleTest is built) target_include_directories(unit_tests PRIVATE ${gtest_SOURCE_DIR}/include) # Add include directories for tests to find headers target_include_directories(unit_tests PRIVATE ${PROJECT_SOURCE_DIR}/src) # Enable testing and discover tests # Discover and run tests include(GoogleTest) gtest_discover_tests(unit_tests)
Followed by src/CMakeList.txt
:
# Set the source directory to the current directory set(SRC_DIR ${CMAKE_CURRENT_LIST_DIR}) # Recursively collect all .c and .h files in the source directory file(GLOB_RECURSE SOURCES ${SRC_DIR}/*.c ${SRC_DIR}/*.h) # Define the name of the main project library using the project name with a "_lib" suffix set(MAIN_PROJECT_LIBNAME ${PROJECT_NAME}_lib) # Create a static library from the collected source files add_library(${MAIN_PROJECT_LIBNAME} STATIC ${SOURCES} ) # Add the main executable, specifying 'main.c' as the source file add_executable(${PROJECT_NAME} main.c) # Link the main executable with the static library created earlier target_link_libraries(${PROJECT_NAME} ${MAIN_PROJECT_LIBNAME})
On the CMake side, we're done. Let's quickly take a look at the sources now.
tests/test_main.cpp
#include <gtest/gtest.h> // Include the GoogleTest framework header // Dummy test // Define a test case named 'ExampleTest' and a test named 'test' TEST(ExampleTest, test) { EXPECT_EQ(true, true); } int main(int argc, char **argv) { // Initialize the GoogleTest framework with command-line arguments ::testing::InitGoogleTest(&argc, argv); // Run all the tests that have been defined and return the result return RUN_ALL_TESTS(); }
Note: In the code below, we can access the functions from example.h
because we included the src directory in the include path by specifying the following line in tests/CMakeLists.txt
(line 24):
target_include_directories(unit_tests PRIVATE ${PROJECT_SOURCE_DIR}/src)
If your project has a more complex directory structure, make sure to include the necessary directories in the include path to ensure proper access to header files.
tests/test_example.cpp
This will be the core test of our example. We'll call the functions inside the src
directory."
#include <gtest/gtest.h> #include "example.h" TEST(Example, sumTest) { uint32_t a = 10; uint32_t b = 20; EXPECT_EQ(a + b, sum(a, b)); } TEST(Example, squareTest) { uint32_t a = 10; EXPECT_EQ(a * a, square(a)); }
Source code files here below:
src/example.h
#pragma once #include <stdint.h> #ifdef __cplusplus extern "C" { #endif uint32_t sum(uint32_t a, uint32_t b); uint32_t square(uint32_t a); #ifdef __cplusplus } #endif
src/example.c
#include "example.h" uint32_t sum(uint32_t a, uint32_t b) { return a + b; } uint32_t square(uint32_t a) { return a*a; }
src/main.c
#include <stdio.h> int main(int argc, char** argv) { puts("Hello World!"); return 0; }
Compilation
To compile the project, follow these steps:
mkdir build cd build cmake .. cmake --build .
Run the test suite
After compiling, you can run the test suite using the following command:
./tests/unit_tests
Upon running the tests, you should see output similar to this:
[==========] Running 3 tests from 2 test suites. [----------] Global test environment set-up. [----------] 2 tests from Example [ RUN ] Example.sumTest [ OK ] Example.sumTest (0 ms) [ RUN ] Example.squareTest [ OK ] Example.squareTest (0 ms) [----------] 2 tests from Example (0 ms total) [----------] 1 test from ExampleTest [ RUN ] ExampleTest.test [ OK ] ExampleTest.test (0 ms) [----------] 1 test from ExampleTest (0 ms total) [----------] Global test environment tear-down [==========] 3 tests from 2 test suites ran. (0 ms total) [ PASSED ] 3 tests.
If you see a similar output, congratulations! Your setup is complete and the tests have passed successfully.
GitHub Repository
You can find the full project and source code on GitHub:
Feel free to clone the repository, explore the code, and contribute if you have any improvements or suggestions.
I hope this article has saved you some time searching for this information online.
Happy coding!
Top comments (1)
Since you have
include(CTest)
, I guess you can simply use the commandctest
to run the tests. Otherwise, this line is probably not necessary.Note that using
file(GLOB_RECURSE....
to get the source file of your project is generally considered as a bad practice, because it has several drawbacks. Instead, simply manually list your files by name. It's generally used when you can't manually enumerate the source files (eg: when files are generated and we can't predict their name easily).