Use assertions in greatest
releasem suffix (e.g., ASSERT_EQm("msg", expected, actual)) which accepts a message string as the first argument.repository·release·Indexed 23 days ago
https://github.com/silentbicycle/greatestA small, portable, and lightweight C testing library contained in a single header file. It depends only on ANSI C89, uses no dynamic allocation, and is suitable for both embedded systems and general-purpose C/C++ applications. Version v1.5.0 provides a test runner with CLI filtering, randomized test shuffling, and a programmatic API for library integration.
m suffix (e.g., ASSERT_EQm("msg", expected, actual)) which accepts a message string as the first argument.greatest have both prefixed (e.g., GREATEST_SUITE) and unprefixed (e.g., SUITE) forms. These aliases are enabled by default. To disable them, #define GREATEST_USE_ABBREVS to 0.Every test case must end by calling one of the following macros to update internal bookkeeping and return from the test function:
PASS() / PASSm("msg"): Marks the test as successful. Prints a dot (verbosity 0) or the test name and message (verbosity >= 1).FAIL() / FAILm("msg"): Marks the test as failed. Always prints FAIL test_name: msg file:line.SKIP() / SKIPm("msg"): Marks the test as skipped. Skips do not cause the test runner to report failure. Useful for TODOs or environment-specific tests. Prints an 's' (verbosity 0) or the test name and message (verbosity >= 1).Instead of using GREATEST_MAIN_BEGIN(), you can integrate greatest into your own program as a library.
GREATEST_INIT() to initialize or re-initialize the framework.GREATEST_PRINT_REPORT() to print the report to GREATEST_STDOUT.greatest_get_report(&report) to retrieve the pass, fail, skip, and assertion counters.Equivalent programmatic functions for CLI flags:
greatest_stop_at_first_fail()greatest_abort_on_fail()greatest_list_only()greatest_set_exact_name_match()greatest_set_suite_filter(const char *filter)greatest_set_test_filter(const char *filter)greatest_set_test_exclude(const char *filter)greatest_get_verbosity()greatest_set_verbosity(unsigned int verbosity)A test is defined as a function that executes assertions and concludes with a status macro like PASS(), FAIL(), or SKIP(). Tests can be run individually using RUN_TEST(test_name) or grouped into suites using SUITE(suite_name) and executed with RUN_SUITE(suite_name).
To create a test runner, use the following boilerplate in your main function:
GREATEST_MAIN_DEFS(): Provides definitions for the runner.GREATEST_MAIN_BEGIN(): Initializes command-line options and the runner.RUN_SUITE(...) or RUN_TEST(...): Executes your tests.GREATEST_MAIN_END(): Displays the final results.#include "greatest.h"
/* A test runs various assertions, then calls PASS(), FAIL(), or SKIP(). */
TEST x_should_equal_1(void) {
int x = 1;
ASSERT_EQ(1, x);
PASS();
}
/* Suites can group multiple tests with common setup. */
SUITE(the_suite) {
RUN_TEST(x_should_equal_1);
}
/* Add definitions that need to be in the test runner's main file. */
GREATEST_MAIN_DEFS();
int main(int argc, char **argv) {
GREATEST_MAIN_BEGIN();
/* Tests can also be gathered into test suites. */
RUN_SUITE(the_suite);
GREATEST_MAIN_END(); /* display results */
}To use greatest, simply include the single header file greatest.h in your project. It is a lightweight, portable testing system that depends only on ANSI C89 and does not use dynamic allocation. Most features are optional, making it easy to integrate into existing C or C++ codebases.
#include "greatest.h"Since greatest does not include built-in coloring to remain portable, you can use provided scripts to format the output:
Color Output:
Pipe output through the greenest script (requires a Unix-like environment):
$ ./example -v | greenestTAP Format:
Convert verbose output to TAP version 13 format using the entapment awk script:
./example -v | contrib/entapmentTo prevent accidental coupling between tests, you can run suites or tests in a randomized order using SHUFFLE_SUITES or SHUFFLE_TESTS. These macros require a seed to ensure reproducibility.
Warning: Avoid running tests directly inside a SHUFFLE_SUITES block without a RUN_SUITE call, as the macro expands to a loop that will execute the code on every iteration.
/* Shuffling suites */
SHUFFLE_SUITES(seed, {
RUN_SUITE(suite1);
RUN_SUITE(suite2);
RUN_SUITE(suite3);
RUN_SUITE(suite4);
RUN_SUITE(suite5);
});
/* Shuffling tests */
SHUFFLE_TESTS(seed, {
RUN_TEST(test_a);
RUN_TEST1(test_b, 12345);
RUN_TEST(test_c);
RUN_TESTp(test_d, "some_argument");
RUN_TEST(test_e);
});Use greatest_set_test_suffix(suffix) to append a custom string to the name of the next test being run. This is useful for parameterized tests where you want to distinguish between multiple runs of the same test function in the output (e.g., test_name_suffix).
Key details:
#define-ing GREATEST_TESTNAME_BUF_SIZE (defaults to 128 bytes).RUN_TEST* call, making it safe to use stack-allocated buffers for the suffix.for (i = 0; i < row_count; i++) {
const struct table_row *row = &table[row_count];
greatest_set_test_suffix(row->name);
RUN_TEST1(test_with_arg, row);
}If a function called within a test returns an enum greatest_test_res and can cause test failures (using macros like PASS(), ASSERT(), or FAIL()), you must wrap the call in CHECK_CALL to correctly handle the returned test result enum.
TEST example_using_subfunctions(void) {
CHECK_CALL(less_than_three(5));
PASS();
}A collection of standard assertions for validating conditions, equality, and comparisons.
### `ASSERT(COND)`
Assert that `COND` evaluates to a true (non-zero) value.
### `ASSERT_FALSE(COND)`
Assert that `COND` evaluates to a false (zero) value.
### `ASSERT_EQ(EXPECTED, ACTUAL)`
Assert that `EXPECTED == ACTUAL`.
### `ASSERT_NEQ(EXPECTED, ACTUAL)`
Assert that `EXPECTED != ACTUAL`.
### `ASSERT_GT(EXPECTED, ACTUAL)`
Assert that `EXPECTED > ACTUAL`.
### `ASSERT_GTE(EXPECTED, ACTUAL)`
Assert that `EXPECTED >= ACTUAL`.
### `ASSERT_LT(EXPECTED, ACTUAL)`
Assert that `EXPECTED < ACTUAL`.
### `ASSERT_LTE(EXPECTED, ACTUAL)`
Assert that `EXPECTED <= ACTUAL`.