A simple ANSI C unit testing library.
This is pretty platform independent, however requires x64 architecture and assumes 8-byte alignment.
This is not an embedded safe library and uses standard library headers. This library is super short and simple and easily modified, if you need to remove some dependencies.
Dependencies |
---|
<stdlib.h> |
<stdio.h> |
<intrin.h> |
<time.h> |
<stdbool.h> |
- Quick Setup
- Simple API
- 2 Files (
cUnit.c
,cUnit.h
)
To actually run the tests you write you need to set up the runner that will well.. run the tests.
bool RunTests()
{
// Create a test suite to add our test methods onto
// we could chose any name for this collection of tests but i'll settle for the file name
TestSuite suite = CreateSuite(__FILE__);
// by default we output test results to stdout, but we could override it with
suite->OutputStream = stdout;
// add our test methods
suite->Append(suite, "Should Pass", &ExampleTest);
suite->Append(suite, "Should Fail", &ShouldFail);
// run our tests and store whether or not all tests passed
bool pass = suite->Run(suite);
// dispose of any unmanaged resources
suite->Dispose(suite);
// return to caller whether or not all of the tests passed
return pass;
}
Once we have a way to run tests we just need to create the tests. A test method has STRICT signature requirements.
- It can either return bool or int(they're the same thing)
- Can be named anything(I encourage meaningful names)
- Can only have a single parameter that accepts a
FILE*
and it's name must bestream
- It must return
true
or (1
)
Here's an example
int name(FILE* stream)
{
return 1;
}
He's some examples of the general API and test methods
bool ExampleTest(FILE* stream)
{
Assert(1 == 1);
Assert(13 != 15);
int x = 12;
int* ptr = &x;
NotNull(ptr);
ptr = NULL;
IsNull(ptr);
return true;
}
bool ShouldFail(FILE* stream)
{
NotEqual(13, 22);
IsNull(NULL);
IsFalse(false);
IsTrue(true);
IsTrue(999); // any non-zero int is true
size_t expected = 12;
size_t actual = 24;
Equals(expected, actual, "%lli"); // this should fail
return true;
}
The test runner's results are streamed to either stdout
(default) or can be streamed to whatever FILE*
you want
using suite->OutputStream = yourCustomStream;
.
The output format is always as follows but can be modified in cUnit.h whenever you want.
[SUITE_NAME] [STARTING] [COUNT = NUMBER_OF_TESTS]
[TEST_NAME]
[PASS/FAIL] [TIME_TAKEN ticks] in __func__ at __FILE__ [__LINE__]
[PASS/FAIL] [TEST_NAME] [TIME_TAKEN ticks]
[SUITE_NAME] [FINISHED] [PASS = NUMBER_OF_PASSED_METHODS] [FAIL = NUMBER_OF_FAILED_METHODS] [TIME_TAKEN ticks]
If you run the example project your output would look similar to this:
[~\program.c] [STARTING] [COUNT = 2]
[Should Pass]
[PASS] [0 ticks] in ExampleTest at ~\program.c [14]
[PASS] [0 ticks] in ExampleTest at ~\program.c [15]
[PASS] [0 ticks] in ExampleTest at ~\program.c [20]
[PASS] [0 ticks] in ExampleTest at ~\program.c [24]
[PASS][Should Pass] [1 ticks]
[Should Fail]
[PASS] [0 ticks] in ShouldFail at ~\program.c [31]
[PASS] [0 ticks] in ShouldFail at ~\program.c [33]
[PASS] [0 ticks] in ShouldFail at ~\program.c [35]
[PASS] [0 ticks] in ShouldFail at ~\program.c [37]
[PASS] [0 ticks] in ShouldFail at ~\program.c [39]
[FAIL] [0 ticks] in ShouldFail at ~\program.c [44]
Expected: 12 Got: 24
[FAIL][Should Fail] [1 ticks]
[~\program.c] [FINISHED] [PASS = 1] [FAIL = 1][2 ticks] FAILED