4 ms·
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
by tom_ 8y ago
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.
- masklinn 8y agoThat's why I love pytest. You just `assert` an expression, and on failure it'll break down each sub-expression and show whatever it yielded, plus by default it captures all output (stdout and stderr) and prints it out only on failure (so logging and other console output is not painfully annoying while testing) and the fixtures systems is just fantastic and parameterised tests make for much clearer data-driven (/table-driven) tests and the tests selection at the CLI is awesome. And all the complexity is in the test framework and runner, all you do is write def test_thing(a_fixture): assert foo(bar) == a_fixture.some_thing() or whatever.
- makmanalp 8y agoOn top of that, it'll compare complex structures to each other, so you could have a very large list of dicts that contain a custom data structure and it'll show you a diff and exactly where the mismatch is. Then it can auto-drop to the debugger and you can inspect previous variables to inspect the root cause, if not immediately apparent. Going back to C land, as much as I enjoy it, the tooling feels like the stone ages. I get that it's a lot harder for a language that compiles down to machine code, but dang.
- slavik81 8y agoStatic reflection is one of my most looked-forward-to features in C++2x. All the information needed to introspect complex data structures is available to the compiler. We just need a way to access it.
- gHosts 8y ago> pretty doctrinaire about And that is the problem. I have met teams that have gone into analysis paralysis about which unit test framework to use. I have met teams where one of the impediments to unit testing was "we don't have time to learn something that complicated, we don't understand why all this stuff is necessary". Answer: It isn't necessary. Get off your ass and start unit testing with the simplist framework possible. It's more important, way way more important to just do it than fuss about the framework. Like TFA. Once you have actually done that for awhile, someone will say, "Wouldn't it be nice if..." And _that's_ the time to introduce a framework. Or grow what you have. On a C project I elected to grow, the nice thing about it is test setup and teardown? It's exactly the same thing as process set up and teardown. So valgrind will tell you _exactly_ if anything leaked or was uninitialized!
- tom_ 8y agoOops, missed this at the time. Rant on... though only for posterity. There's various reasons why one might be doctrinaire about stuff. One common reason: you're an arsehole. Another one: you're an engineer, and this was what you were trained to do. A bonus third: you had it beaten into you by bitter experience. Me? Well, I will say that I'm not clever enough to be an engineer.