# Unittests ## Building and running tests Tests can be built by calling: ```bash cd tests/unittests make ``` If there are tests for a module you even can build tests specifically for this module: ```bash make tests- # e.g. make tests-core ``` You then can run the tests by calling ```bash make term ``` or flash them to your board as you would flash any RIOT application to the board (see [board documentation|RIOT-Platforms](https://github.com/RIOT-OS/RIOT/wiki/RIOT-Platforms)). You can debug your tests by running ```bash make debug ``` and using GDB as usual. ### Other output formats Other output formats using [*embUnit*](http://embunit.sourceforge.net/)'s ``textui`` library are available by setting the environment variable ``OUTPUT``: * Compiler: ``OUTPUT="COMPILER"`` * Text: ``OUTPUT="TEXT"`` * XML: ``OUTPUT="XML"`` * Color: ``OUTPUT="COLOR"`` (like default, but with red/green output) * Colored-Text: ``OUTPUT="COLORTEXT"`` (like ``TEXT``, but with red/green output) #### Compile example ```bash OUTPUT="COMPILER" make tests-core make term ``` (only outputs in case of test failures) #### Text example ```bash OUTPUT="TEXT" make tests-core make term ``` ``` - core_bitarithm_tests 1) OK test_SETBIT_null_null 2) OK test_SETBIT_null_limit 3) ... - core_clist_tests 25) ... - ... OK (... tests) ``` #### XML example ```bash OUTPUT="XML" make tests-core make term ``` ```XML test_SETBIT_null_null test_SETBIT_null_limit ... test_clist_add_one ... ... ``` ## Writing unit tests ### File struture RIOT uses [*embUnit*](http://embunit.sourceforge.net/) for unit testing. All unit tests are organized in ``tests/unittests`` and can be built module-wise, if needed. For each module there exists a ``tests-/tests-.h`` file, at least one C file in ``tests-/`` and a ``tests-/Makefile``. It is recommended to add a C file named ``tests-/tests--.c`` for every header file that defines functions (or macros) implemented in the module. If there is only one such header file ``tests-/tests-.c`` should suffice. Each ``*.c`` file should implement a function defined in ``tests-/tests-.h``, named like ```C Test *tests___tests(void); /* or respectively */ Test *tests__tests(void); ``` ### Testing a module To write new tests for a module you need to do three things: 1. **[Create a Makefile](#create-a-makefile)**: add a file ``tests-/Makefile`` 2. **[Define a test header](#define-a-test-header)**: add a file ``tests-/tests-.h`` 3. **[Implement tests](#implement-tests)**: for each header file, that defines a function or macro implemented or related to the module, add a file ``tests-/tests--.c`` or ``tests-/tests-.c`` if there is only one header. #### Create a Makefile The Makefile should have the following content: ```Makefile include $(RIOTBASE)/Makefile.base ``` #### Define a test header. The test header ``tests-/tests-.h`` of a module you add to ``tests/unittests/`` should have the following structure ```C /* * Copyright (C) * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @addtogroup unittests * @{ * * @file * @brief Unittests for the ``module`` module * * @author */ #ifndef TESTS__H_ #define TESTS__H_ #include "embUnit/embUnit.h" #ifdef __cplusplus extern "C" { #endif /** * @brief Generates tests for .h * * @return embUnit tests if successful, NULL if not. */ Test *tests___tests(void); /** * @brief Generates tests for .h * * @return embUnit tests if successful, NULL if not. */ Test *tests___tests(void); /* ... */ #ifdef __cplusplus } #endif #endif /* TESTS__H_ */ /** @} */ ``` #### Implement tests Every ``tests-/tests-*.c`` file you add to ``tests/unittests/`` should have the following structure: ```C /* * Copyright (C) * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /* clib includes */ #include "embUnit/embUnit.h" #include "
.h" #include "tests-.h" /* your macros */ /* your global variables */ static void set_up(void) { /* omit if not needed */ } static void tear_down(void) { /* omit if not needed */ } static void test__(void) { /* ... */ TEST_ASSERT(/* ... */); } static void test__(void) { /* ... */ TEST_ASSERT(/* ... */); } /* ... */ static void test__(void) { /* ... */ TEST_ASSERT(/* ... */); } static void test__(void) { /* ... */ TEST_ASSERT(/* ... */); } /* ... */ Test *tests__
_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test__), new_TestFixture(test__), new_TestFixture(test__), new_TestFixture(test__), /* ... */ }; EMB_UNIT_TESTCALLER(_
_tests, "_
_tests", tests__
_set_up, tests__
_tear_down, fixtures); /* set up and tear down function can be NULL if omitted */ return (Test *)&_
; } ``` The following assertion macros are available via *embUnit*
Assertion Description
TEST_ASSERT_EQUAL_STRING(expected,actual) Assert that strings actual and expected are equivalent
TEST_ASSERT_EQUAL_INT(expected,actual) Assert that integers actual and expected are equivalent
TEST_ASSERT_NULL(pointer) Assert that pointer == NULL
TEST_ASSERT_NOT_NULL(pointer) Assert that pointer != NULL
TEST_ASSERT_MESSAGE(condition, message) Assert that condition is TRUE (non-zero) or output customized message on failure.
TEST_ASSERT(condition) Assert that condition is TRUE (non-zero)
TEST_FAIL(message) Register a failed assertion with the specified message. No logical test is performed.