simple-test =========== simple unit testing for C implemented as a single header file brief summary ------------- Your tests should be written as a single .c file separate from the body of text containing your functionality to be tested. Write the tests, include simple-test.h, point your compiler at the necessary files / libs, and you're done! an example ---------- consider the following simple program: ```c /* keep this include at the very top of the file */ #include "simple-test.h" /* any global variables, functions, other inclusions, etc. * should be declared here */ #include "header_with_stuff_to_be_tested.h" int add_here(int a, int b) { /* ASSERT / ECHO statements within functions * like this are perfectly valid. this is * useful for writing initialisation functions * called at the beginning of multiple TESTs */ ECHO("this is the local add"); /* ensure a and b are non-0 using generic ASSERT */ ASSERT(a); ASSERT(b); return a + b; } /* must come before all TESTs */ BEGIN_TEST /* the string is a description of the test being run */ TEST("check add()'s return value") { /* mixing different precisions is allowed */ long var1 = 2; int8_t var2 = 2; /* add is a function included from our hypothetical * header_with_stuff_to_be_tested.h */ ASSERT_INT_EQ(var1+var2, add(var1, var2)); /* generic versions of ASSERTions are also valid, * but only for number types (int / uint / float ) */ ASSERT_EQ(var1+var2, add_here(var1, var2)); } TEST("compare two arrays of strings") { int i; char array1[][10] = { "str1", "str2", "str3", }; char array2[][10] = { "str1", "str2", /* matching will fail here */ "different", }; for(i = 0; i < sizeof(array1) / sizeof(char[10]); i++) { /* ECHO can be used to print (with pretty * formatting) the current state within the * test */ ECHO("checking strs at i == %i", i); ASSERT_STR_EQ(array1[i], array2[i]); } } /* must come after all TESTs */ END_TEST ``` running this test, the output might look something like this: ![run 1](doc/run-01.png) if var1 in the first test were changed to 0, like so: ```c /* mixing different precisions is allowed */ long var1 = 0; int8_t var2 = 2; ``` ASSERT(a); in add_here() would fail like this: ![run 2](doc/run-02.png) if array2 were modified instead so the third strings would match, a successful output would look like this: ![run 3](doc/run-03.png) defined macros -------------- | **NAME** | **DESCRIPTION** | |---------:|:----------------| | **BEGIN_TEST** | must be included once, after includes and global declarations and before the first TEST statement | | **END_TEST** | must be included once, after the final TEST statement | | **TEST()**{} | declare a test, described by `description`, which consists of statements between the {} | | **ECHO(<...>)** | print a formatted description of the state within the current test | | **ASSERT<_type_name><_condition>()** | assert, on either one or two `args` of type `_type_name`, that `_condition` is true | valid `_type_name`s and `_conditions` for ASSERT statements are: | **_type_name** | **DESCRIPTION** | |---------------:|:----------------| | | if the _type_name is omitted, generic assertions which automatically determine type are used. valid only for number types, i.e. int, unsigned, double. | | **_BOOL** | operate on args of type `bool` | | **_INT** | operate on signed integer types | | **_UINT** | operate on unsigned integer types | | **_HEX** | operate on unsigned integer types. output with %X formatting | | **_FLOAT** | operate on floating point types | | **_PTR** | operate on generic pointer types. casts to void* | | **_CHAR** | operate on args of type `char` | | **_STR** | operate on strings pointed to by args of type `char*`. | | **_WCHAR** | operate on wide character types | | **_WSTR** | operate on wide strings pointed to by args of type `wchar_t*` | | **_condition** | **DESCRIPTION** | |---------------:|:----------------| | | if the _condition is omitted, fail if the single arg is a "not" value, i.e. NULL, 0, '\0' etc. | | **_EQ** | fail if the two args are not equal | | **_NEQ** | fail if the two args are equal | | **_G** | fail if the first arg is not greater than the second | | **_GEQ** | fail if the first arg is not greater than or equal to the second | | **_L** | fail if the first arg is not less than the second | | **_LEQ** | fail if the first arg is not less than or equal to the second | note ---- this makes heavy use of _Generic, so C11 support is required tested successfully both with gcc and clang