
Google Test (gtest) обеспечивает надежный каркас для модульного тестирования C++ проектов, позволяя интегрировать тесты на ранних этапах разработки. Для эффективного использования gtest в проекте с CMake важно настроить зависимость как внешнюю библиотеку и корректно определить цели сборки.
Первый шаг – подключение gtest через механизм FetchContent. В CMakeLists.txt необходимо использовать команду FetchContent_Declare с указанием репозитория Google Test и конкретной версии. Это обеспечивает стабильность сборки и упрощает обновление тестового фреймворка без ручного скачивания исходников.
После загрузки исходников gtest следует определить отдельную цель тестов с помощью add_executable и привязать к ней библиотеки gtest и gtest_main через target_link_libraries. Для обеспечения корректного включения заголовочных файлов используется target_include_directories с указанием пути к include директории gtest. Такой подход позволяет изолировать тестовую сборку от основной, сохраняя гибкость управления зависимостями.
Оптимизация сборки достигается активацией опции gtest_force_shared_crt и установки BUILD_GMOCK и BUILD_GTEST в значение ON. Это исключает конфликты с компиляторскими настройками проекта и гарантирует совместимость с различными версиями CMake и компиляторов.
Внедрение gtest через CMake с точной конфигурацией целей и зависимостей позволяет создать масштабируемую тестовую среду, которая легко расширяется при добавлении новых модулей и упрощает интеграцию с CI/CD пайплайнами.
Подключение gtest к проекту с использованием CMake
Для интеграции Google Test в проект на CMake рекомендуется использовать встроенный механизм FetchContent. В CMakeLists.txt добавьте вызовы `include(FetchContent)` и `FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/tags/release-1.15.0.zip)`, после чего `FetchContent_MakeAvailable(googletest)` обеспечит загрузку и сборку gtest при конфигурации проекта.
Создайте отдельную директорию `tests` и определите там CMake-файл для тестов. Используйте `add_executable(test_suite test_main.cpp test_module.cpp)` и подключите gtest через `target_link_libraries(test_suite gtest_main gtest pthread)`. Это обеспечит корректную линковку и возможность запуска тестов командой `ctest`.
Для поддержки автоматической генерации тестов можно включить флаг `gtest_discover_tests` из модуля `GoogleTest`. В CMake добавьте `enable_testing()` и затем `include(GoogleTest)` с вызовом `gtest_discover_tests(test_suite)`. Это позволяет CTest автоматически находить все тестовые функции без ручного их перечисления.
Для многоплатформенных проектов используйте условные проверки CMake: `if(WIN32)` или `if(UNIX)` для задания специфических опций компилятора и линкера. Это особенно важно, если проект использует статическую линковку gtest на Windows и динамическую на Linux. Такой подход обеспечивает стабильную работу тестов без необходимости ручного редактирования CMake-файлов под каждую ОС.
Установка Google Test через пакетный менеджер

После установки исходников необходимо сгенерировать статические библиотеки. Перейдите в директорию исходников /usr/src/gtest и создайте папку сборки: mkdir build && cd build. Затем вызовите CMake и соберите библиотеки:
cmake ..make
Для проектов на Windows рекомендуется использовать vcpkg. Установка происходит через команду vcpkg install gtest. После завершения установки библиотеки автоматически помещаются в каталог installed, откуда их можно подключать в CMake с помощью find_package(GTest CONFIG REQUIRED).
На macOS Google Test проще всего подключить через Homebrew. Достаточно выполнить brew install googletest. После установки библиотеки располагаются в /usr/local/Cellar/googletest, а переменные CMake GTEST_ROOT и GTEST_LIBRARIES позволяют легко подключать Google Test к проекту.
Рекомендуется использовать фиксированные версии библиотек, чтобы избежать несовместимостей при обновлениях. В vcpkg можно указать версию пакета через vcpkg install gtest@[version], а в Homebrew – через brew extract и указание конкретного тега.
После успешной установки через пакетный менеджер интеграция с CMake сводится к добавлению find_package(GTest REQUIRED) в CMakeLists.txt, а затем включению целей GTest::gtest и GTest::gtest_main в target_link_libraries. Такой подход обеспечивает автоматическую настройку include-путей и зависимостей без ручного копирования файлов.
Добавление gtest как подмодуля Git в проект
Для начала в корневой каталог вашего проекта выполните команду git submodule add https://github.com/google/googletest.git extern/googletest. Это создаст папку extern/googletest с исходниками gtest и автоматически добавит информацию о подмодуле в .gitmodules.
После добавления подмодуля важно инициализировать его для локальной копии. Используйте git submodule update --init --recursive, чтобы загрузить все ветки и внутренние зависимости gtest. Без этого шагa сборка через CMake не сможет найти необходимые файлы заголовков и исходники.
В CMakeLists.txt проекта подключение подмодуля реализуется через add_subdirectory(extern/googletest). Рекомендуется указывать полный путь относительно корня проекта, чтобы сборка была воспроизводимой на любых машинах и не зависела от текущей рабочей директории.
Для упрощения сборки тестов используйте target_link_libraries(ваш_тестовый_таргет gtest gtest_main). Это автоматически добавляет все необходимые исходники gtest и устанавливает правильные флаги компиляции, включая поддержку C++11 и выше.
Если проект хранится в команде разработчиков, не забудьте добавить инструкции по обновлению подмодуля: git submodule update --remote --merge. Это позволит синхронизировать локальные копии gtest с последними изменениями официального репозитория без ручного вмешательства.
Для более строгого контроля версий можно зафиксировать commit gtest, используемый проектом. В .gitmodules укажите конкретный SHA-1, что исключит случайное обновление до несовместимой версии и обеспечит стабильность тестовой среды на всех этапах CI/CD.
Настройка CMakeLists.txt для сборки тестов

