Implementation:Duckdb Duckdb Catch Test Framework
| Knowledge Sources | |
|---|---|
| Domains | Testing, Third_Party |
| Last Updated | 2026-02-07 12:00 GMT |
Overview
Catch2 is a single-header C++ test framework bundled with DuckDB for writing and running unit tests.
Description
Catch2 (v2.13.7) is a multi-paradigm test framework for C++ that supports test-driven development (TDD) and behavior-driven development (BDD) styles. DuckDB vendors the single-header amalgamation of Catch2 as third_party/catch/catch.hpp. The framework provides a rich set of assertion macros (REQUIRE, CHECK), test organization primitives (TEST_CASE, SECTION), and matchers for expressive test conditions. DuckDB's vendored copy includes modifications to integrate with the duckdb_base_std namespace for smart pointers and stringstreams, as well as optional stack-trace printing on crashes via DUCKDB_DEBUG_STACKTRACE.
Usage
DuckDB uses Catch2 as the primary framework for its C++ unit test suite. All test executables that define CATCH_CONFIG_MAIN or CATCH_CONFIG_RUNNER link against this header to register and execute test cases. Individual test files use TEST_CASE to declare tests and SECTION to create nested sub-tests that share setup logic.
Code Reference
Source Location
- Repository: Duckdb_Duckdb
- Files:
Signature
// Test case declaration
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
// Sections for nested sub-tests
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
// Fatal assertions (abort test on failure)
#define REQUIRE( ... ) // evaluates expression; fails and stops test if false
#define REQUIRE_FALSE( ... ) // evaluates expression; fails and stops test if true
#define REQUIRE_THROWS( ... ) // fails if expression does not throw
#define REQUIRE_THROWS_AS( expr, exceptionType ) // fails if expr does not throw exceptionType
#define REQUIRE_THROWS_WITH( expr, matcher ) // fails if thrown message does not match
#define REQUIRE_NOTHROW( ... ) // fails if expression throws
// Non-fatal assertions (continue test on failure)
#define CHECK( ... ) // evaluates expression; reports failure but continues
#define CHECK_FALSE( ... ) // evaluates expression; reports failure if true
#define CHECK_THROWS( ... ) // reports failure if expression does not throw
#define CHECK_THROWS_AS( expr, exceptionType ) // reports failure if wrong exception type
#define CHECK_NOTHROW( ... ) // reports failure if expression throws
// Matcher-based assertions
#define REQUIRE_THAT( arg, matcher ) // fatal matcher assertion
#define CHECK_THAT( arg, matcher ) // non-fatal matcher assertion
// Logging
#define INFO( msg ) // scoped info message shown on failure
#define CAPTURE( ... ) // captures variable values shown on failure
Import
#include "catch.hpp"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| test name | const char* |
Yes | A string literal identifying the test case passed to TEST_CASE |
| tags | const char* |
No | Optional Catch2 tag string (e.g., "[core][parser]") for filtering tests
|
| expression | C++ expression | Yes | The boolean expression or statement evaluated by REQUIRE or CHECK |
| exceptionType | type name | No | The expected exception type for REQUIRE_THROWS_AS / CHECK_THROWS_AS |
| matcher | Catch::Matchers::* |
No | A Catch2 matcher object for REQUIRE_THAT / CHECK_THAT |
Outputs
| Name | Type | Description |
|---|---|---|
| test result | pass/fail | Each assertion produces a pass or fail result aggregated into the test report |
| diagnostic output | text | On failure, Catch2 prints the expression, expanded values, and any INFO/CAPTURE context |
| exit code | int |
The test runner returns 0 on all-pass, non-zero on any failure |
Usage Examples
#include "catch.hpp"
TEST_CASE("Vector push_back increases size", "[vector]") {
std::vector<int> v;
REQUIRE(v.empty());
SECTION("single element") {
v.push_back(1);
REQUIRE(v.size() == 1);
REQUIRE(v[0] == 1);
}
SECTION("multiple elements") {
v.push_back(1);
v.push_back(2);
REQUIRE(v.size() == 2);
CHECK(v[0] == 1);
CHECK(v[1] == 2);
}
}
TEST_CASE("Exception handling", "[exceptions]") {
REQUIRE_THROWS_AS(throw std::runtime_error("error"), std::runtime_error);
REQUIRE_NOTHROW(1 + 1);
}