Getting started with C++ unit testing

I have been “living” in the C++ world since the very beginning (of my career). But lately I’ve noticed a rising interest in C++ unit testing and even got to speaking about it in NDC Oslo.  But there’s more to it than testing 10 year old C++ legacy code – it is my opinion that C++ is the most innovative language as far as unit testing goes. So if you’re not a C++ developer (and survived this post so far) you should check some of the innovation in the C++ unit testing space.

Because I couldn’t find one I’ve decided to compile a list of resources for C++ developers who wants to learn more about TDD and unit testing, based on my own experience and preferences.

The Books

I love reading books, I know I might be a part of a dying breed but I think they contain knowledge in an organized way that is missing from other resources (present medium included). In the C++ unit testing space there are two books I read many years ago but I still find useful in my daily work:

Modern C++ Programming with Test-Driven Development (code better, sleep better)

lotdd.jpgYou gotta love this book. It has a great name and good content. It takes by the hand showing you how to TDD your code – one step at a time (as TDD should be practiced). The book focus mainly on GTest and some of the later chapters use CppUnit.

Although I don’t agree with everything in this book, I found it to be useful for anyone who wants to start learning about TDD and unit testing in the C++ world. Keep in mind that things have changed a bit in the time that passed since this book was published but the basics are still the same. I wrote a review of this book three years ago – and I still stand by it.

Working effectively with legacy code

51H6SHy6g2L._SX374_BO1,204,203,200_.jpg

This book is a timeless classic – and it has helped me solve hard, difficult and frustrating problems – many times. Once you learn about unit testing and TDD you would want to apply your new powers in the real world – and then you must read this book.

You don’t have to be a C++ developer I but it helps since some of the examples and techniques are in C++.

This book shows you how unit testing can save your code from a slow and painful death and teaches developers what to do when facing a huge, old, complex and convoluted legacy code.

The frameworks

To get you up and running you’ll need a good unit testing framework and probably a good mocking framework as well. The good news is that there are many styles to choose from with many innovative abilities which transcend the classic unit testing framework styles. I have to confess that I haven’t used all of the possible unit testing frameworks out there but I have used quite a lot of them – and the following list is built using only my (incomplete) experience

Unit testing frameworks

  • GTest/Gmock – this power couple has been the standard de-facto of C++ unit testing. In fact for along long time GMock was the only production grade mocking framework in the C++ world. The advantage is that if you have GMock you get GTest fully integrated in the same package. The downside is that you need to build GTest/GMock using the exact configuration as the project you’re trying to test – which can be a pain.
  • Catch – This is my new favorite unit testing framework (not just in C++). Deployment is done by including a single header file in your test project and you’re ready to go. Catch has many cool features – a single, powerful assert, strings for test names and an amazing feature called “sections” – you can read more about it in a blog post I wrote: “Catch – multi-paradigm automated test framework for C++“. Catch has made such an impact with it’s simple yet powerful capabilities that several C++ framework such as DocTest and lest have adopted them and “catch like C++ unit testing framework is becoming a way to categorize a framework just like “xUnit testing framework” was used until now.
  • Mettle – many good ideas in this framework, which is a bit different from others. I like the assertions (fully customization) and different syntax it brings with it. I think that this is the kind of framework that would help us better understand and use unit testing.
  • Boost.Test – part of boost library and used in some projects. I have not had a lot of time to use it but I found it a bit too verbose but I like to give it another try before deciding.

Mocking frameworks

For a long long time GMock was the go to framework for C++ mocking. It comes boundled with GTest and for crying out loud – it was created by the all mighty Google.

Today there are other options such as Trompeloeil which is deployed by including a single header file and has syntax I enjoy using. and FakeIt which is a cool, amazing library which helps developers write fake objects with very minimal code in a syntax that might be familiar to you if you ever using Mockito (Java) or any .NET mocking framework out there. On top of that there’s HippoMocks – although I’ve yet to try it in a client environment seems like another option C++ developers (myself included) might want to look into.

