RepoPilotOpen in app →

catchorg/Catch2

A modern, C++-native, test framework for unit-tests, TDD and BDD - using C++14, C++17 and later (C++11 support is in v2.x branch, and C++03 on the Catch1.x branch)

Mixed

Mixed signals — read the receipts

weakest axis
Use as dependencyConcerns

non-standard license (BSL-1.0)

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 1d ago
  • 20 active contributors
  • BSL-1.0 licensed
Show all 7 evidence items →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 78% of recent commits
  • Non-standard license (BSL-1.0) — review terms
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/catchorg/catch2?axis=fork)](https://repopilot.app/r/catchorg/catch2)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/catchorg/catch2 on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: catchorg/Catch2

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/catchorg/Catch2 shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Mixed signals — read the receipts

  • Last commit 1d ago
  • 20 active contributors
  • BSL-1.0 licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 78% of recent commits
  • ⚠ Non-standard license (BSL-1.0) — review terms

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live catchorg/Catch2 repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/catchorg/Catch2.

What it runs against: a local clone of catchorg/Catch2 — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in catchorg/Catch2 | Confirms the artifact applies here, not a fork | | 2 | License is still BSL-1.0 | Catches relicense before you depend on it | | 3 | Default branch devel exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>catchorg/Catch2</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of catchorg/Catch2. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/catchorg/Catch2.git
#   cd Catch2
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of catchorg/Catch2 and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "catchorg/Catch2(\\.git)?\\b" \\
  && ok "origin remote is catchorg/Catch2" \\
  || miss "origin remote is not catchorg/Catch2 (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(BSL-1\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"BSL-1\\.0\"" package.json 2>/dev/null) \\
  && ok "license is BSL-1.0" \\
  || miss "license drift — was BSL-1.0 at generation time"

# 3. Default branch
git rev-parse --verify devel >/dev/null 2>&1 \\
  && ok "default branch devel exists" \\
  || miss "default branch devel no longer exists"

# 4. Critical files exist
test -f "CMakeLists.txt" \\
  && ok "CMakeLists.txt" \\
  || miss "missing critical file: CMakeLists.txt"
test -f "src/catch2" \\
  && ok "src/catch2" \\
  || miss "missing critical file: src/catch2"
test -f "docs/tutorial.md" \\
  && ok "docs/tutorial.md" \\
  || miss "missing critical file: docs/tutorial.md"
test -f "src/catch2/catch_all.hpp" \\
  && ok "src/catch2/catch_all.hpp" \\
  || miss "missing critical file: src/catch2/catch_all.hpp"
test -f "examples/010-TestCase.cpp" \\
  && ok "examples/010-TestCase.cpp" \\
  || miss "missing critical file: examples/010-TestCase.cpp"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/catchorg/Catch2"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Catch2 is a modern, header-only C++ unit testing framework (now modular in v3) that makes test writing natural and expressive through intuitive assertion syntax, named test cases with tags, and BDD-style sections for setup/teardown sharing. It provides built-in micro-benchmarking via the BENCHMARK() macro and runs on C++14+ while maintaining a v2.x branch for C++11 support. Hybrid structure: core testing framework in src/ (inferred from CMakeLists.txt), modular headers under a catch2 namespace (v3 change from v2's single header), benchmarking extensions in benchmark/ subdirectory, integration examples for Conan in .conan/test_package/, and CI/build configurations scattered across .github/workflows/, .bazelrc, BUILD.bazel, MODULE.bazel, and CMakePresets.json to support multiple build systems.

👥Who it's for

C++ developers and teams building unit tests, TDD workflows, and BDD specifications who want a testing framework that doesn't require test names to be valid identifiers and lets assertions read like normal C++ boolean expressions (e.g., REQUIRE(factorial(5) == 120)).

🌱Maturity & risk

Highly mature and production-ready: v3 was officially released (visible in active devel branch), has comprehensive CI across Linux/macOS/Windows via GitHub Actions, code coverage tracking with codecov.io, multiple build system integrations (CMake, Bazel, Meson, Conan), and active development evidenced by the migration from single-header to modular architecture.

Low risk: well-established project with organized issue templates, security policy (SECURITY.md), maintainers list (MAINTAINERS.md), and distributed maintenance. The v3 refactor to drop the single-header model represents a breaking change but is clearly documented. No single-maintainer bottleneck evident. Moderate dependency surface via CMake, Bazel, Meson, and Conan integration, but dependencies are build-time, not runtime.

