Core Concepts
Test discovery
Section titled “Test discovery”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 fixturebeforeEach()(0–1) — setup before each test casetest()(n) — the test cases themselvesafterEach()(0–1) — teardown after each test caseafterAll()(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.
Workflow
Section titled “Workflow”- Build AceUnit (skip if already installed for your target system).
- Build your object files as usual.
- Build your test object files.
- Run
aceuniton the test object files — it generates the fixture registration source. - Build that generated fixtures object file.
- Link everything together with an AceUnit runner library.
- Run the test executable.
cd aceunit && make # 1. build AceUnitcd ../myprojectcc -I ../aceunit/include/ -c *.c # 2-3. build objects + test objects../aceunit/bin/aceunit *_test.o >testcases.c # 4. generate fixturescc -I ../aceunit/include/ -c testcases.c # 5. build fixtures objectcc *.o ../aceunit/lib/libaceunit-abort.a # 6. link./a.out # 7. runRunners
Section titled “Runners”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.
Which failures each runner catches
Section titled “Which failures each runner catches”| 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.
Glossary
Section titled “Glossary”- 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.