Testing

This section documents C++23 (ISO/IEC 14882:2024), as published by ISO/IEC JTC1/SC22/WG21 (wg21), verified against the freely available working draft N5046 (eel.is/c++draft) and cppreference.com.

This content was generated with the assistance of AI and should be verified against the working draft and cppreference.com before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

C++ has no single built-in test framework the way JUnit/pytest anchor Java/Python — GoogleTest and Catch2 are today’s two dominant third-party choices, both integrating with CMake’s ctest runner.

GoogleTest: Assertions and Fixtures

#include <gtest/gtest.h>

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

TEST(CalculatorTest, AddsTwoNumbers) {
    EXPECT_EQ(add(2, 3), 5);          // EXPECT_* reports a failure but keeps running the test
    ASSERT_EQ(add(-1, 1), 0);          // ASSERT_* aborts the current test immediately on failure
}

class DatabaseTest : public ::testing::Test {
protected:
    void SetUp() override { connection_ = openTestConnection(); }     // runs before EACH test
    void TearDown() override { connection_.close(); }                    // runs after EACH test
    Connection connection_;
};

TEST_F(DatabaseTest, InsertsARow) {         // TEST_F: uses the DatabaseTest fixture above
    EXPECT_TRUE(connection_.insert("row"));
}

GoogleTest: Parameterized Tests

Runs the same test body once per value in a supplied list, instead of hand-duplicating near-identical tests:

#include <gtest/gtest.h>

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

TEST_P(IsPrimeTest, RecognizesPrimes) {
    EXPECT_TRUE(isPrime(GetParam()));
}

INSTANTIATE_TEST_SUITE_P(SmallPrimes, IsPrimeTest, ::testing::Values(2, 3, 5, 7, 11, 13));

GoogleMock

Generates mock implementations of an interface, with expectations on how the mock is called:

#include <gmock/gmock.h>

class Repository {
public:
    virtual ~Repository() = default;
    virtual std::string findById(int id) = 0;
};

class MockRepository : public Repository {
public:
    MOCK_METHOD(std::string, findById, (int id), (override));
};

TEST(ServiceTest, LooksUpById) {
    MockRepository mock;
    EXPECT_CALL(mock, findById(42)).WillOnce(::testing::Return("Ada"));

    Service service(&mock);
    EXPECT_EQ(service.getName(42), "Ada");
}

Catch2: Sections, Matchers, Generators

Catch2’s SECTION shares setup code across multiple sub-tests without a fixture class, re-running the enclosing TEST_CASE once per leaf SECTION:

#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include <catch2/generators/catch_generators.hpp>

TEST_CASE("vector operations", "[vector]") {
    std::vector<int> v = {1, 2, 3};

    SECTION("push_back grows the vector") {
        v.push_back(4);
        REQUIRE(v.size() == 4);
    }
    SECTION("pop_back shrinks the vector") {   // setup above re-runs fresh for THIS section too
        v.pop_back();
        REQUIRE(v.size() == 2);
    }
}

TEST_CASE("string matchers") {
    std::string greeting = "Hello, World!";
    REQUIRE_THAT(greeting, Catch::Matchers::StartsWith("Hello"));
}

TEST_CASE("generated values") {
    int x = GENERATE(1, 2, 3);         // the whole TEST_CASE runs once per generated value
    REQUIRE(x > 0);
}

Boost.Test

Predates both GoogleTest and Catch2, still common in older/Boost-adjacent codebases:

#define BOOST_TEST_MODULE CalculatorTests
#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE(adds_two_numbers) {
    BOOST_CHECK_EQUAL(add(2, 3), 5);        // like EXPECT_*: reports failure, keeps running
    BOOST_REQUIRE_EQUAL(add(-1, 1), 0);      // like ASSERT_*: aborts the test on failure
}

CTest Integration

CMake’s built-in test runner discovers and runs tests registered via add_test (or GoogleTest’s own gtest_discover_tests helper, which registers each TEST/TEST_F individually):

enable_testing()
find_package(GTest REQUIRED)

add_executable(unit_tests calculator_test.cpp)
target_link_libraries(unit_tests PRIVATE GTest::gtest_main)

include(GoogleTest)
gtest_discover_tests(unit_tests)
ctest --output-on-failure
ctest -R CalculatorTest    # run only tests matching a name pattern

Testing constexpr Code with static_assert

Code that runs at compile time can be tested at compile time too — a static_assert failure fails the build itself, immediately, with no separate test binary to run:

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

static_assert(factorial(0) == 1);
static_assert(factorial(5) == 120);
static_assert(factorial(1) == 1);

This complements, rather than replaces, run-time tests — it verifies the constexpr path specifically, and gives immediate feedback during compilation for logic that’s meant to be evaluable at compile time in the first place.

See Also

  • C: Testing — assert-based harnesses and the C frameworks (Unity, CMocka, Check, Criterion).