DEV Community

Dizzyspiral
Dizzyspiral

Posted on

Cmocka Quick Start

Today I have occasion to learn a C unit test framework again. This comes about in my career every 3 years or so, so each time, I do a quick re-survey of what's available and pick something that looks good. This time, I've picked cmocka.

The main page links to the API documentation and a slideshow. Neither of these, in my quick perusal, actually give you an example of building a project with Cmocka. I really appreciate it when there's some kind of quickstart skeleton project you can just roll with, so I've taken their first example from the API and done just that.

The first thing you'll want to do to follow along here is download cmocka. I grabbed the source release of 1.1.5.

Untar the archive:

tar -xzvf cmocka-1.1.5.tar.gz
Enter fullscreen mode Exit fullscreen mode

build the cmocka library. For my project, I want the cmocka library to be statically compiled, so I configure cmocka with cmake accordingly:

cd cmocka-1.1.5
mkdir build
cd build
cmake -DWITH_STATIC_LIB=ON ..
make
Enter fullscreen mode Exit fullscreen mode

cmocka will have built the libcmocka-static.a library to the build/src directory. This is what you'll need to link your tests against to get them to build. Using the static cmocka library means that the library will be copied into the binary that's created. This makes it so that the C interpreter doesn't have to find libcmocka at runtime. This is handy if you don't want to install the libcmocka library on your system, or if you're going to be running your tests in an environment other than you development environment. Be aware though that this does make your binary larger and has other portability concerns attached to it, so in lots of (production) cases, static libraries are not the way to go.

Next, make yourself a test.c file with the following contents:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}
int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}
Enter fullscreen mode Exit fullscreen mode

and build your test file:

gcc -I cmocka-1.1.5/include/ -L cmocka-1.1.5/build/src/ test.c -l:libcmocka-static.a
Enter fullscreen mode Exit fullscreen mode

This will have produced a a.out binary. Run it!

$ ./a.out 
[==========] Running 1 test(s).
[ RUN      ] null_test_success
[       OK ] null_test_success
[==========] 1 test(s) run.
[  PASSED  ] 1 test(s).
Enter fullscreen mode Exit fullscreen mode

And there you go. If you want to write unit tests for real C code, the only difference is you need to #include your headers for the source you're testing, and compile the source files you're testing along with the tests.

Top comments (0)