Skip to content

Core Concepts

AceUnit doesn’t use annotations or a registration API. It inspects the symbol table of a compiled object file (via nm, objdump, or readelf) and finds functions by naming convention:

  • beforeAll() (0–1) — one-time setup for the fixture
  • beforeEach() (0–1) — setup before each test case
  • test() (n) — the test cases themselves
  • afterEach() (0–1) — teardown after each test case
  • afterAll() (0–1) — one-time teardown for the fixture

Functions can also carry a user-defined prefix, useful if your project already has a module-naming convention — e.g. HeapTest_beforeAll(), HeapTest_test1(), activated with aceunit -p HeapTest_.

An object file containing test functions is called a fixture.

  1. Build AceUnit (skip if already installed for your target system).
  2. Build your object files as usual.
  3. Build your test object files.
  4. Run aceunit on the test object files — it generates the fixture registration source.
  5. Build that generated fixtures object file.
  6. Link everything together with an AceUnit runner library.
  7. Run the test executable.
Terminal window
cd aceunit && make # 1. build AceUnit
cd ../myproject
cc -I ../aceunit/include/ -c *.c # 2-3. build objects + test objects
../aceunit/bin/aceunit *_test.o >testcases.c # 4. generate fixtures
cc -I ../aceunit/include/ -c testcases.c # 5. build fixtures object
cc *.o ../aceunit/lib/libaceunit-abort.a # 6. link
./a.out # 7. run

AceUnit ships four runners, chosen at link time depending on what your environment supports:

Runner How it works Best for
Simple Executes tests directly, stops on first failure Learning, practicing TDD
SetJmp Uses setjmp/longjmp to intercept failed assertions Freestanding environments with <setjmp.h>
Abort Like SetJmp, plus a SIGABRT handler to catch abort()/assert() Hosted environments
Fork Runs each fixture/test in a child process via fork() Real-life projects — survives crashes (SIGSEGV etc.)

You can write your own runner — look at the existing ones in the source, they’re small and meant to be read.

Assertion Simple SetJmp Abort Fork
longjmp() no yes yes no
<assert.h> assert() stop no yes yes
abort() stop no yes yes
exit() stop no no yes
<AceUnit.h> assert() stop yes yes yes
Abnormal termination (e.g. SIGSEGV) no no no yes

“stop” means the assertion fails the test case but halts the whole run; “yes” means it fails the test case and execution continues; “no” means that assertion type isn’t caught at all by that runner.

  • Fixture — an object file with test cases.
  • Test Case — a function AceUnit executes as a test.
  • Test Function — any of BeforeAll, BeforeEach, Test Case, AfterEach, AfterAll.
  • Runner — the part of AceUnit that executes test functions.
  • Assertion — code that checks an expectation and, on failure, aborts the test case and reports to the runner.

Next: Mocking for testing code with side effects, or CLI Reference for the aceunit script’s flags.