Catch2 / Google Test для C++: полное руководство с примерами

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

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

Начать курс

Введение: Что такое Catch2 и Google Test и зачем они нужны?

В современной разработке программного обеспечения на C++ тестирование — это не роскошь, а необходимость. Библиотеки для модульного тестирования (unit testing) позволяют разработчикам автоматически проверять, что отдельные компоненты программы (функции, классы, модули) работают корректно. Две самые популярные библиотеки для этой цели — Catch2 и Google Test (gtest).

Catch2 — это современная, легковесная и очень удобная библиотека для модульного тестирования. Её главная особенность — использование макросов, которые делают тесты читаемыми и похожими на обычный английский язык. Catch2 поддерживает Behaviour-Driven Development (BDD) стиль, автоматическую регистрацию тестов и не требует сложной конфигурации.

Google Test (gtest) — это мощная и зрелая библиотека от Google, которая является стандартом де-факто во многих крупных проектах. Она предлагает богатый набор assertion-макросов, механизмы для создания фикстур (test fixtures), параметризованные тесты и отличную интеграцию с системой сборки CMake.

Обе библиотеки решают одну и ту же задачу: позволяют писать тесты, которые автоматически запускаются и сообщают о результатах. Выбор между ними часто зависит от личных предпочтений, требований проекта или существующей инфраструктуры. В этой статье мы рассмотрим обе библиотеки, так как они очень похожи по концепции, но имеют различия в синтаксисе и API.

Установка

В отличие от Python (где используется pip), установка библиотек для C++ обычно происходит через менеджеры пакетов системы или через интеграцию с системой сборки (например, CMake). Рассмотрим оба варианта.

Установка Catch2

Способ 1: Через vcpkg (рекомендуется)

# Установите vcpkg, если он ещё не установлен
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh  # или .\bootstrap-vcpkg.bat на Windows

# Установите Catch2
./vcpkg install catch2

# Интеграция с CMake
./vcpkg integrate install

Способ 2: Header-only (самый простой)
Catch2 можно использовать как header-only библиотеку. Просто скачайте файл catch.hpp с официального репозитория и положите его в папку с проектом. Затем подключите его в коде:

#define CATCH_CONFIG_MAIN  // Эта строка должна быть только в одном .cpp файле
#include "catch.hpp"

Установка Google Test

Способ 1: Через vcpkg

./vcpkg install gtest
./vcpkg integrate install

Способ 2: Через CMake FetchContent (рекомендуется для проектов с CMake)
Добавьте в ваш CMakeLists.txt:

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

# Теперь вы можете использовать target_link_libraries для вашего тестового файла
add_executable(my_tests test.cpp)
target_link_libraries(my_tests GTest::gtest_main)

Быстрый старт с примером кода

Давайте напишем простую функцию и протестируем её с помощью обеих библиотек. Функция будет вычислять факториал числа.

Пример с Catch2

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

// Функция для тестирования
unsigned int factorial(unsigned int n) {
    if (n == 0) return 1;
    return n * factorial(n - 1);
}

// Тестовый кейс
TEST_CASE("Факториалы вычисляются корректно", "[factorial]") {
    REQUIRE(factorial(0) == 1);
    REQUIRE(factorial(1) == 1);
    REQUIRE(factorial(2) == 2);
    REQUIRE(factorial(3) == 6);
    REQUIRE(factorial(10) == 3628800);
}

// Ещё один тестовый кейс с секциями
TEST_CASE("Проверка граничных случаев", "[factorial][edge]") {
    SECTION("Факториал от 0") {
        REQUIRE(factorial(0) == 1);
    }
    SECTION("Факториал от 1") {
        REQUIRE(factorial(1) == 1);
    }
}

Пример с Google Test

#include <gtest/gtest.h>

// Функция для тестирования
unsigned int factorial(unsigned int n) {
    if (n == 0) return 1;
    return n * factorial(n - 1);
}

// Тестовый кейс
TEST(FactorialTest, HandlesZeroInput) {
    EXPECT_EQ(factorial(0), 1);
}

TEST(FactorialTest, HandlesPositiveInput) {
    EXPECT_EQ(factorial(1), 1);
    EXPECT_EQ(factorial(2), 2);
    EXPECT_EQ(factorial(3), 6);
    EXPECT_EQ(factorial(10), 3628800);
}

// Главная функция для запуска тестов
int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Основные методы и функции

Рассмотрим ключевые макросы и функции для обеих библиотек. Для Catch2 мы будем использовать макросы, для Google Test — макросы и функции.

1. TEST_CASE / TEST — Объявление тестового сценария

Что делает: Определяет новый тестовый кейс (группу тестов).

Параметры:
- Catch2: TEST_CASE("имя", "[тег1][тег2]")
- Google Test: TEST(TestSuiteName, TestName)

Пример:

// Catch2
TEST_CASE("Математические операции", "[math]") {
    // тесты
}

// Google Test
TEST(MathTest, Addition) {
    // тесты
}

2. REQUIRE / ASSERT_TRUE — Проверка условия (критическая)