Active areas of work

Active development on v3 (devel branch is primary), with ongoing CI pipeline maintenance (multiple workflow files for different platforms and build systems), code quality enforcement via clang-format/clang-tidy configs, and likely modularization work to replace the v2 single-header design. Package manager integrations (Conan, Bazel modules) suggest focus on distribution and discoverability.

🚀Get running

git clone https://github.com/catchorg/Catch2.git
cd Catch2
mkdir build && cd build
cmake ..
cmake --build .
ctest

Or with Conan: conan create . --build=missing (uses .conan/conanfile.py). Or with Bazel: bazel test //... (uses BUILD.bazel and MODULE.bazel).

Daily commands: Tests: ctest in build directory. Benchmarks: ./your_test_binary [!benchmark] (opt-in via tag). Example from README: compile a .cpp file with Catch2 headers, link against catch2 library (or use header-only in v2), and run the binary directly.

🗺️Map of the codebase

  • CMakeLists.txt — Root build configuration for the entire Catch2 framework; defines compilation targets, dependencies, and installation rules that all contributors must understand.
  • src/catch2 — Core source directory containing the test framework implementation; the heart of the library where assertion macros, test registration, and runner logic reside.
  • docs/tutorial.md — Primary onboarding document explaining Catch2's test structure, macros, and philosophy; essential reading for understanding the framework's design intent.
  • src/catch2/catch_all.hpp — Main single-header include that exports the public API; understanding this entry point is critical for integration and API stability.
  • examples/010-TestCase.cpp — Canonical example demonstrating basic TEST_CASE macro usage; reference implementation for how users write tests.
  • docs/contributing.md — Contribution guidelines and codebase conventions; mandatory for pull request authors.
  • MAINTAINERS.md — Governance structure and decision-making process for the Catch2 project; clarifies roles and expectations.

🛠️How to make changes

Add a new Assertion Macro

  1. Define the macro signature and decomposition logic in src/catch2/test_macros/ (src/catch2/test_macros/assertion_macros.hpp)
  2. Register the macro in the test_macros/all.hpp aggregator for public export (src/catch2/test_macros/all.hpp)
  3. Add a test case to tests/ demonstrating the new assertion (tests/ExceptionTests.cpp)
  4. Document usage and examples in docs/assertions.md (docs/assertions.md)

Implement a Custom Matcher

  1. Create a new matcher class inheriting from MatcherBase<T> in src/catch2/matchers/ (src/catch2/matchers/catch_matchers_floating_point.hpp)
  2. Implement match() and describe() virtual methods for evaluation and messaging (src/catch2/matchers/catch_matchers_floating_point.hpp)
  3. Export matcher factory function in src/catch2/matchers/all.hpp (src/catch2/matchers/all.hpp)
  4. Add example usage to docs/matchers.md with use-case explanation (docs/matchers.md)

Create a New Reporter Backend

  1. Implement ReporterBase interface in src/catch2/reporters/ (src/catch2/reporters/catch_reporter_event.hpp)
  2. Override event handlers (testCaseStarting, assertionEnded, testRunEnded, etc.) for your output format (src/catch2/reporters/catch_reporter_compact.hpp)
  3. Register reporter factory in src/catch2/reporters/all.hpp (src/catch2/reporters/all.hpp)
  4. Add documentation and example output to docs/reporters.md (docs/reporters.md)

Add a Generator for Parameterized Tests

  1. Define a Generator<T> subclass in src/catch2/generators/ (src/catch2/generators/catch_generators_range.hpp)
  2. Implement next() to advance to the next value and current() to retrieve it (src/catch2/generators/catch_generators_range.hpp)
  3. Export a factory function (e.g., range()) in src/catch2/generators/all.hpp (src/catch2/generators/all.hpp)
  4. Add usage example to examples/300-Gen-OwnGenerator.cpp (examples/300-Gen-OwnGenerator.cpp)

🔧Why these technologies

  • C++14/17/20 (with C++11 in v2.x branch) — Provides modern template metaprogramming, constexpr, and variadic templates needed for zero-overhead assertion decomposition and compile-time test registration without runtime overhead.
  • Header-only single-file distribution (catch_all.hpp) — Eliminates linker complexity and makes integration friction-free; users can drop one file into their project. Matches test framework distribution best practices (like googletest).
  • Expression decomposition via template-based operator overloading — Enables human-readable assertion messages showing intermediate values (e.g., 'REQUIRE a == b' prints 'a=5 == b=3' on failure) without requiring separate assertion types for each comparison.
  • Pluggable Reporter interface with event-listener pattern — Decouples test execution from output formatting, enabling multiple reporters (JSON, XML, TAP, Sonarqube) and custom listeners without modifying core runner logic.
  • Generator abstraction for parameterized tests — Provides lazy evaluation and composability (e.g., combining range + filter) for test case generation without requiring separate test instantiation macros or templates.

