# How to Use DYNAMIC_SECTION for Parameterized Test Sections in Catch2

> Learn how to use DYNAMIC_SECTION for parameterized test sections in Catch2. Generate test names at runtime for flexible and dynamic testing.

- Repository: [Catch Org/Catch2](https://github.com/catchorg/Catch2)
- Tags: tutorial
- Published: 2026-07-29

---

**`DYNAMIC_SECTION` lets you create runtime-generated test sections whose names are built from values computed during test execution, unlike the compile-time constant names required by the standard `SECTION` macro.**

The `DYNAMIC_SECTION` macro in the **catchorg/Catch2** testing framework enables data-driven testing by allowing section names to be constructed at runtime from variables, generators, or stream expressions. While the standard `SECTION` macro requires a fixed string literal known at compile time, `DYNAMIC_SECTION` evaluates its argument each time the enclosing test case runs, producing distinct, parameterized test paths that adapt to dynamic values.

## What Is DYNAMIC_SECTION?

Unlike the regular `SECTION` macro, which requires a compile-time constant string, `DYNAMIC_SECTION` evaluates its argument dynamically using stream insertion syntax (`<<`). This allows the same test case to produce different section hierarchies on different iterations, making it ideal for loops, generators, or conditional test logic.

Under the hood, the macro expands to `INTERNAL_CATCH_DYNAMIC_SECTION`, which instantiates a `Catch::Section` object whose description is built from the streamed expression.

## Header Files and Implementation

The public API is defined in **[`src/catch2/catch_test_macros.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_test_macros.hpp)**, where the `DYNAMIC_SECTION` macro is declared. The underlying machinery that handles the runtime name construction and section tracking lives in **[`src/catch2/internal/catch_section.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/internal/catch_section.hpp)**, implementing the `INTERNAL_CATCH_DYNAMIC_SECTION` logic and the `Catch::Section` class.

## How DYNAMIC_SECTION Works

When the test runner encounters a `DYNAMIC_SECTION`, it performs three steps:

1. **Evaluates the expression** (e.g., `std::to_string(i)`) to construct the section name.
2. **Creates a `Catch::Section` object** with that computed name.
3. **Executes the enclosed statements** only if the section is active for the current test run.

If the same `DYNAMIC_SECTION` block is reached again with a different evaluated name, Catch2 treats it as an entirely new section, branching into a fresh execution path while preserving isolation between runs.

## Practical Code Examples

### Parameterized Tests with GENERATE

Combine `DYNAMIC_SECTION` with `GENERATE` to create distinct sections for each generated value:

```cpp
TEST_CASE("Dynamic sections with generators") {
    auto i = GENERATE(0, 1, 2);
    DYNAMIC_SECTION("iteration " << i) {
        REQUIRE(i >= 0);
    }
}

```

Each generated value creates an independent section named "iteration 0", "iteration 1", and so on, appearing as separate entries in the test report.

### Loop-Based Dynamic Sections

Use standard loops to generate multiple sections programmatically:

```cpp
TEST_CASE("Loop-driven dynamic sections") {
    for (int i = 0; i < 3; ++i) {
        DYNAMIC_SECTION("loop index = " << i) {
            INFO("Current index: " << i);
            REQUIRE(i < 3);
        }
    }
}

```

The loop executes three times, yielding three isolated sections that run independently.

### Conditional Sections with Runtime Data

Construct section names from runtime data such as environment variables:

```cpp
TEST_CASE("Conditional dynamic sections") {
    std::string mode = std::getenv("TEST_MODE") ? std::getenv("TEST_MODE") : "default";
    DYNAMIC_SECTION("mode = " << mode) {
        if (mode == "fast") {
            REQUIRE(true);  // fast-mode specific checks
        } else {
            REQUIRE(false); // default-mode specific checks
        }
    }
}

```

The section name reflects the runtime environment state, enabling separate reporting for each configuration mode.

## Summary

- **Runtime Evaluation**: `DYNAMIC_SECTION` evaluates its name expression at runtime using stream syntax (`<<`), unlike the compile-time constants required by `SECTION`.
- **Source Locations**: The macro is defined in [`src/catch2/catch_test_macros.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_test_macros.hpp) with implementation details in [`src/catch2/internal/catch_section.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/internal/catch_section.hpp).
- **Distinct Paths**: Changing the evaluated name between iterations creates entirely new section branches, supporting data-driven and parameterized testing patterns.
- **Integration**: Works seamlessly with `GENERATE`, loops, and conditional logic to produce flexible test hierarchies that adapt to runtime data.

## Frequently Asked Questions

### What is the difference between SECTION and DYNAMIC_SECTION in Catch2?

The `SECTION` macro requires a string literal or compile-time constant for its name, while `DYNAMIC_SECTION` accepts a stream expression evaluated at runtime. This allows `DYNAMIC_SECTION` to incorporate variable values, generator outputs, or computed strings into the section name, enabling parameterized test structures that `SECTION` cannot support.

### Can I use DYNAMIC_SECTION with data generators?

Yes. `DYNAMIC_SECTION` pairs naturally with `GENERATE` to create uniquely named sections for each generated dataset. Because the section name is evaluated after the generator produces its value, each iteration appears as a distinct test path in the output, providing clear isolation and reporting for parameterized tests.

### How does Catch2 handle section names that change between runs?

Catch2 treats each unique evaluated name as a separate section entity. When a `DYNAMIC_SECTION` produces a different string on subsequent executions within the same test case, the framework branches into a new execution path, running the enclosed code exactly once for that specific name while maintaining standard section scoping and lifecycle guarantees.

### Is there a performance cost to using DYNAMIC_SECTION?

The primary overhead comes from the runtime construction of the section name string and the associated `Catch::Section` object creation. While slightly more expensive than the static `SECTION` macro, this cost is negligible for most test suites and is offset by the flexibility of runtime parameterization, especially when testing against dynamic data sources or large parameterized datasets.