What's New in Catch2 v3 Compared to v2: Key Changes and Migration Guide

Catch2 v3 replaces the single-header distribution with a static-library build and modular headers, requires C++14, improves compilation speed by roughly 80%, and reorganizes matchers into the Catch::Matchers namespace.

Catch2 v3 represents a major architectural redesign of the popular C++ testing framework, moving away from the header-only model that defined v2. According to the catchorg/Catch2 source code, this release prioritizes compilation performance and build-system integration while maintaining the expressive testing DSL developers expect. Understanding these structural changes is essential for teams planning to migrate existing test suites.

Static Library Distribution Replaces Header-Only Model

The most significant architectural change in Catch2 v3 is the shift from a pure header-only library to a compiled static library. In src/CMakeLists.txt, the build system now defines two primary targets: Catch2 (the core framework) and Catch2WithMain (which provides the main() function). This eliminates the massive compilation overhead incurred by including the entire framework in every translation unit.

When linking your test executable, you now target these CMake libraries directly:

add_executable(my_tests test_main.cpp)
target_link_libraries(my_tests PRIVATE Catch2WithMain)

This approach reduces compile times by approximately 80% compared to v2, as the framework is built once rather than parsed repeatedly.

Modular Header Structure

Split Headers vs. Monolithic Include

Catch2 v3 abandons the monolithic <catch2/catch.hpp> header in favor of a granular, split-header layout. The catch-all header is now <catch2/catch_all.hpp>, but the recommended practice is to include only what you need, such as <catch2/catch_test_macros.hpp> for basic testing functionality.

Key individual headers include:

Migration Example for Matchers and Generators

When using matchers, you must now include the specific headers and use the updated namespace:

#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>

TEST_CASE("String matching") {
    std::string s = "hello world";
    REQUIRE_THAT(s, Catch::Matchers::ContainsSubstring("world"));
}

Note that Contains has been renamed to ContainsSubstring, and all matchers now live under Catch::Matchers instead of nested internal namespaces.

For generators:

#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators_all.hpp>

TEST_CASE("Parametrised test") {
    int x = GENERATE(1, 2, 3);
    REQUIRE(x > 0);
}

Updated Language and Performance Requirements

Catch2 v3 raises the minimum C++ standard from C++11 to C++14, allowing the framework to utilize modern language features internally. This requirement is enforced in the CMake configuration and documented in docs/migrate-v2-to-v3.md.

The combination of the static-library model and split headers yields dramatic performance improvements. According to the release notes in docs/release-notes.md, v3 reduces inclusion overhead by roughly 80% compared to v2's single-header approach.

Breaking API Changes

Matcher Namespace Reorganization

All matchers have been moved to the Catch::Matchers namespace, creating a cleaner, flatter hierarchy. Additionally, the string matcher previously named Contains is now called ContainsSubstring to clarify its behavior.

Reporter Interface Overhaul

Custom reporters and listeners must adapt to new interfaces in v3. The event system and reporter APIs have been restructured, as detailed in the migration documentation. Projects implementing custom reporters will need to update their inheritance and method signatures to match the new interfaces.

CMake Integration and Package Manager Support

The CMake configuration in v3 generates catch2-config.cmake from the new layout, providing imported targets that work seamlessly with find_package(Catch2). This redesign makes the framework significantly more friendly to package managers like vcpkg and Conan, resolving distribution challenges inherent in the v2 single-header model.

Backward Compatibility via Amalgamated Header

For teams that require a single-file distribution, Catch2 v3 provides extras/catch_amalgamated.hpp. This file combines the entire framework into one header for backward compatibility, though it sacrifices the compilation speed benefits of the modular approach.

#include "catch_amalgamated.hpp"  // From extras/catch_amalgamated.hpp

Summary

  • Static library build: Catch2 v3 uses Catch2 and Catch2WithMain CMake targets instead of header-only inclusion.
  • Modular headers: Replace <catch2/catch.hpp> with specific headers like <catch2/catch_test_macros.hpp> or the aggregate <catch2/catch_all.hpp>.
  • C++14 requirement: The minimum language standard increased from C++11 to C++14.
  • Performance gains: Compilation speed improves by approximately 80% due to the static-library architecture.
  • Matcher changes: All matchers reside in Catch::Matchers, and Contains is now ContainsSubstring.
  • Amalgamated option: Use extras/catch_amalgamated.hpp for single-file compatibility.

Frequently Asked Questions

Is Catch2 v3 backward compatible with v2?

No, v3 introduces breaking changes that require code modifications. You must update include paths, matcher namespaces, and CMake targets. However, the testing macros (TEST_CASE, REQUIRE, etc.) remain syntactically identical, minimizing changes to actual test logic.

Do I need to change all my includes when migrating to v3?

Yes. The monolithic <catch2/catch.hpp> is removed in v3. You should include <catch2/catch_test_macros.hpp> for basic functionality, or <catch2/catch_all.hpp> for the convenience of a single include. Matchers and generators require their specific "all" headers or individual component headers.

Why did Catch2 switch from header-only to a static library?

The header-only model in v2 caused excessive compilation times because the entire framework was parsed in every translation unit. By compiling Catch2 as a static library defined in src/CMakeLists.txt, v3 reduces build overhead by roughly 80% while maintaining the same runtime behavior and API expressiveness.

Can I still use Catch2 v3 as a single-header library?

Yes, though it is not recommended for new projects. The file extras/catch_amalgamated.hpp provides a single-header distribution for backward compatibility, but you lose the compilation speed benefits of the modular, static-library approach.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →