# How to Debug Failing Tests with Assertion Info and Timing in Catch2

> Debug failing Catch2 tests effectively with detailed assertion info and precise section timing. Learn to use reporter infrastructure for better visibility.

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

---

**Catch2 provides deep debugging visibility through its reporter infrastructure, exposing full assertion details via `AssertionInfo` and precise section timing through `SectionStats`, controllable via command-line flags or custom reporters.**

When a test fails in the [Catch2](https://github.com/catchorg/Catch2) framework, you need more than just a pass/fail signal to diagnose the issue. You need to know exactly which assertion failed, where it lives in your source code, and how long each test section took to execute. This article shows you how to extract rich debugging metadata from Catch2's reporter system to debug failing tests with assertion info and timing.

## Understanding the Reporter Infrastructure

The core of Catch2's debugging capability lives in its reporter infrastructure defined in [`src/catch2/interfaces/catch_interfaces_reporter.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/interfaces/catch_interfaces_reporter.hpp). When tests fail, the framework transmits detailed metadata through virtual callbacks like `assertionStarting` and `sectionEnded`, giving you programmatic access to exactly what failed and how long each part took.

### Capturing Assertion Details with AssertionInfo

Every assertion in Catch2 generates a `Catch::AssertionInfo` object that records the **source location**, the **original expression**, and the **macro** that generated the assertion. According to the source code in [`src/catch2/catch_assertion_info.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_assertion_info.hpp), this struct contains the file path, line number, and macro name【source 3†L17-L20】.

The reporter interface receives this data via `IEventListener::assertionStarting( AssertionInfo const& )`【source 1†L84-L86】. When you implement a custom reporter or use high verbosity settings, Catch2 forwards this struct for every assertion, allowing you to pinpoint exactly which `REQUIRE` or `CHECK` macro failed and where it is located in your codebase.

### Tracking Execution Timing with durationInSeconds

Timing information attaches to a `SectionInfo` object through the field `double durationInSeconds`, which the framework populates when a section finishes. This value is later exposed through `SectionStats` and the reporter callback `sectionEnded( SectionStats const& )`【source 2†L37-L38】.

As implemented in [`src/catch2/catch_section_info.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_section_info.hpp), this mechanism tracks how long each `TEST_CASE` or `SECTION` block takes to execute. When you enable duration reporting, Catch2 highlights sections that exceed your performance thresholds, making it easy to identify slow tests that might indicate performance regressions or flaky timeouts.

## Command-Line Debugging Options

You don't need to write custom code to access assertion metadata and timing data. Catch2 exposes these internals through command-line flags that configure the built-in reporters.

### Enabling High Verbosity for Assertion Tracing

Use the `--verbosity high` flag to force the console reporter to invoke `assertionStarting` for **all** assertions, not only the failing ones. This gives you a step-by-step trace of every `CHECK` and `REQUIRE` as it executes:

```bash
./tests --reporter console --verbosity high

```

This setting targets the `shouldReportAllAssertionStarts` preference in the reporter configuration, ensuring you see the progression of assertions even in passing tests.

### Configuring Duration Reporting

Add the `--durations yes` flag to display the execution time for each section after the test run. You can also set a specific threshold with `--durations <seconds>` to highlight only sections slower than the specified value:

```bash
./tests --durations 0.5

```

Sections exceeding 0.5 seconds will be flagged in the output, leveraging the `durationInSeconds` field populated in `SectionStats`.

### Using XML and JUnit Reporters for CI Integration

For programmatic analysis in CI pipelines, use the XML or JUnit reporters to serialize assertion details and timing data:

```bash
./tests --reporter xml > results.xml

```

The XML output contains `<failure>` elements with full `AssertionInfo` (file, line, expression) and `<section>` elements with a `duration` attribute, allowing you to parse and trend test performance over time.

## Building a Custom Debug Reporter

When the built-in reporters don't suit your needs, you can write a custom reporter by inheriting from `IEventListener`. This approach lets you capture `AssertionInfo` and `SectionStats` in your own data structures.

Implement `assertionStarting` and `assertionEnded` to capture assertion metadata, and `sectionEnded` to log timing. The `ReporterPreferences` struct lets you opt-in to receive all assertions via `shouldReportAllAssertions = true` and to get start notifications via `shouldReportAllAssertionStarts = true`.

Here is a complete example that logs every assertion and section timing to a JSON file:

```cpp
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <fstream>

class JsonLogger : public Catch::IEventListener {
    std::ofstream out;
public:
    explicit JsonLogger( Catch::IConfig const* ) 
        : out("catch_debug.json") {
        // Opt-in to receive all assertion events
        getPreferences().shouldReportAllAssertions = true;
        getPreferences().shouldReportAllAssertionStarts = true;
    }
    
    void assertionStarting( Catch::AssertionInfo const& info ) override {
        out << "{ \"type\":\"assert_start\", \"file\":\""
            << info.file << "\", \"line\":" << info.line
            << ", \"macro\":\"" << info.macroName << "\" }\n";
    }
    
    void assertionEnded( Catch::AssertionStats const& stats ) override {
        out << "{ \"type\":\"assert_end\", \"passed\":"
            << (stats.assertionResult.isOk() ? "true" : "false")
            << " }\n";
    }
    
    void sectionEnded( Catch::SectionStats const& stats ) override {
        out << "{ \"type\":\"section\", \"name\":\""
            << stats.sectionInfo.name << "\", \"duration\":"
            << stats.durationInSeconds << " }\n";
    }
};

CATCH_REGISTER_REPORTER( "json", JsonLogger )

```

Compile this reporter into your test binary and invoke it with:

```bash
./tests -r json

```

The generated [`catch_debug.json`](https://github.com/catchorg/Catch2/blob/main/catch_debug.json) will contain every assertion's source location from `AssertionInfo` and the elapsed time for each section from `SectionStats`, which you can feed into dashboards or debugging tools.

## Summary

- **`AssertionInfo`** captures the file path, line number, macro name, and expression for every assertion, defined in [`src/catch2/catch_assertion_info.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_assertion_info.hpp).
- **`SectionStats`** exposes `durationInSeconds` populated from `SectionInfo`, allowing you to identify slow test sections.
- **Command-line flags** `--verbosity high` and `--durations yes` expose this data through built-in reporters without code changes.
- **Custom reporters** inherit from `IEventListener` and use `CATCH_REGISTER_REPORTER` to implement bespoke logging of assertion starts/ends and section timing.
- **XML/JUnit reporters** serialize the same metadata for CI pipelines, containing `<failure>` elements with full source location and `<section>` elements with duration attributes.

## Frequently Asked Questions

### How do I see every assertion including passing ones?

Use the `--verbosity high` command-line flag. This sets the reporter preference `shouldReportAllAssertionStarts = true`, causing the framework to call `assertionStarting` for every assertion, not just failures.

### Can I filter to show only slow test sections?

Yes. Use `--durations <threshold>` where `<threshold>` is a floating-point number of seconds. Catch2 will only highlight sections whose `durationInSeconds` exceeds this value, making it easy to spot performance bottlenecks.

### Where is assertion source information stored in the Catch2 source?

Assertion source details live in [`src/catch2/catch_assertion_info.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_assertion_info.hpp), which defines the `AssertionInfo` struct containing the file path, line number, and macro name used in the assertion.

### How do I export timing data to JSON?

Create a custom reporter inheriting from `IEventListener` that implements `sectionEnded( SectionStats const& )` to capture `stats.durationInSeconds`. Write this data to a JSON file in your reporter implementation and register it with `CATCH_REGISTER_REPORTER`. Run your tests with `-r <your_reporter_name>` to generate the output.