I've been adding unit tests to my C-based projects with the CMocka testing framework. Now that I have tests defined, I want my build server to run the tests and track the results for each build. Jenkins requires test results to be reported in the JUnit XML format. Luckily, CMocka has built in XML support that's quite easy to enable.
Enabling XML Output
The first step in enabling XML output is to set the CMocka output format. The easiest approach is to set the output format in your test program. This API must be called before any tests are run:
You can also change CMocka's output behavior using the
CMOCKA_MESSAGE_OUTPUT environment variable. Note that
CMOCKA_MESSAGE_OUTPUT has higher precedence than the
cmocka_set_message_output API, so you can override a test program's default formatting behavior.
Possible values for
xml. Options are case-insensitive.
Configuring XML Output Destination
By default, XML output will be printed to
stderr. In order to write the results to a file, you must define the environment variable
CMOCKA_XML_FILE. If the file already exists or cannot be created, CMocka will output the results to
XML Output With Multiple Test Groups
I like to organize my tests into multiple groups. This causes CMocka to generate invalid XML, as too many top level tags exist in the file. Jenkins will fail to parse the file, and you will also find that tools like
xmllint will report errors.
To work around this, you can enable CMocka to generate a separate XML file for each test group. Simply include "
%g" in the filename definition. The "
%g" characters will be replaced by the group name.
A Note on CMocka API Usage With XML Results
You must use the
cmocka_run_group_tests_name APIs to successfully generate XML test results. All other testing APIs will result in summary output instead of XML output.
Putting it All Together
Here's a sample from the Embedded Artistry libc repository. I place my test results inside of my
buildresults directory, which is untracked and gets cleaned by the build server.
.PHONY: test test: ifeq ("$(wildcard buildresults/testresults/)","") @mkdir -p buildresults/testresults else @rm -f buildresults/testresults/* endif @CMOCKA_XML_FILE=buildresults/testresults/%g.xml buildresults/x86_64_debug/test/libc.bin