TDD with Compiler Explorer

Compiler Explorer (CE) has been around for several years now. When it first appeared on the scene, it immediately became an invaluable tool. Its ability to show generated assembler from given source code across many different compilers and ISAs (Instruction Set Architectures) is “mind-blowing”. We use it extensively when teaching as it allows you to clarify the effect your code can have on both performance and memory usage. 

However, rather than limiting itself to only showing generated assembler, recent developments include the ability to execute the code and examine the program output. Having online support for this is nothing especially new (e.g. ColiruWandbox, etc.), but it’s helpful to have it within one tool.

For example, given a simple “hello, world!” program, we see the standard output in a new tab:

Test-Driven Development

One of the significant benefits to come out of the growth of Agile development is the acceptance that unit testing is just part of the development cycle, rather than a separate activity after coding.

Agile unit-testing, better known as Test-Driven Development, or TDD for short, has lead to a growth of unit-test frameworks, all based around the original xUnit model, typified by GoogleTest (gtest). 

As part of the continuing improvements and feature extensions, CE added support for various libraries to be included as part of the build. Included in this set is support for gtest, as well as two other, more modern, test frameworks; Catch2 and doctest.

Using Google Test with Compiler Explorer

Writing tests with CE using Google Test is relatively straightforward, with the only differences to using gtest locally a single file contains both the Unit-Under-Test (UUT) and the test code.

The equivalent of a test “hello, world!” for gtest looks thus:

#include "gtest/gtest.h"

TEST(setup_test_case, testWillPass)
{
   ASSERT_EQ(42, 42);
}

When you first type this into CE, the compilation output window will report that the compilation failed. Examining the error message

<source>:1:10: fatal error: gtest/gtest.h: No such file or directory
    1 | #include "gtest/gtest.h"
      |          ^~~~~~~~~~~~~~~
compilation terminated.
Compiler returned: 1

This indicates the Google Test header ‘gtest.h’ cannot be found. To fix this, we have to include the Google Test library. 

Finally, we can run the program and see the test result output. The Google Test library must likewise be added to the execution view. However, as we have not specified the main function, we must include the linker option ‘-lgtest_maind’ to pull in the Google Test library with main defined (of course you still have the capability to defined your own test main). 

Example: https://godbolt.org/z/88jqPG

And there we have it, an online capability to use Google Test. 

Catch2

With the release of C++11, specific changes to the language made it easier to start writing ‘header-only’ libraries (which has got steadily easier with C++14, 17 and 20). Catch2, developed by Phil Nash, was one of the first header-only xUnit test libraries. Header-only libraries significantly simplify build dependencies, especially when moving towards Agile-based Continuous Integration (CI) strategies.

Setting up Catch2 is similar to Google Test, but does deviate from the tutorial on the Catch2 repo. Three items of note (at the time of writing):

  • You must use the ‘3.0.0-preview2’ library version in Compiler Explorer.
  • You must include the header “catch2/catch_test_macros.hpp” rather than just “catch.hpp”
  • You must include the linker directive ‘-lCatch2Main’

Example: https://godbolt.org/z/dKPdo9

doctest

As stated on the doctest GitHub repo:

doctest is modeled after Catch and some parts of the code have been taken directly.”

doctest’s major USP is it is very fast at both compilation and execution. It is my preferred C++ unit-test framework.  

 Thankfully, doctest doesn’t require any specific flags or settings to use with Compiler Explorer. It just works!

Example: https://godbolt.org/z/b7o4TY

Summary

Obviously, using these test frameworks doesn’t replace using them within a local project. But the fact files can both be loaded and stored to the local file system means there is now the opportunity to study modern C++ using Compiler explorer. Also, for anyone new to TDD and xUnit test frameworks, it offers a simple, easy-to-use environment for experimentation.

I would like to thank both @Partouf and @amorton for all their help guiding me through the subtleties of getting these example to build correctly. 

Dislike (0)

About Niall Cooling

Co-Founder and Director of Feabhas since 1995. Niall has been designing and programming embedded systems for over 30 years. He has worked in different sectors, including aerospace, telecomms, government and banking. His current interest lie in IoT Security and Agile for Embedded Systems.
This entry was posted in Agile, C/C++ Programming, Testing and tagged , , , , , , , . Bookmark the permalink.

Leave a Reply