Тестирование в C++: обзор фреймворков и инструментов (Google Test, Catch2, doctest)

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Тестирование в C++: фреймворки и инструменты

Качество кода на C++ — критический фактор для надёжности программного обеспечения. В отличие от языков с управляемой памятью, ошибки в C++ могут приводить к серьёзным сбоям, утечкам памяти и неопределённому поведению. Система модульного тестирования (unit-тестирования) позволяет выявлять дефекты на ранних этапах, облегчает рефакторинг и документирует поведение функций. В этой статье мы рассмотрим три популярных фреймворка для тестирования на C++: Google Test, Catch2 и doctest, а также инструменты для их интеграции в процесс разработки.

Зачем нужно тестирование в C++?

  • Безопасность при рефакторинге: тесты мгновенно сигнализируют о регрессиях.
  • Документация: читаемые тесты служат живыми примерами использования API.
  • Интеграция с CI: автоматический прогон тестов при каждом коммите.
  • Выявление неопределённого поведения: тесты с санитайзерами (AddressSanitizer, UndefinedBehaviorSanitizer).

1. Google Test (GTest)

Наиболее популярный фреймворк от Google. Поддерживает xUnit-стиль, богатый набор макросов утверждений (assertions), автоматическую регистрацию тестов, моки (через Google Mock) и параметризованные тесты.

Установка (через CMake FetchContent)

# CMakeLists.txt
include(FetchContent)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG release-1.12.1
)
FetchContent_MakeAvailable(googletest)

add_executable(my_tests test.cpp)
target_link_libraries(my_tests GTest::gtest_main)

Пример теста

#include <gtest/gtest.h>

int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

TEST(FactorialTest, HandlesZeroInput) {
    EXPECT_EQ(factorial(0), 1);
}

TEST(FactorialTest, HandlesPositiveInput) {
    EXPECT_EQ(factorial(5), 120);
    EXPECT_GT(factorial(3), 5);
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
  • TEST() — макрос для определения тестового случая.
  • EXPECT_EQ — проверка равенства (нефатальная).
  • ASSERT_* — фатальные проверки (прерывают тест при провале).

2. Catch2

Современный фреймворк с акцентом на читаемость и простоту. Поддерживает BDD-стиль (Given-When-Then), секции (разделение тестов на вложенные сценарии) и генерацию случайных данных. Не требует наследования от базовых классов.

Установка (single-header или через vcpkg)

# vcpkg
vcpkg install catch2

# CMake
find_package(Catch2 REQUIRED)
target_link_libraries(my_tests Catch2::Catch2)

Пример теста

#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>

int add(int a, int b) { return a + b; }

TEST_CASE("Addition works", "[math]") {
    REQUIRE(add(2, 2) == 4);
    CHECK(add(-1, 1) == 0);

    SECTION("With zero") {
        REQUIRE(add(0, 5) == 5);
    }
}

TEST_CASE("String concatenation", "[string]") {
    std::string result = std::string("Hello ") + "World";
    CHECK(result == "Hello World");
}
  • TEST_CASE — объявление теста с именем и тегами.
  • REQUIRE — фатальная проверка.
  • CHECK — нефатальная проверка.
  • SECTION — вложенный сценарий (каждая секция запускается из общего состояния).

3. Doctest

Лёгкая и быстрая альтернатива. Вдохновлён Catch2, но компилируется в 2-5 раз быстрее. Предназначен для проектов, где важна скорость сборки. Поддерживает заголовочный файл (header-only), макросы CHECK и REQUIRE, а также вывод в формате XML.

Установка (header-only)

# CMakeLists.txt
add_executable(test_doctest test.cpp)
target_include_directories(test_doctest PRIVATE /path/to/doctest/headers)
                
    
    

Рекомендаций