A Brief History of Catch(2)


Prehistory

In the middle of 2010 I started working on a little side project. It was originally meant to be a test framework for Objective-C (I wasn’t happy with OCUnit, at the time, and I didn’t find any other options). But the framework was written in a mix of Objective-C++ and plain C++. So before long the focus shifted to being a C++ test framework first (but the Objective-C part remained). I had been playing with the idea of being able to write the comparison expressions using natural syntax (rather than the, still common, JUnit style of having a family of macros like ASSERT_EQUAL, ASSERT_NOTEQUAL). After initially dismissing the idea of using expression templates for this as being overly complex, I reconsidered after seeing Kevlin Henney use exactly that technique for his experimental test framework, LHR. I also added Kevlin’s idea of what he called Dividers, calling them Sections, free-form string test names and a few other features. Then, on the 28th December 2010, I released Catch to the world!

Catch v0-v1

Of course, Catch developed and evolved over time. It became single-header-only (one of the first, I believe) and gained BDD-style macros, but it wasn’t until two-and-a-half years later that I felt it had stabilised enough to call it 1.0. At that time it also got Matchers. It was also around this time that I was starting to talk about it at conferences and it seemed to really take off.

Catch2 v2-v3

By 2017 I had Martin Hořeňovský helping out as co-maintainer, and we felt it was the right time to go all-in on C++11 (which had been out for six years by then, after all). This became Catch2. I said at the time that Catch2 was the new name - not just a version number (this was to make it easier to search for). I went as far as to say that when we go to the next major version it would be called Catch2 v3. People laughed, but that has now happened! The difference is: I wasn’t really part of v3. By that time my involvement had dwindled and Martin had really picked up the slack and became the de-facto sole maintainer. There’s a few reasons that things went that way. None particularly interesting. Let’s just say my focus was divided and I had lots of interesting things to work on. Whereas Catch started out as an interesting diversion for me, it had become a distraction.

Catch23

But I do miss working on Catch/ Catch2. As it happens, around the time we rebranded with Catch2, of course many people were making jokes about Catch22. That was largely intentional. Especially when you consider the big breaking change that was C++11. What does 2 × 11 equal? But I also said, mostly-jokingly, that when we get C++23 I’d produce a version called Catch23. Remember that was in 2017. We didn't even have C++17 then. I didn’t really know what would be in C++23 but had expectations that we might get Reflection - which would be very useful! In any case I knew some of the things coming for C++20 and they would make a big difference already. I was particularly looking forward to Ranges, which I thought would play very nicely into Catch’s Generators (as it happens, yes - but less so than I thought). Concepts would certainly be useful (spoiler - they're a game changer!). But really it was more about the number than the features.

Then, a few years ago, I started working with C++20 Coroutines and it struck me that they could be useful for Catch in a couple of ways: first as a mechanism for Generators - but also for the test runner! Running a test case is a bit of a dance backwards and forwards between the test runner infrastructure (for capturing results and deciding what to do next) and that is, currently, all facilitated by a whole family of singletons (if such a phrase is meaningful)! That idea of weaving back and forth between parallel streams of code is exactly what Coroutines are all about, and some initial experiments were quite fruitful.

So I got back to thinking about what else could be rebased on modern C++ features and the more I picked, the more I realised that C++20 changes everything! What about C++23? That actually brings a number of very nice features too (maybe even enough to justify waiting for C++23 instead of 20). But I’m getting ahead of myself…

There's always a catch

… let me be clear: I'm not promising a timeline for getting to a 1.0 that is ready to use - let alone replace Catch2. So if you're looking for a test framework today, I would still recommend Catch2. But I'm already at a point where I can see significant value in this reboot.

In the meantime, consider this experimental - and an opportunity to explore new language features. Since I will be largely retreading ground from a C++03/11 code base, but starting, again, from scratch with C++17, 20 and 23 features, this is a great opportunity to see what a difference these language evolutions make to a real world codebase, and what new opportunities it opens up.

So I'm going to be talking, here, about the process of writing Catch23 in upcoming posts. Watch this space!


Please submit or upvote, here - or follow through to comment on Reddit