🪤Traps & gotchas

C++ standard version: v3 requires C++14+; v2.x branch needed for C++11 projects; check CMAKE_CXX_STANDARD in CMakePresets.json. Single-header vs. modular: v3 broke from single-header design—old v2 code using monolithic catch.hpp won't work directly without migration. Benchmark opt-in: benchmarks only run with [!benchmark] tag; accidental benchmark in normal test suite may be silently skipped. Multi-build-system maintenance: changes must be applied to CMakeLists.txt AND BUILD.bazel AND meson.build (if applicable), or CI will fail selectively. Conan test package: .conan/test_package/ must be kept synchronized with library API changes or package validation fails.

🏗️Architecture

💡Concepts to learn

  • BDD (Behavior-Driven Development) Macros — Catch2 provides GIVEN/WHEN/THEN syntax (via SECTIONs and readable test names) for readable test specifications that bridge developer and business language.
  • Expression Template Assertions — Catch2's assertion macros (REQUIRE, CHECK) use C++ expression templates to capture and decompose failing expressions into readable diagnostics without external libraries.
  • Micro-benchmarking — Catch2's BENCHMARK() macro provides in-test performance measurement with statistical analysis (timing, iterations) without requiring separate tools like Google Benchmark.
  • Test Tag Filtering — Catch2's [tag] syntax allows runtime filtering of tests (e.g., [!benchmark] for opt-in, [slow] for skipping) without code changes or recompilation.
  • Header-only to Modular Migration (v2 → v3) — Understanding why Catch2 v3 moved from single-header (catch.hpp) to modular design (namespace headers) reveals trade-offs between compile-time convenience and link-time flexibility.
  • Multi-build-system Support (CMake, Bazel, Meson) — Catch2's integration across CMake, Bazel, and Meson demonstrates how to maintain a C++ library that works in heterogeneous build ecosystems without code duplication.
  • Conan Package Manager Integration — Catch2's .conan/ structure shows how to publish and distribute C++ libraries with pre-built binaries, enabling dependency management similar to npm/pip for C++.
  • google/googletest — Most popular C++ testing alternative; heavier OOP design vs. Catch2's expression-based assertions; many projects choose between the two.
  • doctest/doctest — Lightweight single-header C++ test framework with similar natural syntax; faster compilation and smaller binary footprint than Catch2 v2, though Catch2 v3 addressed some of this.
  • boost/test — Boost.Test is the heavyweight alternative; tightly integrated with Boost ecosystem; used in large legacy C++ codebases.
  • catchorg/Catch2-docs — Companion documentation repository for Catch2; contains guides, examples, and API reference separate from main codebase.
  • nlohmann/json — Commonly paired with Catch2 for JSON test data fixtures and assertion libraries; popular in C++ test suites for mock data.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive documentation for Conan package integration and test coverage

The repo has Conan configuration files (.conan/build.py, conanfile.py, .conan/test_package/) but lacks detailed documentation on how contributors and users should use Conan with Catch2. The docs/ directory doesn't contain a conan-integration.md file (similar to cmake-integration.md), making it difficult for package manager users to understand build workflows. This is especially important given the package-manager-builds.yaml CI workflow exists.

  • [ ] Create docs/conan-integration.md documenting Conan usage with Catch2
  • [ ] Include examples for consuming Catch2 via Conan (test_package/conanfile.py shows this partially)
  • [ ] Document the conanfile.py structure and .conan/build.py customization options
  • [ ] Add troubleshooting section for common Conan + Catch2 integration issues

Create header guard validation tests in CI and document the validation workflow

A validate-header-guards.yml workflow exists in .github/workflows/ but there's no corresponding documentation explaining header guard conventions, what the validation checks for, or how contributors should structure headers. Additionally, there's no visible test file documenting expected header patterns for new contributors. This validation is critical for a header-only library but underdocumented.

  • [ ] Create docs/header-guidelines.md explaining Catch2 header guard naming conventions
  • [ ] Document the validate-header-guards.yml workflow expectations
  • [ ] Add examples of correct/incorrect header guard patterns used in the codebase
  • [ ] Reference this documentation in CONTRIBUTING.md or docs/contributing.md

