A few months ago, I was at a conference and I ran a session called Design Sense with a friend of mine, Emmanuel Gaillot. We presented over a hundred snippets of code and asked participants to rate them. The idea was to see just how much we could all agree on good design. We gathered a lot of information and learned quite a bit.

The examples came from all over. Many were from open source projects. Some were examples from the web (a couple of the highest scoring snippets were excerpts from Python code that Peter Norvig wrote), and some of them were from open source things that Emmanuel and I had done in the past. When we asked people to rate them, we didn’t tell them who had written them, so it was fun to see just what they thought of some of our code. It turns out that there was one snippet of mine that I was particularly proud of, but it didn’t score very high. Here it is:

#define TEST(name,classUnderTest) \
  class classUnderTest##name##Test : public Test \
  { \
  public: \
    classUnderTest##name##Test () : Test (#name "Test") {} \
    void runTest (TestResult& result_); \
  } classUnderTest##name##Instance; \
  void classUnderTest##name##Test::runTest (TestResult& result_) 

Yeah, I know. It does look ugly, but here’s the story. That macro is from a C++ testing harness that I wrote a long time ago, and ugly as it was, I had good intentions. The idea was to make it drop dead easy for people to write test cases in C++. And, I didn’t want to use C++ templates either. At that time, it seemed that there were too many people who had compilers that didn’t support them very well.

In JUnit, it’s easy. You write a new class, mark it with some JUnit annotations, and the framework takes over. JUnit uses reflection to find the class and find the appropriate testing methods. Then it creates the test objects, and runs them. It’s all hands-free. In C++, however, there is no reflection, so you are stuck registering test cases, grouping cases into suites, and registering suites.

The goal was to make writing and registering a test as simple as this:

TEST(recording, Vise)
{
  vise.openSection("aSection");
  ASSERT_TRUE(vise.isRecording());
}

And that macro does the job. Here’s how:

The TEST macro takes two tokens as arguments and uses them to construct the name of a new class using the token pasting operator (##). The macro defines the class and declares an instance that is created when the program starts up. The class of that instance inherits from a class named Test whose objects register themselves with a global test runner when they are constructed. The macro ends with the declaration of a method named runTest. People who are using the macro supply code in a set of braces after the macro call. That code becomes the body of runTest.

Once all of that machinery is there, you can create an arbitrary number of tests:

TEST(recording, Vise)
{
  vise.openSection("aSection");
  CHECK(vise.isRecording());
}

TEST(gripAValue, Vise)
{
  vise.openSection("aSection");
  vise.grip("3", __FILE__, __LINE__);
  vise.closeSection();

  CHECK_FALSE(vise.isRecording());
  LONGS_EQUAL(1, store.size("aSection"));
}

The thing that makes the C++ preprocessor so powerful is the fact that you can use it to create unhygienic macros – it’s all just simple text replacement and you can replace text anywhere, even across language constructs. TEST uses this power to generate a declaration that should be followed by a block. It’s almost Ruby-esque that way.

I hate C++’s preprocessor, but I love it also. When you’re in a corner and you need to create an abstraction that doesn’t really align with C++’s grammar, you’re not completely lost. You do, however, pay a price.

It’s been a while since I wrote that code, and I’ve found better ways of doing similar things since then. But, sometimes making one thing ugly allows you to make many other things nice, and that can be a fair trade.

Note: The test macro above was inspired by a similar macro in Mike Hill's TestKit framework. The idea lives on in UnitTest++ and a few other C++ testing frameworks.