ACEUNIT(3)

NAME
aceunit, assert, AceUnit_runFixtures, AceUnit_fail - run unit tests with AceUnit

SYNOPSIS
#include <aceunit.h>

void AceUnit_fail(void);
void assert(scalar expression);

void AceUnit_run(const AceUnit_Fixture_t *fixtures[], AceUnit_Result_t *result);
bool runCatching(void(*code)(void));

extern AceUnit_Fixture_t *fixtures[];
int main(int argc, const char *argv[]);

DESCRIPTION
The functions described on this page are used to execute unit tests. The AceUnit_fail() function can be called from a unit test to abort the current test case and mark it failed. The assert() macro effectively does the same if its scalar expression evaluates to zero.

The AceUnit_run() function can be called to run fixtures. See the aceunit(1) program for how to generate fixtures. The runCatching() function is called by AceUnit_run() to wrap a test function, possibly catching signals.

The main() function is provided for convenience to execute the test cases. If you want to use it, you need to make sure that fixtures is defined, usually by auto-generating them using aceunit(1).

AceUnit provides different libraries / implementations that you can link with.

libaceunit-simple.a will simply run your test cases with no error handling at all and AceUnit_fail() calling abort(). This is a great option to simply get started with test-driven development in C.

libaceunit-setjmp.a will run your test cases wrapped in setjmp() / longjmp() and AceUnit_fail() calling longjmp(). This option should even work in freestanding environments as long as <setjmp.h> is available as well, which usually is the case. For embedded development, this is the default choice.

libaceunit-abort.a will run your test cases wrapped in setjmp() / longjmp() plus a signal handler for SIGABRT with AceUnit_fail() calling abort(). The signal handler catches SIGABRT and performs a longjmp() back to the runner. This is a good choice for hosted environments that do not support POSIX and thus have signal() but not fork() available, like native Amiga OS, Windows, or MS-DOS.

libaceunit-fork.a will run test functions wrapped in fork() catching eventual failures by detecting a non-zero exit code from the child process. This is the best choice for POSIX environments.

EXAMPLES
Consider the following module, which provides a function to see whether a year is a leap year:

    // File: leapyear.h
    #ifndef LEAPYEAR_H
    #define LEAPYEAR_H
    #include <stdbool.h>
    extern bool isLeap(int year);
    #endif
    // File: leapyear.c
    #include "leapyear.h"
    bool isLeap(int year) {
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    }

Then a unit test module could look like this:
    // File: leapyear_test.o
    #include <aceunit.h>
    void testLeapYears(void) {
        assert(isLeap(0));
        assert(isLeap(4));
        assert(isLeap(400));
    }
    void testNonLeapYears(void) {
        assert(!isLeap(1));
        assert(!isLeap(100));
    }

AceUnit could be used with the following command sequence:
    cc -c -o leapyear.o leapyear.c
    cc -c -o leapyear_test.o leapyear_test.c
    aceunit leapyear_test.o >unit_test.c
    cc -c -o unit_test.o unit_test.c
    cc -o unit_test unit_test.o leapyear_test.o leapyear.o -laceunit-abort
    ./aceunit

AUTHOR
Written by Christian Hujer.

REPORTING BUGS
AceUnit online help: <https://nelkinda.com/products/aceunit/>

COPYRIGHT
Copyright © 2007, 2024 Christian Hujer License BSD
This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

SEE ALSO
aceunit(1), abort(3), assert(3), longjmp(3), setjmp(3), fork(2), signal(2), Full documentation: <https://nelkinda.com/products/aceunit/>