Anteru's blog
  • Consulting
  • Research
    • Assisted environment probe placement
    • Assisted texture assignment
    • Error Metrics for Smart Image Refinement
    • High-Quality Shadows for Streaming Terrain Rendering
    • Hybrid Sample-based Surface Rendering
    • Interactive rendering of Giga-Particle Fluid Simulations
    • Quantitative Analysis of Voxel Raytracing Acceleration Structures
    • Real-time Hybrid Hair Rendering
    • Scalable rendering for very large meshes
    • Subpixel Reconstruction Antialiasing
    • Tiled light trees
  • About
  • Archive

Advent 2021: Catch2

December 18, 2021
  • Programming
approximately 3 minutes to read

I’ve always been a huge proponent of unit testing. However, unit tests must be easy to write, otherwise, nobody will bother doing so. For Python, we have PyTest which makes it incredibly easy, but C++ didn’t use to be that lucky. There was Google Test, Boost.Test, and a few other small frameworks, but nothing “modern” which would come close in usability to the testing frameworks we enjoy in other languages … that is, until Catch2 came along.

Since it appeared it has been my goto test framework. Be it at work or in personal projects – after setting up a new (static) library, I set up a corresponding Catch2 unit test runner. Usage is so simple that even junior developers end up writing tests within minutes, it’s super fast to execute, and it has high quality failures messages without requiring large amounts of code and markup.

What’s so great about it? Two things really:

  • Very few macros to remember. Most checks are of the form CHECK(x == 23)
  • Sections render test fixtures mostly obsolete

The section bit in particular is just so helpful it’s no longer funny:

IO::MemoryStream ms;

ms.Write ("ABCDEF", sizeof (char) * 7);
ms.Seek (0);

SECTION("Read to MutableArrayRef")
{
    char buffer[7] = { 0 };
    ms.Read(MutableArrayRef<>(buffer));

    CHECK_THAT(buffer, Catch::Equals("ABCDEF"));
}

SECTION("Reading from closed stream fails", "[core]")
{
    ms.Close();

    byte buffer;
    CHECK_THROWS_AS(ms.Read(&buffer, 1), IO::IOException);
}

SECTION("Read into null buffer fails", "[core]")
{
    CHECK_THROWS_AS(ms.Read(nullptr, 3), RuntimeException);
}

Each SECTION runs with the same setup code, so there’s no leaking of data between them, and no need to write fixture boilerplate. It feels really natural quickly and makes test development much quicker, especially as nearly every test requires some setup and then a few mutations. For me, Catch2 was a real eye opener as to how easy unit testing in C++ can be. It’s now an integral part of my C++ toolbox and I really can’t imagine working on a C++ project without it any more.

Previous post
Next post

Recent posts

  • Advent 2021: Open source
    Posted on 2021-12-24
  • Advent 2021: Blender
    Posted on 2021-12-23
  • Advent 2021: Visual Studio Code
    Posted on 2021-12-22
  • Advent 2021: Thunderbird
    Posted on 2021-12-21
  • Advent 2021: ZFS
    Posted on 2021-12-20
  • Older posts

Find me on the web

  • GitHub
  • GPU database
  • Projects

Follow me

NIV_Anteru

Contents © 2005-2022 | Anteru | Imprint/Impressum | Privacy policy/Datenschutz | Made with Liara