Simple macros for Check
During my vacation I have had the opportunity to add unit testing to SCEW (Simple C Expat Wrapper). I looked at various C unit testing frameworks and I decided to use Check. Most of them follow the xUnit approach, but I chose Check because tests run in a separate address space other than the test runner.
I found that writing test cases was a bit hard using Check’s syntax, for example following the manual you can write this integer check:
fail_unless (money_amount (m) == 5, "Amount not set correctly on creation");
This is fine if you are reading the code, but if the check fails the output doesn’t show you what the actual or expected values are, so the manual suggests changing it for:
fail_unless(money_amount (m) == 5, "Amount was %d, instead of 5", money_amount (m));
which is quite better than the first one, but to painful if you have to write it for every check. So, why not write a helper macro that checks for integers, prints the actual and expected values and also shows you the check that is being done?
#define CHECK_INT(A, B, MSG, ...) \ do \ { \ enum { MAX_BUFFER = 250 }; \ static char buffer[MAX_BUFFER]; \ sprintf (buffer, MSG, ##__VA_ARGS__); \ fail_unless ((A) == (B), \ "(%s) == (%s) \n Actual: %d \n Expected: %d \n %s", \ #A, #B, A, B, buffer); \ } \ while (0);
With this macro you can now write code like this:
CHECK_INT (scew_list_size (list), N_ELEMENTS, "Number of children found searching by name");
which is really easy to read and in the test’s output you can see the actual and expected values, the performed test and the user message clarifying the intention of the check.
element.c:205:F:Core:test_search:0: (scew_list_size (list)) == (N_ELEMENTS) Actual: 1 Expected: 12 Number of children found searching by name
The same happens with strings, so instead of writing this:
fail_if (strcmp (money_currency (m), "USD") != 0, "Currency not set correctly on creation");
or this:
if (strcmp (money_currency (m), "USD") != 0) { fail ("Currency not set correctly on creation"); }
we can write a string checking macro that shows the actual and expected strings and the check being done:
#define CHECK_STR(A, B, MSG, ...) \ do \ { \ if (strcmp ((A), (B)) != 0) \ { \ enum { CHECK_MAX_BUFFER = 250 }; \ static char buffer[CHECK_MAX_BUFFER]; \ sprintf (buffer, MSG, ##__VA_ARGS__); \ fail ("(%s) == (%s) \n Actual: %s \n Expected: %s \n %s", \ #A, #B, A, B, buffer); \ } \ } \ while (0);
As before, this would be the new output:
element.c:97:F:Core:test_accessors:0: (scew_element_name (element)) == (NAME) Actual: new_root Expected: root Element name do not match
Well, this is not a big deal, but I have found it quite useful. Below, is the list of macros I am using right now:
#define CHECK_INT(A, B, MSG, ...) \ do \ { \ enum { MAX_BUFFER = 250 }; \ static char buffer[MAX_BUFFER]; \ sprintf (buffer, MSG, ##__VA_ARGS__); \ fail_unless ((A) == (B), \ "(%s) == (%s) \n Actual: %d \n Expected: %d \n %s", \ #A, #B, A, B, buffer); \ } \ while (0); #define CHECK_STR(A, B, MSG, ...) \ do \ { \ if (strcmp ((A), (B)) != 0) \ { \ enum { CHECK_MAX_BUFFER = 250 }; \ static char buffer[CHECK_MAX_BUFFER]; \ sprintf (buffer, MSG, ##__VA_ARGS__); \ fail ("(%s) == (%s) \n Actual: %s \n Expected: %s \n %s", \ #A, #B, A, B, buffer); \ } \ } \ while (0); #define CHECK_PTR(A, MSG, ...) \ do \ { \ enum { MAX_BUFFER = 250 }; \ static char buffer[MAX_BUFFER]; \ sprintf (buffer, MSG, ##__VA_ARGS__); \ fail_unless ((A) != NULL, "(%s) != NULL \n %s", #A, buffer); \ } \ while (0); #define CHECK_NULL_PTR(A, MSG, ...) \ do \ { \ enum { MAX_BUFFER = 250 }; \ static char buffer[MAX_BUFFER]; \ sprintf (buffer, MSG, ##__VA_ARGS__); \ fail_unless ((A) == NULL, "(%s) == NULL \n %s", #A, buffer); \ } \ while (0);
Update 2007/08/11: I have updated the macros so variable number of arguments are allowed (see variadic macros).