7.2.3. How to use Unit Tests
Verify that the unit testing framework is working as expected:
.\fox.ps1 waf build_app_unit_test_gcc
./fox.sh waf build_app_unit_test_gcc
./fox.sh waf build_app_unit_test_gcc
Typical usage and more information on the unit tests can be found in Unit tests.
7.2.3.1. Guidelines for the Unit Test Skeleton
Note
This example
In this example a driver that resides in src/app/driver/<driver>/<driver>.c and
src/app/driver/<driver>/<driver>.h is added and therefore the accompanying unit tests
need to be added also.
The module abc.c implements the public function
extern uint8_t ABC_DoThis(void) and the static function
static uint8_t ABC_DoSomethingElse(uint8_t someArgument).
Therefore, there are now two functions that need to be united tested.
At first the accompanying unit test file needs to be created in
tests/unit/app/driver/abc/test_abc.c (notice the prefix test) based on
the template in conf/tpl/test_c.c.
7.2.3.2. Public/Extern Function Tests
Add a function
uint8_t testABC_DoThis()in the appropriate section in the test filetests/unit/app/driver/abc/test_abc.c. This function implements the tests forABC_DoThis(). The prefixtest(no trailing underscore) is required for CMock to detect the function as a test-function.Write the test code.
7.2.3.3. Static Function Tests
Static functions are not seen by other translation units, therefore the static functions must be made callable from other modules by creating a wrapper. For this example the wrapper will be
extern uint8_t TEST_ABC_DoSomethingElse(uint8_t someArgument)(notice theTEST_prefix followed by the name of the static function).The declaration of the wrapper needs to be placed in the appropriate section in the header of the driver (
src/app/driver/<driver>/<driver>.h).The definition of the wrapper needs to be placed in the appropriate section in the source of the driver (
src/app/driver/<driver>/<driver>.c). The only thing this wrapper needs to do, is to verbatim pass all arguments to the original function (i.e., the static function) and return its result. The definition of the wrapper looks therefore like this1extern uint8_t testABC_DoSomethingElse(uint8_t someArgument) { 2 return ABC_DoSomethingElse(someArgument); 3}
Add a function
void testABC_DoSomethingElse(void)in the appropriate section in the test filetests/unit/app/driver/abc/test_abc.c. This function implements the tests forABC_DoSomethingElse(). The prefixtest(no trailing underscore) is required for CMock to detect the function as a test-function. Note: TheTEST_prefix of the externalization wrapper is removed and not part of the test function name.Write test code.
7.2.3.4. Result
1/*========== Extern Function Prototypes =====================================*/
2extern uint8_t ABC_DoThis(void);
3
4/*========== Externalized Static Functions Prototypes (Unit Test) ===========*/
5#ifdef UNITY_UNIT_TEST
6extern uint8_t TEST_ABC_DoSomethingElse(uint8_t someArgument);
7#endif
The wrapper function TEST_ABC_DoSomethingElse needs to be put inside the
UNITY_UNIT_TEST guard, so that it is not build during target builds.
1/*========== Static Function Prototypes =====================================*/
2static uint8_t ABC_DoSomethingElse(uint8_t someArgument);
3
4/*========== Static Function Implementations ================================*/
5static uint8_t ABC_DoSomethingElse(uint8_t someArgument) {
6 return someArgument;
7}
8
9/*========== Extern Function Implementations ================================*/
10extern uint8_t ABC_DoThis(void) {
11 return ABC_DoSomethingElse(1);
12}
13
14/*========== Externalized Static Function Implementations (Unit Test) =======*/
15#ifdef UNITY_UNIT_TEST
16extern uint8_t TEST_ABC_DoSomethingElse(uint8_t someArgument) {
17 return ABC_DoSomethingElse(someArgument);
18}
19#endif
1void testABC_DoThis(void) {
2 /* test code */
3 ABC_DoThis();
4}
5
6void testABC_DoSomethingElse() {
7 /* test code */
8 TEST_ABC_DoSomethingElse(2);
9}
7.2.4. Linux specific Usage
The unit test suite is developed on Windows and there works out of the box on all setup that install the dependencies as they are specified in Software Installation. However, it is still possible to get the unit test suite working on Linux. Internally it is tested with the following setup:
cat /etc/redhat-release: AlmaLinux release 10.2 (Lavender Lion)uname -mrs: Linux 6.12.0-211.7.3.el10_2.x86_64 x86_64gcc --version: gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4)ruby --version: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
7.2.5. Unit Test Macros
UNITY_UNIT_TEST: shall be used to exclude code that is not needed for the target build, but required for unit testing (e.g., making a static function testable). It shall not be used to change functional behavior when compiling (some rare exceptions to this rule can be found in the code, but it is generally not preferred to do so, although sometimes it is needed.)COMPILE_FOR_UNIT_TEST: shall be used when code needs to be compiled differently in oder to make it unit testable on the host. Do not useUNITY_UNIT_TESTto achieve the same (see above).