Skip to content

Creating Unit Tests with CMocka

Jeffrey N. Johnson edited this page May 17, 2021 · 2 revisions

This project supports the creation of unit tests: simple, small programs that test specific features for individual software components. These tests are created using the cmocka testing framework. So far, our existing unit tests lives in the src/tests directory. Take a look at the test_* source files to see how they look.

Because TDycore is a high performance simulator, we support parallel MPI-based unit tests. MPI programs are more complicated to debug than serial ones, so we modify the usual cmocka testing approach to support a mode in which exactly one test is run for each invocation of a test suite. We use a special function called run_selected_tests in the main function for each of the test suites to provide a protocol for the caller of the test executable. This function is defined in src/tests/tdycore_tests.h and has the following signature:

int run_selected_tests(int argc,
                       char **argv,
                       void init_func(int, char**),
                       const struct CMUnitTest tests[],
                       int nproc); 

where

  • argc and argv are the command line arguments passed to your main function
  • init_func is a pointer to a function that, if non-NULL, is called with argc and argv with any command to the test harness removed.
  • tests is an array of CMocka unit tests that make up your test suite (see existing tests in src/tests for examples)
  • nproc is the number of MPI processes that should be used to invoke this test suite by the build system

When your test suite calls run_selected_tests, the build system is able to build and run the tests itself using a make unit-tests target. In addition, you can run an individual test program with specific arguments to poll the number of tests and run them one at a time. Here are some examples of things you can do with these unit tests, provided that cmocka is installed on your system (it's available both in most Linux package managers and via homebrew for Macs):

# Build and run all unit tests.
make unit-tests

# Ask our unit test exe how many tests it has (should be 3).
./src/tests/test_tdyinit count

# Try running the tests individually by 0-based index.
./src/tests/test_tdyinit 0
./src/tests/test_tdyinit 1
./src/tests/test_tdyinit 2

# What happens here?
./src/tests/test_tdyinit 3