Check

Language: C

Testing

Check was created to provide an easy-to-use framework for C unit testing, similar to frameworks available in other languages like JUnit for Java. It supports test cases, setup/teardown functions, and reporting, helping C developers maintain robust and reliable code.

Check is a unit testing framework for C that allows developers to write test cases for their code in a simple and structured way. It provides assertions, test fixtures, and test suites to ensure code correctness.

Installation

linux: sudo apt install check
mac: brew install check
windows: Use MSYS2 or build from source via https://libcheck.github.io/check/

Usage

Check allows you to define test cases with `START_TEST` and `END_TEST` macros, group them into test suites, and run them with the `SRunner`. It supports setup/teardown functions for initializing and cleaning resources before and after tests.

Simple test case

#include <check.h>
#include <stdlib.h>

int add(int a, int b) { return a + b; }

START_TEST(test_add) {
    ck_assert_int_eq(add(2, 3), 5);
}
END_TEST

int main(void) {
    Suite *s = suite_create("MySuite");
    TCase *tc = tcase_create("Core");
    tcase_add_test(tc, test_add);
    suite_add_tcase(s, tc);

    SRunner *sr = srunner_create(s);
    srunner_run_all(sr, CK_NORMAL);
    int number_failed = srunner_ntests_failed(sr);
    srunner_free(sr);
    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

Defines a simple test for the `add` function using `ck_assert_int_eq` and runs it via a test suite and runner.

Using setup and teardown

START_TEST(test_example) {
    ck_assert_int_eq(42, *ptr);
}
END_TEST

void setup(void) { ptr = malloc(sizeof(int)); *ptr = 42; }
void teardown(void) { free(ptr); }

Demonstrates initializing resources before a test and cleaning them up afterward.

Multiple test cases in a suite

START_TEST(test_add) { ck_assert_int_eq(add(2,3), 5); } END_TEST
START_TEST(test_subtract) { ck_assert_int_eq(subtract(5,3), 2); } END_TEST
TCase *tc = tcase_create("Math");
tcase_add_test(tc, test_add);
tcase_add_test(tc, test_subtract);
Suite *s = suite_create("MathSuite");
suite_add_tcase(s, tc);

Groups multiple test cases into a single test suite for organized execution.

Skipping tests

START_TEST(test_skip) { ck_abort_msg("Skipping this test"); } END_TEST

Shows how to skip a test dynamically with a custom message.

Floating-point assertions

START_TEST(test_float) { ck_assert_double_eq_tol(3.1415, pi, 0.0001); } END_TEST

Demonstrates asserting approximate equality for floating-point values with a tolerance.

Error Handling

Segmentation fault in a test: Check pointer usage and ensure proper memory allocation/deallocation in setup and test cases.
Assertion failures: Review the failed assertion message and debug the logic of the function under test.

Best Practices

Group related test cases into suites for easier management.

Use setup/teardown functions to handle resource allocation and cleanup.

Keep tests independent to avoid side effects between tests.

Use meaningful assertion macros (`ck_assert`, `ck_assert_int_eq`, `ck_assert_double_eq_tol`, etc.) for clarity.

Run tests frequently during development to catch regressions early.