Для интеграции Google Test в проект первым делом необходимо подключить его как внешнюю зависимость. В CMakeLists.txt это делается через FetchContent или add_subdirectory. Рекомендуется использовать FetchContent для автоматической загрузки последней стабильной версии gtest:
«`cmake
include(FetchContent)
FetchContent_Declare(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.15.0
)
FetchContent_MakeAvailable(googletest)
Следующий шаг – создание отдельного исполняемого файла для тестов. Для этого используют add_executable с указанием всех исходников тестов. Желательно хранить их в папке tests, чтобы структура проекта оставалась чистой. Например:
«`cmake add_executable(unit_tests tests/test_main.cpp tests/test_math.cpp)«`
Важно корректно связать тестовый исполняемый файл с библиотеками проекта и gtest через target_link_libraries. Это обеспечит доступ тестов к основным функциям и классам проекта. Например:
«`cmake target_link_libraries(unit_tests PRIVATE mylib gtest gtest_main)«`
Для автоматизации запуска тестов используйте enable_testing и add_test. Это позволяет запускать все тесты командой ctest после сборки. Пример настройки:
«`cmake enable_testing() add_test(NAME math_tests COMMAND unit_tests)«`
Рекомендуется добавить опции компилятора -Wall -Wextra -Werror для тестов отдельно, чтобы ошибки и предупреждения не влияли на основную сборку. Использование target_compile_options(unit_tests PRIVATE …) позволяет контролировать строгость проверки только в тестовом окружении.
Подключение заголовочных файлов gtest к исходникам
Для интеграции Google Test с вашим проектом на CMake необходимо правильно настроить пути к заголовочным файлам. Обычно gtest располагается в отдельной папке, например third_party/googletest, где находятся директории include и src. Основные заголовочные файлы – gtest/gtest.h и gtest/gtest-spi.h.
В CMake важно использовать команду target_include_directories, чтобы указать путь к директории include. Рекомендуется указывать путь с опцией PRIVATE или INTERFACE, в зависимости от того, будут ли ваши исходники использовать gtest напрямую или нет.
Пример правильного подключения: target_include_directories(${PROJECT_NAME}_tests PRIVATE ${GTEST_SOURCE_DIR}/include). Здесь ${GTEST_SOURCE_DIR} – это переменная, указывающая на корень gtest, что позволяет избежать хардкода пути.
Если в проекте используется подмодуль Git для gtest, убедитесь, что переменная GTEST_SOURCE_DIR определяется до вызова add_executable и target_include_directories. Иначе сборка может завершиться ошибкой из-за отсутствия заголовочных файлов.
При использовании gmock подключение заголовочных файлов аналогично, но необходимо добавить директорию googlemock/include. Это важно, если ваши тесты применяют mock-объекты, иначе компилятор не найдет классы MockFunction и MockMethod.
Для крупных проектов с множеством тестов целесообразно создать отдельный CMake target, например tests_include, который инкапсулирует все include-пути gtest. После этого все тестовые executables можно подключать к tests_include через target_link_libraries без дублирования путей.
Наконец, проверяйте правильность подключения с помощью include_directories на уровне отдельных файлов только при необходимости. В большинстве случаев предпочтительнее работать через target_include_directories, чтобы сохранить модульность и изоляцию зависимостей.
Создание исполняемого файла тестов в CMake
Первый шаг при интеграции Google Test с CMake – определение исполняемого файла для тестов. Обычно его создают отдельно от основной сборки проекта, чтобы тесты не зависели от линковки производственного кода. В CMake это реализуется с помощью команды add_executable, где указываются исходники тестов и необходимые заголовочные файлы.
Рекомендуется держать тестовые файлы в отдельной директории, например tests/. Для каждого модуля проекта создайте соответствующий тестовый файл с именем по шаблону test_<имя_модуля>.cpp. Такой подход упрощает расширение набора тестов без изменения CMakeLists.
После объявления исполняемого файла необходимо подключить библиотеку Google Test. Если GTest добавлен через FetchContent, подключение происходит командой target_link_libraries:
| Команда | Назначение |
|---|---|
| add_executable(tests tests/test_main.cpp tests/test_module.cpp) | Создает исполняемый файл с тестами |
| target_link_libraries(tests gtest gtest_main) | Линкует Google Test к тестовому исполняемому файлу |
| target_include_directories(tests PRIVATE ${PROJECT_SOURCE_DIR}/include) | Добавляет путь к заголовочным файлам проекта |
Для удобства запуска тестов из командной строки включите опцию enable_testing() в корневом CMakeLists и используйте add_test для регистрации исполняемого файла:
enable_testing()
add_test(NAME all_tests COMMAND tests)
Важно учитывать зависимости тестов от внешних библиотек. Если модуль использует сторонние библиотеки, их необходимо явно линковать с тестовым исполняемым файлом через target_link_libraries, иначе сборка завершится ошибкой компоновки.
При больших проектах полезно разбивать тесты на несколько исполняемых файлов, например unit_tests, integration_tests. Это ускоряет локальную сборку и позволяет запускать только нужные группы тестов без полной компиляции всего тестового набора.
Настройка автоматического запуска тестов через CTest
Для интеграции Google Test с CTest необходимо сначала убедиться, что каждая тестовая цель добавлена с помощью команды add_executable и зарегистрирована через add_test. Например, после создания тестового исполняемого файла my_tests следует прописать: add_test(NAME MyTests COMMAND my_tests). Это позволит CTest идентифицировать тесты и включать их в автоматический прогон.
Далее рекомендуется активировать поддержку CTest в корневом CMakeLists.txt через enable_testing(). Без этой команды команды ctest не будут видеть ни одной тестовой цели. Оптимальной практикой является создание отдельного каталога для сборки, чтобы тестовые бинарники не смешивались с исходниками.
Для комплексного управления тестами можно использовать свойства тестов через set_tests_properties. Например, задавать таймауты, повторные запуски при нестабильности, категории или условия пропуска. Практический пример:
set_tests_properties(MyTests PROPERTIES TIMEOUT 30)– ограничение выполнения одной тестовой группы до 30 секунд;set_tests_properties(MyTests PROPERTIES FAIL_REGULAR_EXPRESSION "Segmentation")– автоматическое выявление критических ошибок по регулярному выражению.
Это делает интеграцию с CTest гибкой и полностью управляемой через CMake.
Вопрос-ответ:
Как подключить библиотеку gtest к проекту на CMake без ручного скачивания исходников?
Для этого можно использовать встроенные возможности CMake. Начиная с версии 3.14, доступна команда FetchContent, которая позволяет автоматически загрузить gtest с GitHub и добавить его в проект. Нужно подключить FetchContent, указать репозиторий gtest, а затем использовать add_subdirectory для включения в сборку. После этого можно создавать тесты через add_executable и target_link_libraries с gtest_main.
Как организовать структуру проекта, чтобы тесты с gtest не мешали основной сборке?
Обычно создают отдельную папку, например tests, и помещают туда все файлы тестов. В CMake создают отдельный исполняемый файл для тестов с использованием add_executable, подключают к нему gtest и другие зависимости. Основной проект собирается отдельно, а тесты компилируются только при необходимости, что позволяет избежать конфликтов и ускоряет сборку основного приложения.
Можно ли использовать gtest с CMake на Windows и Linux одновременно без изменений в CMakeLists?
Да, если использовать кроссплатформенные механизмы CMake. FetchContent или ExternalProject позволяют автоматически подтягивать исходники и компилировать их для конкретной платформы. Главное — не прописывать платформо-специфичные пути к библиотеке и использовать target_link_libraries с правильными зависимостями. Таким образом один и тот же CMakeLists будет работать на разных системах.
Как подключить собственные вспомогательные функции к тестам gtest через CMake?
Если у вас есть набор утилит или вспомогательных классов, которые используют тесты, их можно оформить как отдельную библиотеку с add_library. Затем при создании тестового исполняемого файла подключаете эту библиотеку через target_link_libraries вместе с gtest. Это позволяет переиспользовать код между тестами, упрощает поддержку и делает CMakeLists более структурированным.