Что делает: Проверяет, что условие истинно. Если условие ложно, тест немедленно прекращается (фатальная ошибка).

Параметры: Логическое выражение.

Пример:

// Catch2
REQUIRE(5 > 3);  // Тест пройдёт
REQUIRE(2 + 2 == 5); // Тест упадёт здесь

// Google Test
ASSERT_TRUE(5 > 3);
ASSERT_TRUE(2 + 2 == 5); // Тест упадёт здесь

Что делает: Проверяет условие. Если условие ложно, тест продолжается, но ошибка фиксируется.

Параметры: Логическое выражение.

Пример:

// Catch2
CHECK(5 > 3);  // Пройдёт
CHECK(2 + 2 == 5); // Ошибка, но тест продолжит выполнение

// Google Test
EXPECT_TRUE(5 > 3);
EXPECT_TRUE(2 + 2 == 5); // Ошибка, но тест продолжит выполнение

4. REQUIRE_EQ / EXPECT_EQ — Проверка равенства

Что делает: Проверяет, что два значения равны.

Параметры: REQUIRE_EQ(ожидаемое, фактическое)

Пример:

// Catch2
REQUIRE_EQ(4, 2 + 2); // Пройдёт
REQUIRE_EQ(5, 2 + 2); // Упадёт

// Google Test
EXPECT_EQ(4, 2 + 2);
ASSERT_EQ(5, 2 + 2); // Упадёт

5. REQUIRE_NE / EXPECT_NE — Проверка неравенства

Что делает: Проверяет, что два значения не равны.

Параметры: REQUIRE_NE(значение1, значение2)

Пример:

// Catch2
REQUIRE_NE(5, 3); // Пройдёт
REQUIRE_NE(4, 2 + 2); // Упадёт

// Google Test
EXPECT_NE(5, 3);
ASSERT_NE(4, 2 + 2); // Упадёт

6. REQUIRE_THROWS / EXPECT_THROW — Проверка исключений

Что делает: Проверяет, что код выбрасывает исключение определённого типа.

Параметры: REQUIRE_THROWS_AS(выражение, тип_исключения)

Пример:

#include <stdexcept>

void mightThrow(bool should) {
    if (should) throw std::runtime_error("Ошибка!");
}

// Catch2
TEST_CASE("Проверка исключений", "[exceptions]") {
    REQUIRE_THROWS_AS(mightThrow(true), std::runtime_error);
    REQUIRE_NOTHROW(mightThrow(false));
}

// Google Test
TEST(ExceptionTest, ThrowsRuntimeError) {
    EXPECT_THROW(mightThrow(true), std::runtime_error);
    EXPECT_NO_THROW(mightThrow(false));
}

7. SECTION / Test Fixtures (SetUp/TearDown) — Группировка тестов

Что делает: Позволяет структурировать тесты и выполнять общую инициализацию/очистку.

Параметры: В Catch2 — SECTION("имя"), в Google Test — класс, наследующий от ::testing::Test.

Пример (Catch2):

TEST_CASE("Работа с вектором", "[vector]") {
    std::vector<int> v = {1, 2, 3};

    SECTION("Проверка размера") {
        REQUIRE(v.size() == 3);
    }
    SECTION("Проверка доступа") {
        REQUIRE(v[0] == 1);
        REQUIRE(v[2] == 3);
    }
}

Пример (Google Test):

class VectorTest : public ::testing::Test {
protected:
    void SetUp() override {
        v = {1, 2, 3};
    }
    void TearDown() override {
        // Очистка, если нужна
    }
    std::vector<int> v;
};

TEST_F(VectorTest, SizeIsCorrect) {
    EXPECT_EQ(v.size(), 3);
}

TEST_F(VectorTest, AccessIsCorrect) {
    EXPECT_EQ(v[0], 1);
    EXPECT_EQ(v[2], 3);
}

8. GENERATE / ValuesIn — Параметризованные тесты

Что делает: Позволяет запускать один и тот же тест с разными входными данными.

Параметры: Список значений.

Пример (Catch2):

TEST_CASE("Параметризованный тест", "[param]") {
    auto data = GENERATE(1, 2, 3, 4, 5);
    REQUIRE(data < 10);
}

Пример (Google Test):

class ParamTest : public ::testing::TestWithParam<int> {};

TEST_P(ParamTest, IsLessThanTen) {
    int value = GetParam();
    EXPECT_LT(value, 10);
}

INSTANTIATE_TEST_SUITE_P(Values, ParamTest, ::testing::Values(1, 2, 3, 4, 5));

9. CHECK_THAT / EXPECT_THAT — Проверка с использованием Matchers

Что делает: Использует мощные сопоставители (matchers) для сложных проверок.

Параметры: Выражение и matcher.

Пример (Catch2):

#include <catch2/matchers/catch_matchers_string.hpp>

TEST_CASE("Проверка строк", "[string]") {
    std::string text = "Hello, World!";
    CHECK_THAT(text, Catch::Matchers::Contains                    

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