Add missing documentation for Bazel build integration and examples

The repo contains BUILD.bazel and MODULE.bazel files plus a linux-bazel-builds.yml CI workflow, but no docs/bazel-integration.md exists (only cmake-integration.md). This creates a documentation gap for users wanting to integrate Catch2 with Bazel. Given the presence of Bazel configuration and CI coverage, a dedicated guide would help contributors and users understand this build system integration.

  • [ ] Create docs/bazel-integration.md with Bazel-specific build instructions
  • [ ] Document how to use Catch2 as a Bazel dependency (referencing MODULE.bazel)
  • [ ] Include examples of BUILD files for test targets using Catch2
  • [ ] Add troubleshooting section for common Bazel + Catch2 issues

🌿Good first issues

  • Add a complete example integration test for Meson build system similar to the Bazel/CMake/Conan examples (currently linux-meson-builds.yml exists but no test_package equivalent in meson/ directory).
  • Enhance documentation in docs/ or root README with a 'Quick Start by Build System' section showing exact CMakeLists.txt snippet, bazel BUILD snippet, and Meson snippet side-by-side (currently README only shows test code, not build integration).
  • Add missing header guard validation for new files added to src/catch2/ by implementing a pre-commit check or documenting the guard pattern (.github/workflows/validate-header-guards.yml exists but may not catch all cases).

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 54af406 — Add more runtime benchmark recipe TODOs (horenmar)
  • 5f47160 — Add benchmark for catch_test_macros.hpp inclusion (horenmar)
  • e83528c — Add readme to benchmarks/ with some simple examples (horenmar)
  • fd31a62 — Add benchmark for REQUIRE_THAT into runtime_assertion_benches.cpp (horenmar)
  • 4df8fee — IConfig derives from NonCopyable privately (horenmar)
  • 300c5d3 — Fix Wconversion warning in catch_reporter_helpers.cpp (Ole Schmidt)
  • 11a96e1 — Cleanups from static analysis (horenmar)
  • 10f6248 — AssertionHandler uses RunContext directly to avoid virtual dispatch (horenmar)
  • be2dfb4 — Update Doxyfile (horenmar)
  • 47200dd — Rework internals of CATCH_REGISTER_ENUM (horenmar)

🔒Security observations

Catch2 demonstrates good security posture as a unit test framework with minimal attack surface. No critical vulnerabilities were identified in the repository structure, build configuration, or dependencies (none explicitly listed). The main security concerns are operational: (1) a maintainer's personal email address exposed in the security policy, and (2) a PGP key fingerprint included in plaintext. The security policy itself is minimal but appropriate for the project's scope. The project uses modern CI/CD pipelines (GitHub Actions, AppVeyor) with multiple build configurations, indicating good build security practices. Recommendations focus on improving vulnerability disclosure processes and expanding security awareness documentation.

  • Low · Potential PGP Key Exposure in Security Policy — SECURITY.md. The SECURITY.md file contains a PGP public key fingerprint (E29C 46F3 B8A7 5028 6079 3B7D ECC9 C20E 314B 2360) in plaintext. While PGP public keys are meant to be public, including them in the repository makes them easily accessible to automated scanning tools and could be used for social engineering or to validate spoofed communications. Fix: Consider hosting the PGP key on a dedicated key server or the maintainer's website instead. The SECURITY.md can reference the key location without including it directly in the repository.
  • Low · Email Address Exposed in Security Policy — SECURITY.md. A maintainer's email address (martin.horenovsky@gmail.com, obfuscated with dots) is publicly listed in the SECURITY.md file for vulnerability reports. This increases exposure to spam and potential targeted attacks. Fix: Consider using a dedicated security contact email address (e.g., security@catchorg.org) or implement a GitHub Security Advisory reporting mechanism instead of public email addresses.
  • Low · Limited Security Policy Scope — SECURITY.md. The SECURITY.md acknowledges that as a unit test framework, Catch2 'shouldn't interact with untrusted inputs.' However, this assumption may not account for scenarios where test frameworks are used with malicious test files, adversarial input generation, or in CI/CD pipelines processing untrusted data. Fix: Expand the security policy to include: (1) security considerations for users, (2) guidelines for secure usage in CI/CD pipelines, (3) handling of potential code injection through test macros, and (4) fuzzing and security testing recommendations.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · catchorg/Catch2 — RepoPilot