Catch the advice

This will be a very short post to trace my solution to a strange error message I had from the linker while I was trying to modernize one of my first TDD project. The very short message is: Unless you have to provide your own main function the test harness and you are getting linker errors, check the CATCH_CONFIG_MAIN macro definition on first place, be sure it appear before the catch header file inclusion.

Here is the long story

My first attempt to TDD was with gtest + gmock but that framework has the relevant (to me) drawback to require quite a complex configuration of the test harness as it requires to make and link a couple of libs. Well, it is not a really big effort but I want a quick and simple setup for my test harness so that it can be in place in minutes. My current test framework of choise is Catch by Phill Nash, I think it is great cause:

  • requires only a single header file into your test project
  • has no limits to test names
  • enables you write tests in BDD style
  • doesn't requires cutting edge compiler

The test project I was trying to convert, used some london school style as you might expect by gmock involvement, but catch doesn't have support (AFAIK)for mock objects creation by itself. Therefore I started to find a quick and simple mock framework with not too much preprocessor magic involved. I found FakeIt and decided to give it a try as it also is a single header library and it apply explicitelly as a Catch companion.

Linker complains

FakeIt comes with a single header version created on purpose for Catch integration, compiling the first test has gone like a breeze, but the linker complained about unresolved symbols.

It was about:

public: __thiscall Catch::SourceLineInfo::SourceLineInfo(void)
public: __thiscall Catch::SourceLineInfo::SourceLineInfo(char const *,unsigned int)
public: __thiscall Catch::AutoReg::AutoReg(void (__cdecl*)(void),struct Catch::SourceLineInfo const &,struct Catch::NameAndDesc const &)
public: __thiscall Catch::ResultBuilder::ResultBuilder(char const *,struct Catch::SourceLineInfo const &,char const *,enum Catch::ResultDisposition::Flags,char const *)
public: void __thiscall Catch::ResultBuilder::captureResult(enum Catch::ResultWas::OfType)
public: void __thiscall Catch::ResultBuilder::react(void)

as you know, linker errors are a mess, this was just a subset. Clearly those error are about Catch or its integration with FakeIt. My first attempt to solve was update to latest Catch version but this didn't solve. Then started to search for the definitiions the linker complains about into the code and found them obscured by #ifdefs. Some further inquiry lead me to check for the CATCH_CONFIG_MAIN macro definition which was supposed to be defined to let Catch provide a CLI interface for my test harness. That macro was not defined (my fail), simply defining it solved the linker problems. Next step is to check whether those definitions should be there or not when user provides his own main method.

Final advice

Unless you have to provide your own main function the test harness and you are getting linker errors, check the CATCH_CONFIG_MAIN macro definition on first place, be sure it appear before the catch header file inclusion.