Test Framework¶
The Zephyr Test Framework (Ztest) provides a simple testing framework intended to be used during development. It provides basic assertion macros and a generic test structure.
The framework can be used in two ways, either as a generic framework for integration testing, or for unit testing specific modules.
Quick start - Integration testing¶
A simple working base is located at samples/testing/integration. Just
copy the files to tests/ and edit them for your needs. The test will then
be automatically built and run by the sanitycheck script. If you are testing
the bar component of foo, you should copy the sample folder to
tests/foo/bar. It can then be tested with:
./scripts/sanitycheck -s tests/foo/bar/test
The sample contains the following files:
Makefile
1 2 3 4 | BOARD ?= qemu_x86
CONF_FILE ?= prj.conf
include $(ZEPHYR_BASE)/Makefile.inc
|
sample.yaml
1 2 3 4 5 6 | sample:
description: TBD
name: TBD
tests:
- test:
tags: my_tags
|
prj.conf
1 | CONFIG_ZTEST=y
|
src/Makefile
1 2 3 | obj-y = main.o
include $(ZEPHYR_BASE)/tests/Makefile.test
|
src/main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
static void assert_tests(void)
{
zassert_true(1, "1 was false");
zassert_false(0, "0 was true");
zassert_is_null(NULL, "NULL was not NULL");
zassert_not_null("foo", "\"foo\" was NULL");
zassert_equal(1, 1, "1 was not equal to 1");
zassert_equal_ptr(NULL, NULL, "NULL was not equal to NULL");
}
void test_main(void)
{
ztest_test_suite(framework_tests,
ztest_unit_test(assert_tests)
);
ztest_run_test_suite(framework_tests);
}
|
Quick start - Unit testing¶
Ztest can be used for unit testing. This means that rather than including the entire Zephyr OS for testing a single function, you can focus the testing efforts into the specific module in question. This will speed up testing since only the module will have to be compiled in, and the tested functions will be called directly.
Since you won’t be including basic kernel data structures that most code depends on, you have to provide function stubs in the test. Ztest provides some helpers for mocking functions, as demonstrated below.
In a unit test, mock objects can simulate the behavior of complex real objects and are used to decide whether a test failed or passed by verifying whether an interaction with an object occurred, and if required, to assert the order of that interaction.
The samples/testing/unit folder contains an example for testing
the net-buf api of Zephyr.
Makefile
1 2 3 | INCLUDE += subsys
include $(ZEPHYR_BASE)/tests/unit/Makefile.unittest
|
sample.yaml
1 2 3 4 5 6 7 | sample:
description: TBD
name: TBD
tests:
- test:
tags: buf
type: unit
|
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | /*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <net/buf.h>
struct net_buf_pool _net_buf_pool_list[1];
unsigned int irq_lock(void)
{
return 0;
}
void irq_unlock(unsigned int key)
{
}
#include <net/buf.c>
void k_queue_init(struct k_queue *fifo) {}
void k_queue_append_list(struct k_queue *fifo, void *head, void *tail) {}
int k_is_in_isr(void)
{
return 0;
}
void *k_queue_get(struct k_queue *fifo, s32_t timeout)
{
return NULL;
}
void k_queue_append(struct k_queue *fifo, void *data)
{
}
void k_queue_prepend(struct k_queue *fifo, void *data)
{
}
#define TEST_BUF_COUNT 1
#define TEST_BUF_SIZE 74
NET_BUF_POOL_DEFINE(bufs_pool, TEST_BUF_COUNT, TEST_BUF_SIZE,
sizeof(int), NULL);
static void test_get_single_buffer(void)
{
struct net_buf *buf;
buf = net_buf_alloc(&bufs_pool, K_NO_WAIT);
zassert_equal(buf->ref, 1, "Invalid refcount");
zassert_equal(buf->len, 0, "Invalid length");
zassert_equal(buf->flags, 0, "Invalid flags");
zassert_equal_ptr(buf->frags, NULL, "Frags not NULL");
}
void test_main(void)
{
ztest_test_suite(net_buf_test,
ztest_unit_test(test_get_single_buffer)
);
ztest_run_test_suite(net_buf_test);
}
|
API reference¶
Running tests¶
警告
doxygengroup: Cannot find file: /home/docs/checkouts/readthedocs.org/user_builds/zephyr-doc/checkouts/v1.9.0/doc/doxygen/xml/index.xml
Assertions¶
These macros will instantly fail the test if the related assertion fails. When an assertion fails, it will print the current file, line and function, alongside a reason for the failure and an optional message. If the config option:CONFIG_ZTEST_ASSERT_VERBOSE is 0, the assertions will only print the file and line numbers, reducing the binary size of the test.
Example output for a failed macro from
zassert_equal(buf->ref, 2, "Invalid refcount"):
Assertion failed at main.c:62: test_get_single_buffer: Invalid refcount (buf->ref not equal to 2)
Aborted at unit test function
警告
doxygengroup: Cannot find file: /home/docs/checkouts/readthedocs.org/user_builds/zephyr-doc/checkouts/v1.9.0/doc/doxygen/xml/index.xml
Mocking¶
These functions allow abstracting callbacks and related functions and
controlling them from specific tests. You can enable the mocking framework by
setting CONFIG_ZTEST_MOCKING to “y” in the configuration file of the
test. The amount of concurrent return values and expected parameters is
limited by CONFIG_ZTEST_PARAMETER_COUNT.
Here is an example for configuring the function expect_two_parameters to
expect the values a=2 and b=3, and telling returns_int to return
5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <ztest.h>
static void expect_two_parameters(int a, int b)
{
ztest_check_expected_value(a);
ztest_check_expected_value(b);
}
static void parameter_tests(void)
{
ztest_expect_value(expect_two_parameters, a, 2);
ztest_expect_value(expect_two_parameters, b, 3);
expect_two_parameters(2, 3);
}
static int returns_int(void)
{
return ztest_get_return_value();
}
static void return_value_tests(void)
{
ztest_returns_value(returns_int, 5);
zassert_equal(returns_int(), 5, NULL);
}
void test_main(void)
{
ztest_test_suite(mock_framework_tests,
ztest_unit_test(parameter_test),
ztest_unit_test(return_value_test)
);
ztest_run_test_suite(mock_framework_tests);
}
|
警告
doxygengroup: Cannot find file: /home/docs/checkouts/readthedocs.org/user_builds/zephyr-doc/checkouts/v1.9.0/doc/doxygen/xml/index.xml