One thing I'm pretty doctrinaire about when it comes to this sort of thing is printing out more than just a simple message. Quite often, this makes the problem obvious with no need for deeper investigation.
To do this I have a bunch of macros like this:
/* check A and B are equal. */
#define EQ_II(A,B,M) (CheckEQII((A),(B),M,#A,#B,__FILE__,__LINE__))
You use it like this:
EQ_II(i,3,"blah blah blah");
CheckEQII looks roughly like this:
void CheckEQII(int64_t a,int64_t b,const char *message,const char *a_str,const char *b_str,const char *file,int64_t line) {
if(a!=b) {
printf("%s:%" PRId64 ": test failed: %s\n",file,line,message);
printf(" Values not equal.\n");
printf(" Got expr : %s\n",a_str);
printf(" Wanted expr : %s\n",b_str);
printf(" Got value : %" PRId64 " (0x%" PRIx64 ")\n");
printf(" Wanted value: %" PRId64 " (0x%" PRIx64 ")\n");
DEBUG_BREAK();
exit(1);
}
}
(DEBUG_BREAK breaks into the debugger if you're running in the debugger.)
The FILE:LINE notation is probably clickable in your favourite text editor. (For VC++, use "FILE(LINE):". Just do #ifdef _MSC_VER or something.) Very convenient if you run tests as part of the build.
And you can flesh it out for strings, arrays, floats, doubles, and all the rest. You can fit everything you need into about 500 lines.
This isn't quite as impressive as the 3 lines here, but compared to something like Catch - which is a huge amount of C++ code, crazy C++ code to boot, that adds literally seconds to your build time - and, no, the fact that seconds is a drop in the ocean in C++land is not an excuse - it's in the same ballpark. At least, its extra utility should prove, over the course of a project, in my view, commensurate with the extra LOC.