Extension for the unit testing framework for C that adds automatic tests collection using the constructor attributed functions. The usage is pretty much the same as for the origin Check test framework except it removes tedious registration of the test cases. You still can do it manually if you require it, but most of the testing can be done without need of manual test registering.
You still have to study the Check API and usage so you can use this library.
To compile this project you have to run:
meson setup builddir meson compile -C builddir
Subsequent installation can be done with meson install -C builddir
.
The expected usage is that you link the libcheck_suite
with C files containing
your tests and tested code. The Check Suite provides main
and thus there is no
need for any initialization.
Tip
|
You might want to read the source files itself, as they are pretty short.
Another very good source for usage examples are Check Suite test’s in the
tests directory.
|
You can also read the test example in this repository.
The single C file is expected to be single C test suite. It requires unique name
defined in it and it is common to be same as file name but that is not required.
The suite name has to be defined as macro #SUITE "foo"
before you include
check_suite.h
:
#define SUITE "foo" #include <check_suite.h>
Tests that are part of single suite are also grouped to test cases. Every test case can have unique setup and teardown procedure. The test case can be defined as follows:
void setup_function(void) {} void teardown_function(void) {} const double timeout = 0; TEST_CASE(foo, setup_function, teardown_function, timeout) {}
You can pass NULL
for either of the functions. You can also pass drop the
latter arguments. The default for timeout
then is default Check timeout
(environment variable CK_DEFAULT_TIMEOUT
). The default for the
setup function is macro DEFAULT_SETUP
and for the teardown function is
DEFAULT_TEARDOWN
. You can define these macros before you include
check_suite.h
or they are set to NULL
.
There is also possibility to apply any other modifications to the test case by
writing some function body. The function gets current test case as argument
called tcase
. That is for example:
TEST_CASE(fee) { tcase_set_tags(tcase, "fee"); }
There are three types of types based on expected test. There is simple TEST
that is used most of the time. Then there is TEST_RAISE_SIGNAL
for signal
checking (note that this works only if you run every test in fork()
which is
default). And lastly there is TEST_EXIT
that checks exit code (same limitation
applies as for TEST_RAISE_SIGNAL
).
The simple test looks like this:
TEST(foo, check_foos) { ck_assert_int_eq(answer4everything(), 42); } END_TEST
The fist argument foo
is the test case name. The second argument is name of
the test.
The usage of TEST_RAISE_SIGNAL
and TEST_EXIT
are are pretty much the same
except that they expect additional argument. That is signal number in case of
TEST_RAISE_SIGNAL
and exit code in case of TEST_EXIT
:
TEST_RAISE_SIGNAL(foo, check_raise, SIGUSR1) { raise(SIGUSR1); } END_TEST TEST_EXIT(foo, check_exit, 1) { exit(1); } END_TEST
It is very common that we run the same test check with different data or just
incrementing values. For that reason there are loop tests. They allow you to go
trough integer value from some value to the other (always incrementing by 1).
The test is provided with loop variable _i
.
LOOP_TEST(foo, check_fooses, 0, 42) { ck_assert_int_lt(_i, 42); }
This checks if all numbers from 0 to 42 (excluding) are less than 42.
There are also variants LOOP_TEST_RAISE_SIGNAL
and LOOP_TEST_EXIT
. These
macros expect signal and exit code respectively as a third additional argument
(this starting index is fourth argument and ending index fifth).
The most common usage of the loop tests is to iterate over array that is used to
parameterize tests. To simplify this usage there is dedicated macro
ARRAY_TEST
and its variants in terms of ARRAY_TEST_RAISE_SIGNAL
and
ARRAY_TEST_EXIT
. Compared to the LOOP_TEST
the ARRAY_TEST
expects only
name of the array it is expected to iterate over. It provides on top of _i
(which is index to the array) also value from the array as _d
.
The common usage would look like this:
static const struct { const char *format; int value; const char *result; } check_printf_d[] = { {"%d", 42, "42"}, {"0x%x", 42, "0x2a"}, }; ARRAY_TEST(foo, check_printf, check_printf_d) { char *str = NULL; ck_assert_int_eq(asprintf(&str, _d.format, _d.value), strlen(_d.result)); ck_assert_str_eq(str, _d.result); free(str); }
Tip
|
The array is optional and if not specified then it is expected to be test
name with _d appended.
|
There is possibility to modify Check’s runner manually, although Check Suite is designed to automate that as much as possible. This is provided in case the default settings chosen by Check Suite are not ideal for you.
You can define function void check_suite_setup_cb(void)
. This function is
called right before tests are executed. You can use global variable
SRunner *check_suite_runner
in it.
Warning
|
The fork status is set to true by Check Suite and setting it to
false is going to break TEST*_EXIT macros.
|
This project contains basic tests in directory tests.
To run tests you have to either use debug
build type (which is commonly the
default for meson) or explicitly enable them using meson configure
-Dtests=enabled builddir
. To execute all tests run:
meson test -C builddir
You can also run tests with Valgrind tool such as memcheck
:
VALGRIND=memcheck meson test -C builddir