L_TEST
is a minimalistic and simple Unit-Test framework, designed with bare-metal embedded targets in mind.
This implementation is heavily inspired by Martin Dørum's great work on Snow, check it out. I've essentially implemeneted a very stripped down version of it, both as an exercise and as a means to meet my immediate needs on an ongoing project.
Add l_test.h
and l_test.c
to your project.
In l_test.h
, supply a printf
compliant function, as well as a fuction to measure system uptime in millseconds (i.e., an Arduino-like millis()
):
/// Supply your printf compliant function
#define __L_PRINTF(...) printf(__VA_ARGS__)
// Supply a function to return a wall time (in ms)
#define __L_MILLIS millis
Test cases are grouped in modules, which kind of follows the syntax format in Snow. Define a module, and within it, appropriate test cases. For example:
int add(int a, int b) {
return a + b;
}
L_TEST_MODULE(simple_test, "Test routines for some basic functions.") {
L_TEST_CASE("Simple integer math") {
int a = 3, b = 2;
L_TEST_ASSERT(add(a, b) > a);
L_TEST_ASSERTEQ_INT(add(a, b), 5);
}
}
Somewhere in your project (global scope #define
, or with a -D
compilation flag), define L_UNIT_TESTS
.
Then, execute l_test_main()
. That's it.
Define a test module, with a name and a string description. Test cases should be defined within its body.
Define a test case with a description. Test cases can only be defined withen a L_TEST_MODULE body.
Quick shorthand to disable a particular test module. Module's contents will be compiled, but not executed.
Quick shorthand to disable a particular test case. Case's contents will be compiled, but not executed.
Asserts that the value is non-zero. If the assertion fails, an error message is printed and the test case is aborted.
Asserts that the value is zero. If the assertion fails, an error message is printed and the test case is aborted.
Asserts that val == ref
, assuming integer values.
If the assertion fails, the expected and current values will be printed, and the test case will be aborted.
Asserts that the RPD between val
and ref
is less than 0.1%.
If the assertion fails, the expected and current values will be printed, and the test case will be aborted.
Executes a strcmp
between the two supplied strings.
If the assertion fails, the expected string and the supplied string are printed.
Executes a memcmp
between the two supplied buffers. If the assertion fails, an error message is printed and the test case is aborted.
In its current form, this library does require a printf
compliant call. Support for floating point prints is not assumed.
Also, the library makes use of two GCC extensions, __attribute__((unused))
and __attribute__((constructor))
,
so make sure that these are available on your system.
Lastly, the constructor calls link the test modules in a queue for execution, which means that, AFAIK, you can't fully define the order in which modules will be run.