diff options
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 158 |
1 files changed, 135 insertions, 23 deletions
@@ -1,5 +1,5 @@ simple-test -============== +=========== simple unit testing for C implemented as a single header file @@ -8,33 +8,145 @@ 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, and you're done! see this -[documentation (pdf)](https://github.com/shmibs/simple-test/blob/master/README.pdf?raw=true) -for more details (because github markdown is annoying and doesn't -let me colour things). +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 appear before all tests and after all global variable declarations -**END_TEST**|must appear at the end of your test program -**CLEANUP(statements)**|this defines a list of statements to run when the test exits, either successfully or on a failure. it isn't necessary for a test to run, but, if it does appear, it must be after the declaration of all variables to which it makes reference. -**RETURN()**|place at the end of a test which uses CLEANUP to ensure it is called before the test exits. i couldn't find any way around this without using more than just one header file, so i hope it isn't too annoying. -**STATE(description)**|show a prettily-formatted description of the program's state during a test. takes printf-style arguments. -**EXPECT_ZERO(summary, arg)**|fail if `arg` does not resolve to 0 -**EXPECT_ONE(summary, arg)**|fail if `arg` does not resolve to 1 -**EXPECT_GREATER_THAN_ZERO(summary, arg)**|fail if `arg` does not resolve to a value greater than 0. this will be replaced with more generic integer comparisons soon. -**EXPECT_INT(summary, arg1, arg2)**|fail if `arg2` does not match the expected integer value `arg1` -**EXPECT_EQUAL_INT(summary, arg1, arg2)**|fail if `arg1` and `arg2` are not equal -**EXPECT_UNEQUAL_INT(summary, arg1, arg2)**|fail if `arg1` and `arg2` are equal -**EXPECT_STR(summary, arg1, arg2)**|fail if string `arg2` does not match the expected string value `arg1` -**EXPECT_EQUAL_STR(summary, arg1, arg2)**|fail if `arg1` and `arg2` are not equivalent strings -**EXPECT_UNEQUAL_STR(summary, arg1, arg2)**|fail if `arg1` and `arg2` are equivalent strings +| **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(<description>)**{} | 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>(<args>)** | 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*` | -**WARNING: this will work fine in gcc, but it uses the non-standard -macro \__COUNTER__ and nested functions.** +| **_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 |