Audition: The C Testing Framework Ready for Its Big Break
Posted on 2024-11-11T15:51:00Z
Railgun Labs LLC proudly announces Audition – a modern xUnit testing framework for C11 and beyond.
Audition is an all-in-one testing framework for C. It’s built with the features you expect from an xUnit testing framework and so much more. In this announcement, I’ll showcase its unique features.
Automatic Test Registration
Traditional C testing frameworks require boilerplate code to register tests. This means writing the test and then registering it with a test suite. If you don’t have a test suite, it becomes an additional step. With Audition, this process becomes one-step.
The following code defines a complete executable program with a single test case.
The test is named myTest and the suite is named mySuite.
#include <audition.h>
TEST(mySuite, myTest) {
ASSERT_EQ(1 + 2, 3);
}
Notice the absence of a main function?
Audition provides that too.
By default, Audition will run all tests when your unit test executable runs. If you want to run a specific test, you can specify its suite and test name at the command line (the test and suite are delimited by a period character).
$ ./your_test_program.exe mySuite.myTest
1 passing [100%] (1ms)
Glob patterns are supported so a pattern like, mySuite.my* would instruct Audition to run every test that begins with my in the mySuite suite.
Function Mocking
Contemporary C unit testing frameworks lack native function mocking. Those that do attempt to support it usually involve non-portable linker flags or code generators. These approaches require access to the source code (or at least the object files) which is something you may not have.
Audition is different. With Audition you can trivially mock C functions, including functions you lack the source code of!
Audition offers two types of mocks: fakes and stubs.
Fakes
Fake functions are special functions that calls to the original function are redirected to.
The fake function is a function you implement. In its body you can assert the arguments and return a hard-coded return value.
In the following code snippet all calls to the foo function are redirected to the mock_foo function.
#include <audition.h>
int foo(int); // original function, forward declared
static int fake_foo(int x) { // fake function
EXPECT_GTEQ(x, 0); // assert argument x >= 0
return 42; // return hard-coded value
}
TEST(mySuite, myTest) {
FAKE(foo, fake_foo); // redirect foo() to fake_foo()
foo() // returns 42
}
Stubs
For scenarios where you only need to return a hard-coded value, Audition provides a shorthand called function stubbing. When you stub a function you provide the return value and let Audition handle the rest.
#include <audition.h>
int foo(int); // original function, forward declared
TEST(mySuite, myTest) {
STUB(foo, 42); // make foo() to always return 42
foo(); // returns 42
}
Reporting Formats
Audition’s default output format is designed for terminal display, but it also supports TAP, JUnit, and Subunit formats. Specifically, Audition supports TAP format version 12, 13, and 14; JUnit XML version 5 and; subunit version 1. You can choose the output format via command line arguments.
Here’s an example of TAP v13 output:
$ ./your_test_program.exe --reporter=tap
TAP version 13
1..3
ok 1 - spaceship.closeDoors
ok 2 - spaceship.checkFuel
ok 3 - spaceship.blastOff
And here’s JUnit XML output:
$ ./your_test_program.exe --reporter=junit
<?xml version="1.0" encoding="UTF-8" ?>
<testsuites tests="3" failures="0" time="0.0">
<testsuite name="spaceship" tests="3" failures="0">
<testcase name="closeDoors" />
<testcase name="checkFuel" />
<testcase name="blastOff" />
</testsuite>
</testsuites>
JUnit XML is a favorite among CI tools (perfect for dashboard integration)!
Other Goodies
Audition includes many other quality of life improvements.
Generic Assertion Macros
Audition uses C11’s _Generic to provide type-generic assertion macros.
The snippet below shows the ASSERT_EQ assertion being used to test equality between integers and floating-point numbers.
ASSERT_EQ(1, 2); // compare integers
ASSERT_EQ(1.0, 2.0); // comparing floating-point numbers
Binary and Text Diffing
Audition supports multi-line string diffing for easy comparison of multi-line strings.
The excerpt below demonstrates diff’d output for two mismatching multi-line strings. Note that one string is from Edger Allen Poe’s The Raven and the other is a knockoff. I’ll let you guess which is which.
@@ -35,7 +35,7 @@
Open here I flung the shutter, when, with many a flirt and flutter,
-In there stepped a stately Raven of the saintly days of yore.
+In there stepped a stately Crow of the saintly days of yore.
Not the least obeisance made he; not an instant stopped or stayed he;
Audition also supports binary diffs.
@@ -0000,41 +0000,38 @@
-0000 | 41 | A |
0001 0000 | DE AD BE EF BA AD F0 0D BA 6D | .........m |
-000E | 00 | . |
+ 000D | BE AF C0 | ... |
Platform Abstractions
Audition implements various cross-platform utilities presented through a cross platform interface. Among these include portable file system utilities (create directory, iterate files in directory) and high-resolution timers.
Closing Thoughts
Audition brings a unique combination of features unmatched by other C testing frameworks. It is available for Windows, macOS, and Ubuntu Linux. Download it for your platform here..