1.. _test-framework:
2
3Test Framework
4###############
5
6The Zephyr Test Framework (Ztest) provides a simple testing framework intended
7to be used during development.  It provides basic assertion macros and a generic
8test structure.
9
10The framework can be used in two ways, either as a generic framework for
11integration testing, or for unit testing specific modules.
12
13Creating a test suite
14*********************
15
16Using Ztest to create a test suite is as easy as calling the :c:macro:`ZTEST_SUITE`. The macro
17accepts the following arguments:
18
19* ``suite_name`` - The name of the suite. This name must be unique within a single binary.
20* :c:type:`ztest_suite_predicate_t` - An optional predicate function to allow choosing when the
21  test will run. The predicate will get a pointer to the global state passed in through
22  :c:func:`ztest_run_all` and should return a boolean to decide if the suite should run.
23* :c:type:`ztest_suite_setup_t` - An optional setup function which returns a test fixture. This
24  will be called and run once per test suite run.
25* :c:type:`ztest_suite_before_t` - An optional before function which will run before every single
26  test in this suite.
27* :c:type:`ztest_suite_after_t` - An optional after function which will run after every single
28  test in this suite.
29* :c:type:`ztest_suite_teardown_t` - An optional teardown function which will run at the end of
30  all the tests in the suite.
31
32Below is an example of a test suite using a predicate:
33
34.. code-block:: C
35
36   #include <zephyr/ztest.h>
37   #include "test_state.h"
38
39   static bool predicate(const void *global_state)
40   {
41   	return ((const struct test_state*)global_state)->x == 5;
42   }
43
44   ZTEST_SUITE(alternating_suite, predicate, NULL, NULL, NULL, NULL);
45
46Adding tests to a suite
47***********************
48
49There are 5 macros used to add a test to a suite, they are:
50
51* :c:macro:`ZTEST` ``(suite_name, test_name)`` - Which can be used to add a test by ``test_name`` to a
52  given suite by ``suite_name``.
53* :c:macro:`ZTEST_P` ``(suite_name, test_name)`` - Add a parameterized test to a given suite by specifying
54  the ``suite_name`` and ``test_name``. You can then access the passed parameter within
55  the body of the test using the ``data`` pointer.
56* :c:macro:`ZTEST_USER` ``(suite_name, test_name)`` - Which behaves the same as :c:macro:`ZTEST`, only
57  that when :kconfig:option:`CONFIG_USERSPACE` is enabled, then the test will be run in a userspace
58  thread.
59* :c:macro:`ZTEST_F` ``(suite_name, test_name)`` - Which behaves the same as :c:macro:`ZTEST`, only
60  that the test function will already include a variable named ``fixture`` with the type
61  ``<suite_name>_fixture``.
62* :c:macro:`ZTEST_USER_F` ``(suite_name, test_name)`` - Which combines the fixture feature of
63  :c:macro:`ZTEST_F` with the userspace threading for the test.
64
65Test fixtures
66=============
67
68Test fixtures can be used to help simplify repeated test setup operations. In many cases, tests in
69the same suite will require some initial setup followed by some form of reset between each test.
70This is achieved via fixtures in the following way:
71
72.. code-block:: C
73
74   #include <zephyr/ztest.h>
75
76   struct my_suite_fixture {
77   	size_t max_size;
78   	size_t size;
79   	uint8_t buff[1];
80   };
81
82   static void *my_suite_setup(void)
83   {
84   	/* Allocate the fixture with 256 byte buffer */
85      struct my_suite_fixture *fixture = malloc(sizeof(struct my_suite_fixture) + 255);
86
87   	zassume_not_null(fixture, NULL);
88   	fixture->max_size = 256;
89
90   	return fixture;
91   }
92
93   static void my_suite_before(void *f)
94   {
95   	struct my_suite_fixture *fixture = (struct my_suite_fixture *)f;
96   	memset(fixture->buff, 0, fixture->max_size);
97   	fixture->size = 0;
98   }
99
100   static void my_suite_teardown(void *f)
101   {
102      free(f);
103   }
104
105   ZTEST_SUITE(my_suite, NULL, my_suite_setup, my_suite_before, NULL, my_suite_teardown);
106
107   ZTEST_F(my_suite, test_feature_x)
108   {
109   	zassert_equal(0, fixture->size);
110   	zassert_equal(256, fixture->max_size);
111   }
112
113Using memory allocated by a test fixture in a userspace thread, such as during execution of
114:c:macro:`ZTEST_USER` or :c:macro:`ZTEST_USER_F`, requires that memory to be declared userspace
115accessible. This is because the fixture memory is owned and initialized by kernel space. The Ztest
116framework provides the :c:macro:`ZTEST_DMEM` and :c:macro:`ZTEST_BMEM` macros for use of such
117user/kernel space shared memory.
118
119Advanced features
120*****************
121
122Test result expectations
123========================
124
125Some tests were made to be broken. In cases where the test is expected to fail or skip due to the
126nature of the code, it's possible to annotate the test as such. For example:
127
128  .. code-block:: C
129
130    #include <zephyr/ztest.h>
131
132    ZTEST_SUITE(my_suite, NULL, NULL, NULL, NULL, NULL);
133
134    ZTEST_EXPECT_FAIL(my_suite, test_fail);
135    ZTEST(my_suite, test_fail)
136    {
137      /** This will fail the test */
138      zassert_true(false, NULL);
139    }
140
141    ZTEST_EXPECT_SKIP(my_suite, test_skip);
142    ZTEST(my_suite, test_skip)
143    {
144      /** This will skip the test */
145      zassume_true(false, NULL);
146    }
147
148In this example, the above tests should be marked as failed and skipped respectively. Instead,
149Ztest will mark both as passed due to the expectation.
150
151Test rules
152==========
153
154Test rules are a way to run the same logic for every test and every suite. There are a lot of cases
155where you might want to reset some state for every test in the binary (regardless of which suite is
156currently running). As an example, this could be to reset mocks, reset emulators, flush the UART,
157etc.:
158
159.. code-block:: C
160
161   #include <zephyr/fff.h>
162   #include <zephyr/ztest.h>
163
164   #include "test_mocks.h"
165
166   DEFINE_FFF_GLOBALS;
167
168   DEFINE_FAKE_VOID_FUN(my_weak_func);
169
170   static void fff_reset_rule_before(const struct ztest_unit_test *test, void *fixture)
171   {
172   	ARG_UNUSED(test);
173   	ARG_UNUSED(fixture);
174
175   	RESET_FAKE(my_weak_func);
176   }
177
178   ZTEST_RULE(fff_reset_rule, fff_reset_rule_before, NULL);
179
180A custom ``test_main``
181======================
182
183While the Ztest framework provides a default :c:func:`test_main` function, it's possible that some
184applications will want to provide custom behavior. This is particularly true if there's some global
185state that the tests depend on and that state either cannot be replicated or is difficult to
186replicate without starting the process over. For example, one such state could be a power sequence.
187Assuming there's a board with several steps in the power-on sequence a test suite can be written
188using the ``predicate`` to control when it would run. In that case, the :c:func:`test_main`
189function can be written as follows:
190
191.. code-block:: C
192
193   #include <zephyr/ztest.h>
194
195   #include "my_test.h"
196
197   void test_main(void)
198   {
199        struct power_sequence_state state;
200
201        /* Only suites that use a predicate checking for phase == PWR_PHASE_0 will run. */
202        state.phase = PWR_PHASE_0;
203        ztest_run_all(&state, false, 1, 1);
204
205        /* Only suites that use a predicate checking for phase == PWR_PHASE_1 will run. */
206        state.phase = PWR_PHASE_1;
207        ztest_run_all(&state, false, 1, 1);
208
209        /* Only suites that use a predicate checking for phase == PWR_PHASE_2 will run. */
210        state.phase = PWR_PHASE_2;
211        ztest_run_all(&state, false, 1, 1);
212
213        /* Check that all the suites in this binary ran at least once. */
214        ztest_verify_all_test_suites_ran();
215   }
216
217
218Quick start - Integration testing
219*********************************
220
221A simple working base is located at :zephyr_file:`samples/subsys/testsuite/integration`.
222To make a test application for the **bar** component of **foo**, you should copy the
223sample folder to ``tests/foo/bar`` and edit files there adjusting for your test
224application's purposes.
225
226To build and execute all applicable test scenarios defined in your test application
227use the :ref:`Twister <twister_script>` tool, for example:
228
229.. code-block:: console
230
231    ./scripts/twister -T tests/foo/bar/
232
233To select just one of the test scenarios, run Twister with ``--scenario`` command:
234
235.. code-block:: console
236
237   ./scripts/twister --scenario tests/foo/bar/your.test.scenario.name
238
239In the command line above ``tests/foo/bar`` is the path to your test application and
240``your.test.scenario.name`` references a test scenario defined in :file:`testcase.yaml`
241file, which is like ``sample.testing.ztest`` in the boilerplate test suite sample.
242
243See :ref:`Twister test project diagram <twister_test_project_diagram>` for more details
244on how Twister deals with Ztest application.
245
246The sample contains the following files:
247
248CMakeLists.txt
249
250.. literalinclude:: ../../../samples/subsys/testsuite/integration/CMakeLists.txt
251   :language: CMake
252   :linenos:
253
254testcase.yaml
255
256.. literalinclude:: ../../../samples/subsys/testsuite/integration/testcase.yaml
257   :language: yaml
258   :linenos:
259
260prj.conf
261
262.. literalinclude:: ../../../samples/subsys/testsuite/integration/prj.conf
263   :language: text
264   :linenos:
265
266src/main.c
267
268.. literalinclude:: ../../../samples/subsys/testsuite/integration/src/main.c
269   :language: c
270   :linenos:
271
272.. contents::
273   :depth: 1
274   :local:
275   :backlinks: top
276
277
278
279A test application may consist of multiple test suites that
280either can be testing functionality or APIs. Functions implementing a test case
281should follow the guidelines below:
282
283* Test cases function names should be prefixed with **test_**
284* Test cases should be documented using doxygen
285* Test case function names should be unique within the section or component being
286  tested
287
288For example:
289
290.. code-block:: C
291
292   /**
293    * @brief Test Asserts
294    *
295    * This test case verifies the zassert_true macro.
296    */
297   ZTEST(my_suite, test_assert)
298   {
299           zassert_true(1, "1 was false");
300   }
301
302Listing Tests
303=============
304
305Tests (test applications) in the Zephyr tree consist of many test scenarios that run as
306part of a project and test similar functionality, for example an API or a
307feature. The ``twister`` script can parse the test scenarios, suites and cases in all
308test applications or a subset of them, and can generate reports on a granular
309level, i.e. if test cases have passed or failed or if they were blocked or skipped.
310
311Twister parses the source files looking for test case names, so you
312can list all kernel test cases, for example, by running:
313
314.. code-block:: console
315
316   ./scripts/twister --list-tests -T tests/kernel
317
318Skipping Tests
319==============
320
321Special- or architecture-specific tests cannot run on all
322platforms and architectures, however we still want to count those and
323report them as being skipped.  Because the test inventory and
324the list of tests is extracted from the code, adding
325conditionals inside the test suite is sub-optimal.  Tests that need
326to be skipped for a certain platform or feature need to explicitly
327report a skip using :c:func:`ztest_test_skip` or :c:macro:`Z_TEST_SKIP_IFDEF`. If the test runs,
328it needs to report either a pass or fail.  For example:
329
330.. code-block:: C
331
332   #ifdef CONFIG_TEST1
333   ZTEST(common, test_test1)
334   {
335   	zassert_true(1, "true");
336   }
337   #else
338   ZTEST(common, test_test1)
339   {
340   	ztest_test_skip();
341   }
342   #endif
343
344   ZTEST(common, test_test2)
345   {
346   	Z_TEST_SKIP_IFDEF(CONFIG_BUGxxxxx);
347   	zassert_equal(1, 0, NULL);
348   }
349
350   ZTEST_SUITE(common, NULL, NULL, NULL, NULL, NULL);
351
352.. _ztest_unit_testing:
353
354Quick start - Unit testing
355**************************
356
357Ztest can be used for unit testing. This means that rather than including the
358entire Zephyr OS for testing a single function, you can focus the testing
359efforts into the specific module in question. This will speed up testing since
360only the module will have to be compiled in, and the tested functions will be
361called directly.
362
363To setup unit tests you have to add a CMakeLists.txt, a testcases.yml and a
364prj.conf to the directory containing the unit test source files. The resulting
365binary from this directory is build with the -DBOARD=unit_testing. When twister
366is invoked the script zephyr/scripts/pylib/twister/twisterlib/testplan.py
367filters out all testcases.yml in which type: unit is not set. Only unit tests
368are executed with a firmware build with BOARD=unit_testing.
369
370.. note::
371   Unit tests are run as **native** applications on the host and are therefore
372   subject to similar :ref:`limitations <posix_arch_limitations>` as documented
373   for the :ref:`POSIX architecture<Posix arch>`. Running unit tests is
374   therefore only supported for Linux. To run unit tests on Windows or macOS
375   it is necessary to use containers or Virtual Machines running a Linux guest.
376   Follow the same instructions as for the
377   :ref:`POSIX Arch dependencies<posix_arch_deps>`.
378
379CMakeLists.txt
380==============
381
382In order to declare the unit tests present in a source folder, you need to add
383the relevant source files to the ``testbinary`` target from the CMake
384:zephyr_file:`unittest <cmake/modules/unittest.cmake>` component. See a minimal
385example below:
386
387.. code-block:: cmake
388
389   cmake_minimum_required(VERSION 3.20.0)
390
391   project(app)
392   find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE})
393   target_sources(testbinary PRIVATE main.c)
394
395Since you won't be including basic kernel data structures that most code
396depends on, you have to provide function stubs in the test. Ztest provides
397some helpers for mocking functions, as demonstrated below.
398
399In a unit test, mock objects can simulate the behavior of complex real objects
400and are used to decide whether a test failed or passed by verifying whether an
401interaction with an object occurred, and if required, to assert the order of
402that interaction.
403
404testcases.yaml
405==============
406
407You have to set the value for the key "type" to "unit" in the testcase.yaml
408
409.. code-block:: yaml
410
411   tests:
412      testscenario.testsuite:
413         tags: your_tag
414         type: unit
415
416prj.conf
417========
418
419For unit tests this contains usually only
420
421.. code-block:: kconfig
422
423   CONFIG_ZTEST=y
424
425If your unit tests require additional libraries (e.g. math-lib) you will have to
426add them either via the CMakeLists.txt or in the testcase.yaml:
427
428.. code-block:: yaml
429
430   tests:
431      testscenario.testsuite:
432         tags: your_tag
433         type: unit
434         extra_args:
435            - EXTRA_LDFLAGS="-lm"
436
437Examples of unit tests can be found in the :zephyr_file:`tests/unit/` folder.
438
439Best practices for declaring the test suite
440*******************************************
441
442*twister* and other validation tools need to obtain the list of
443test cases that a Zephyr *ztest* test image will expose.
444
445.. admonition:: Rationale
446
447   This all is for the purpose of traceability. It's not enough to
448   have only a semaphore test application.  We also need to show that we
449   have testpoints for all APIs and functionality, and we trace back
450   to documentation of the API, and functional requirements.
451
452   The idea is that test reports show results for every test case
453   as passed, failed, blocked, or skipped.  Reporting on only the
454   high-level test application, particularly when tests do too
455   many things, is too vague.
456
457Other questions:
458
459- Why not pre-scan with CPP and then parse? or post scan the ELF file?
460
461  If C pre-processing or building fails because of any issue, then we
462  won't be able to tell the subcases.
463
464- Why not declare them in the YAML test configuration?
465
466  A separate test case description file would be harder to maintain
467  than just keeping the information in the test source files
468  themselves -- only one file to update when changes are made
469  eliminates duplication.
470
471Stress test framework
472*********************
473
474Zephyr stress test framework (Ztress) provides an environment for executing user
475functions in multiple priority contexts. It can be used to validate that code is
476resilient to preemptions. The framework tracks the number of executions and preemptions
477for each context. Execution can have various completion conditions like timeout,
478number of executions or number of preemptions.
479
480The framework is setting up the environment by creating the requested number of threads
481(each on different priority), optionally starting a timer. For each context, a user
482function (different for each context) is called and then the context sleeps for
483a randomized amount of system ticks. The framework is tracking CPU load and adjusts sleeping
484periods to achieve higher CPU load. In order to increase the probability of preemptions,
485the system clock frequency should be relatively high. The default 100 Hz on QEMU x86
486is much too low and it is recommended to increase it to 100 kHz.
487
488The stress test environment is setup and executed using :c:macro:`ZTRESS_EXECUTE` which
489accepts a variable number of arguments. Each argument is a context that is
490specified by :c:macro:`ZTRESS_TIMER` or :c:macro:`ZTRESS_THREAD` macros. Contexts
491are specified in priority descending order. Each context specifies completion
492conditions by providing the minimum number of executions and preemptions. When all
493conditions are met and the execution has completed, an execution report is printed
494and the macro returns. Note that while the test is executing, a progress report is
495periodically printed.
496
497Execution can be prematurely completed by specifying a test timeout (:c:func:`ztress_set_timeout`)
498or an explicit abort (:c:func:`ztress_abort`).
499
500User function parameters contains an execution counter and a flag indicating if it is
501the last execution.
502
503The example below presents how to setup and run 3 contexts (one of which is k_timer
504interrupt handler context). Completion criteria is set to at least 10000 executions
505of each context and 1000 preemptions of the lowest priority context. Additionally,
506the timeout is configured to complete after 10 seconds if those conditions are not met.
507The last argument of each context is the initial sleep time which will be adjusted throughout
508the test to achieve the highest CPU load.
509
510  .. code-block:: C
511
512             ztress_set_timeout(K_MSEC(10000));
513             ZTRESS_EXECUTE(ZTRESS_TIMER(foo_0, user_data_0, 10000, Z_TIMEOUT_TICKS(20)),
514                            ZTRESS_THREAD(foo_1, user_data_1, 10000, 0, Z_TIMEOUT_TICKS(20)),
515                            ZTRESS_THREAD(foo_2, user_data_2, 10000, 1000, Z_TIMEOUT_TICKS(20)));
516
517Configuration
518=============
519
520Static configuration of Ztress contains:
521
522 - :kconfig:option:`CONFIG_ZTRESS_MAX_THREADS` - number of supported threads.
523 - :kconfig:option:`CONFIG_ZTRESS_STACK_SIZE` - Stack size of created threads.
524 - :kconfig:option:`CONFIG_ZTRESS_REPORT_PROGRESS_MS` - Test progress report interval.
525
526API reference
527*************
528
529Running tests
530=============
531
532.. doxygengroup:: ztest_test
533
534Assertions
535==========
536
537These macros will instantly fail the test if the related assertion fails.
538When an assertion fails, it will print the current file, line and function,
539alongside a reason for the failure and an optional message. If the config
540:kconfig:option:`CONFIG_ZTEST_ASSERT_VERBOSE` is 0, the assertions will only print the
541file and line numbers, reducing the binary size of the test.
542
543Example output for a failed macro from
544``zassert_equal(buf->ref, 2, "Invalid refcount")``:
545
546.. code-block:: none
547
548    Assertion failed at main.c:62: test_get_single_buffer: Invalid refcount (buf->ref not equal to 2)
549    Aborted at unit test function
550
551.. doxygengroup:: ztest_assert
552
553
554Expectations
555============
556
557These macros will continue test execution if the related expectation fails and subsequently fail the
558test at the end of its execution.  When an expectation fails, it will print the current file, line,
559and function, alongside a reason for the failure and an optional message but continue executing the
560test. If the config :kconfig:option:`CONFIG_ZTEST_ASSERT_VERBOSE` is 0, the expectations will only print the
561file and line numbers, reducing the binary size of the test.
562
563For example, if the following expectations fail:
564
565.. code-block:: C
566
567   zexpect_equal(buf->ref, 2, "Invalid refcount");
568   zexpect_equal(buf->ref, 1337, "Invalid refcount");
569
570The output will look something like:
571
572.. code-block:: none
573
574   START - test_get_single_buffer
575       Expectation failed at main.c:62: test_get_single_buffer: Invalid refcount (buf->ref not equal to 2)
576       Expectation failed at main.c:63: test_get_single_buffer: Invalid refcount (buf->ref not equal to 1337)
577    FAIL - test_get_single_buffer in 0.0 seconds
578
579.. doxygengroup:: ztest_expect
580
581Assumptions
582===========
583
584These macros will instantly skip the test or suite if the related assumption fails.
585When an assumption fails, it will print the current file, line, and function,
586alongside a reason for the failure and an optional message. If the config
587:kconfig:option:`CONFIG_ZTEST_ASSERT_VERBOSE` is 0, the assumptions will only print the
588file and line numbers, reducing the binary size of the test.
589
590Example output for a failed macro from
591``zassume_equal(buf->ref, 2, "Invalid refcount")``:
592
593.. code-block::none
594
595    START - test_get_single_buffer
596        Assumption failed at main.c:62: test_get_single_buffer: Invalid refcount (buf->ref not equal to 2)
597     SKIP - test_get_single_buffer in 0.0 seconds
598
599.. doxygengroup:: ztest_assume
600
601
602Ztress
603======
604
605.. doxygengroup:: ztest_ztress
606
607
608.. _mocking-fff:
609
610Mocking via FFF
611===============
612
613Zephyr has integrated with FFF for mocking. See `FFF`_ for documentation. To use it,
614include the relevant header:
615
616.. code-block:: C
617
618   #include <zephyr/fff.h>
619
620Zephyr provides several FFF-based fake drivers which can be used as either stubs or mocks. Fake
621driver instances are configured via :ref:`devicetree` and :ref:`kconfig`. See the following
622devicetree bindings for more information:
623
624 - :dtcompatible:`zephyr,fake-can`
625 - :dtcompatible:`zephyr,fake-eeprom`
626
627Zephyr also has defined extensions to FFF for simplified declarations of fake functions.
628See :ref:`FFF Extensions <fff-extensions>`.
629
630Customizing Test Output
631***********************
632Customization is enabled by setting :kconfig:option:`CONFIG_ZTEST_TC_UTIL_USER_OVERRIDE` to "y"
633and adding a file :file:`tc_util_user_override.h` with your overrides.
634
635Add the line ``zephyr_include_directories(my_folder)`` to
636your project's :file:`CMakeLists.txt` to let Zephyr find your header file during builds.
637
638See the file :zephyr_file:`subsys/testsuite/include/zephyr/tc_util.h` to see
639which macros and/or defines can be overridden.
640These will be surrounded by blocks such as:
641
642.. code-block:: C
643
644   #ifndef SOMETHING
645   #define SOMETHING <default implementation>
646   #endif /* SOMETHING */
647
648.. _ztest_shuffle:
649
650Shuffling Test Sequence
651***********************
652By default the tests are sorted and ran in alphanumerical order.  Test cases may
653be dependent on this sequence. Enable :kconfig:option:`CONFIG_ZTEST_SHUFFLE` to
654randomize the order. The output from the test will display the seed for failed
655tests.  For native simulator builds you can provide the seed as an argument to
656twister with ``--seed``.
657
658
659Repeating Tests
660***********************
661By default the tests are executed once. The test cases and test suites
662may be executed multiple times. Enable :kconfig:option:`CONFIG_ZTEST_REPEAT` to
663execute the tests multiple times. By default the multiplication factors are 3, which
664means every test suite is executed 3 times and every test case is executed 3 times. This can
665be changed by the :kconfig:option:`CONFIG_ZTEST_SUITE_REPEAT_COUNT` and
666:kconfig:option:`CONFIG_ZTEST_TEST_REPEAT_COUNT` Kconfig options.
667
668Test Selection
669**************
670For tests built for native simulator, use command line arguments to list
671or select tests to run. The test argument expects a comma separated list
672of ``suite::test`` .  You can substitute the test name with an ``*`` to run all
673tests within a suite.
674
675For example
676
677.. code-block:: bash
678
679    $ zephyr.exe -list
680    $ zephyr.exe -test="fixture_tests::test_fixture_pointer,framework_tests::test_assert_mem_equal"
681    $ zephyr.exe -test="framework_tests::*"
682
683
684.. _fff-extensions:
685
686FFF Extensions
687**************
688
689.. doxygengroup:: fff_extensions
690
691
692.. _FFF: https://github.com/meekrosoft/fff
693