If you want to see the syntax of each check this repository on GitHub and you should check the recording of my NDC Oslo session: C++ Unit testing – the good, the bad & the ugly.

Other resources

Conferences

There are many good talks about C++ unit testing and I wish I could see them all – or at least know about all of them, if you know of a recording I forgot to mention – please let me know in the comments section.

My C++ unit testing/testing legacy C++ code sessions can be found at the recording section of this blog.

Yes it’s Catch again – explained by it’s creator Phil Nash (from Meeting C++):

One more session by a framework creator:

Online courses

There are not many (read: none that I know of) courses on C++ unit testing and so a year ago I’ve decided to remedy that by recording two courses for Pluralsight:

I’ve enjoyed creating those courses and I hope other developers find them usful.

Is that it?

This is the resource I thought would be useful for C++ developers who what to start unit testing (TDD’ing) their code and do not know where to start. I’m sure there are other good resources – which I would like to learn about. So in case I forgot or more likely was not aware of a cool library, online course or guru – just let me know.

And until then – happy coding…

10 thoughts on “Getting started with C++ unit testing

  1. Thanks for the shout-out to Catch 🙂
    It’s a shame you picked probably my worst Catch talk to use as an example. I’d probably go with my Meeting C++, or NDC Oslo ones (https://www.youtube.com/watch?v=C2LcIp56i-8 and https://vimeo.com/131632252).
    Note I’m also back on the road with an updated Catch talk – particularly talking about Catch2.

    Also missing here is mention of HippoMocks – another great mocking framework for C++ (Peter Bindels (HippoMocks), Björn Fahller (Trompeloeil) and I know each other quite well and have been talking about better integrating our respective frameworks).

    1. Sorry about that, I’ll update the link, as for HyppoMock I think I need more experience using it before I can talk about it but I’ll add a link as well. BTW Did you had the chance to look into FakeIt, I’ve been using it for the last few months and it works without any boilerplate code – but has a few limitations the other frameworks do not have.

  2. After reading most of the first book, I gave Gtest a try. Two simple tests, one test file, two C++ headers, using cmake to build. Build time: about 3s. Since you said that catch2 was your “new favorite”, I tried that (v2.13.9) on the same tests. The only structural difference was with Gtest I used a fixture for both tests but with catch2 I used two SECTIONs. Used FetchContent in cmake. Build time: almost 13s! Some years ago, I had tried catch2 and I also recall horrendous build times. Considering that the book says TDD should *only* be used with fast tests (yes, the tests are fast–a few ms), such long build times appear to defeat the purpose of using the much vaunted “single header file”.

    1. Hi Joe,

      I think that’s one of the reasons that Catch2 is moving away from single header to CMake file, you might also consider checking out DocTest which has better build times. And you can always build Catch2 into a dll/so if the build times are too long for your needs.

      Having said that I would gladly “pay” a few seconds or even minutes per test run (not per test).
      I think that Sections and Require are a big difference when writing and more importantly reading unit tests, it help you write netter tests and avoid the pitfalls that test fixtures help you create, instead of breaking you tests into two (or more) places then starting to create a “one size fits all” initialization you can sue sections where they are available, the 2nd benefit is that test names are simple descriptive text, no more using “descriptions” underscores or upper case letters in a futile effort to explain what your test does. And finally a single Require that uses code instead of dozens (hundreds in GTest) of assertions helps you write proper checks.

      1. I’m afraid the “Short Answer” on that page didn’t register (if I read something like it, elsewhere in the intro docs, or in the presentations/posts I’ve watched/read). Having a test_main.cpp with just those two lines changes the picture quite a bit. The first build takes about 13s, as before, but subsequent builds after just touching the test file *without* the CATCH_CONFIG_MAIN, run in about 3s, or about the same time as Gtest. OTOH, applying the same technique to Doctest, result in test runs of a bit over 2s. So thanks, Phil. I *will* give Catch2 a further look.

Leave a Reply to Phil Nash Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.