^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) .. SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ===============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) Getting Started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) ===============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) Installing dependencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) =======================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) KUnit has the same dependencies as the Linux kernel. As long as you can build
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) the kernel, you can run KUnit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) Running tests with the KUnit Wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ====================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) Included with KUnit is a simple Python wrapper which runs tests under User Mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) Linux, and formats the test results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) The wrapper can be run with:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) .. code-block:: bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ./tools/testing/kunit/kunit.py run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) For more information on this wrapper (also called kunit_tool) check out the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) :doc:`kunit-tool` page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) Creating a .kunitconfig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) -----------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) If you want to run a specific set of tests (rather than those listed in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) KUnit defconfig), you can provide Kconfig options in the ``.kunitconfig`` file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) This file essentially contains the regular Kernel config, with the specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) test targets as well. The ``.kunitconfig`` should also contain any other config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) options required by the tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) A good starting point for a ``.kunitconfig`` is the KUnit defconfig:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .. code-block:: bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) cd $PATH_TO_LINUX_REPO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) cp arch/um/configs/kunit_defconfig .kunitconfig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) You can then add any other Kconfig options you wish, e.g.:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .. code-block:: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) CONFIG_LIST_KUNIT_TEST=y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) :doc:`kunit_tool <kunit-tool>` will ensure that all config options set in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ``.kunitconfig`` are set in the kernel ``.config`` before running the tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) It'll warn you if you haven't included the dependencies of the options you're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) using.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .. note::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) Note that removing something from the ``.kunitconfig`` will not trigger a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rebuild of the ``.config`` file: the configuration is only updated if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ``.kunitconfig`` is not a subset of ``.config``. This means that you can use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) other tools (such as make menuconfig) to adjust other config options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) Running the tests (KUnit Wrapper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ---------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) To make sure that everything is set up correctly, simply invoke the Python
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) wrapper from your kernel repo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .. code-block:: bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ./tools/testing/kunit/kunit.py run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .. note::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) You may want to run ``make mrproper`` first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) If everything worked correctly, you should see the following:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .. code-block:: bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) Generating .config ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) Building KUnit Kernel ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) Starting KUnit Kernel ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) followed by a list of tests that are run. All of them should be passing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .. note::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) Because it is building a lot of sources for the first time, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ``Building KUnit kernel`` step may take a while.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) Running tests without the KUnit Wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) =======================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) If you'd rather not use the KUnit Wrapper (if, for example, you need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) integrate with other systems, or use an architecture other than UML), KUnit can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) be included in any kernel, and the results read out and parsed manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .. note::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) KUnit is not designed for use in a production system, and it's possible that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) tests may reduce the stability or security of the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) Configuring the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ----------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) In order to enable KUnit itself, you simply need to enable the ``CONFIG_KUNIT``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) Kconfig option (it's under Kernel Hacking/Kernel Testing and Coverage in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) menuconfig). From there, you can enable any KUnit tests you want: they usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) have config options ending in ``_KUNIT_TEST``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) KUnit and KUnit tests can be compiled as modules: in this case the tests in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) module will be run when the module is loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) Running the tests (w/o KUnit Wrapper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) -------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) Build and run your kernel as usual. Test output will be written to the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) log in `TAP <https://testanything.org/>`_ format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .. note::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) It's possible that there will be other lines and/or data interspersed in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) TAP output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) Writing your first test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) =======================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) In your kernel repo let's add some code that we can test. Create a file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ``drivers/misc/example.h`` with the contents:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .. code-block:: c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int misc_example_add(int left, int right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) create a file ``drivers/misc/example.c``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .. code-block:: c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #include "example.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int misc_example_add(int left, int right)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return left + right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) Now add the following lines to ``drivers/misc/Kconfig``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .. code-block:: kconfig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) config MISC_EXAMPLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) bool "My example"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) and the following lines to ``drivers/misc/Makefile``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .. code-block:: make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) obj-$(CONFIG_MISC_EXAMPLE) += example.o
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) Now we are ready to write the test. The test will be in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ``drivers/misc/example-test.c``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .. code-block:: c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #include <kunit/test.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #include "example.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Define the test cases. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void misc_example_add_test_basic(struct kunit *test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void misc_example_test_failure(struct kunit *test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) KUNIT_FAIL(test, "This test never passes.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static struct kunit_case misc_example_test_cases[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) KUNIT_CASE(misc_example_add_test_basic),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) KUNIT_CASE(misc_example_test_failure),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static struct kunit_suite misc_example_test_suite = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .name = "misc-example",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .test_cases = misc_example_test_cases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) kunit_test_suite(misc_example_test_suite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) Now add the following to ``drivers/misc/Kconfig``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .. code-block:: kconfig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) config MISC_EXAMPLE_TEST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) bool "Test for my example"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) depends on MISC_EXAMPLE && KUNIT=y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) and the following to ``drivers/misc/Makefile``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .. code-block:: make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) Now add it to your ``.kunitconfig``:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .. code-block:: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) CONFIG_MISC_EXAMPLE=y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) CONFIG_MISC_EXAMPLE_TEST=y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) Now you can run the test:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .. code-block:: bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ./tools/testing/kunit/kunit.py run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) You should see the following failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .. code-block:: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) [16:08:57] [PASSED] misc-example:misc_example_add_test_basic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) [16:08:57] [FAILED] misc-example:misc_example_test_failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) [16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) [16:08:57] This test never passes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) Congrats! You just wrote your first KUnit test!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) Next Steps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ==========
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Check out the :doc:`usage` page for a more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) in-depth explanation of KUnit.