| .. _module-pw_unit_test: |
| |
| ============ |
| pw_unit_test |
| ============ |
| .. pigweed-module:: |
| :name: pw_unit_test |
| |
| .. tab-set:: |
| |
| .. tab-item:: mylib_test.cpp |
| |
| .. code-block:: c++ |
| |
| #include "mylib.h" |
| |
| #include "pw_unit_test/framework.h" |
| |
| namespace { |
| |
| TEST(MyTestSuite, MyTestCase) { |
| pw::InlineString<32> expected = "(╯°□°)╯︵ ┻━┻"; |
| pw::InlineString<32> actual = mylib::flip_table(); |
| EXPECT_STREQ(expected.c_str(), actual.c_str()); |
| } |
| |
| } |
| |
| .. tab-item:: BUILD.bazel |
| |
| .. code-block:: python |
| |
| load("@pigweed//pw_build:pigweed.bzl", "pw_cc_test") |
| |
| cc_library( |
| name = "mylib", |
| srcs = ["mylib.cc"], |
| hdrs = ["mylib.h"], |
| includes = ["."], |
| deps = ["@pigweed//pw_string"], |
| ) |
| |
| pw_cc_test( |
| name = "mylib_test", |
| srcs = ["mylib_test.cc"], |
| deps = [ |
| "@pigweed//pw_unit_test", |
| ":mylib", |
| ], |
| ) |
| |
| .. tab-item:: mylib.cc |
| |
| .. code-block:: c++ |
| |
| #include "mylib.h" |
| |
| #include "pw_string/string.h" |
| |
| namespace mylib { |
| |
| pw::InlineString<32> flip_table() { |
| pw::InlineString<32> textmoji = "(╯°□°)╯︵ ┻━┻"; |
| return textmoji; |
| } |
| |
| } |
| |
| .. tab-item:: mylib.h |
| |
| .. code-block:: c++ |
| |
| #include "pw_string/string.h" |
| |
| namespace mylib { |
| |
| pw::InlineString<32> flip_table(); |
| |
| } |
| |
| .. _GoogleTest: https://google.github.io/googletest/ |
| |
| ``pw_unit_test`` provides a `GoogleTest`_-compatible unit testing framework for |
| Pigweed-based projects. The default backend is a lightweight subset of |
| GoogleTest that uses embedded-friendly primitives. |
| |
| .. grid:: 1 |
| |
| .. grid-item-card:: :octicon:`rocket` Quickstart |
| :link: module-pw_unit_test-quickstart |
| :link-type: ref |
| :class-item: sales-pitch-cta-primary |
| |
| Set up your project for testing and learn testing basics. |
| |
| .. grid:: 2 |
| |
| .. grid-item-card:: :octicon:`list-unordered` Guides |
| :link: module-pw_unit_test-guides |
| :link-type: ref |
| :class-item: sales-pitch-cta-secondary |
| |
| Learn how to do common tasks. |
| |
| .. grid-item-card:: :octicon:`code-square` C++ API reference |
| :link: module-pw_unit_test-cpp |
| :link-type: ref |
| :class-item: sales-pitch-cta-secondary |
| |
| Get detailed C++ API reference information. |
| |
| .. grid:: 2 |
| |
| .. grid-item-card:: :octicon:`code-square` Bazel API reference |
| :link: module-pw_unit_test-bazel |
| :link-type: ref |
| :class-item: sales-pitch-cta-secondary |
| |
| Get detailed Bazel API reference information. |
| |
| .. grid-item-card:: :octicon:`code-square` GN API reference |
| :link: module-pw_unit_test-gn |
| :link-type: ref |
| :class-item: sales-pitch-cta-secondary |
| |
| Get detailed GN API reference information. |
| |
| .. grid:: 2 |
| |
| .. grid-item-card:: :octicon:`code-square` CMake API reference |
| :link: module-pw_unit_test-cmake |
| :link-type: ref |
| :class-item: sales-pitch-cta-secondary |
| |
| Get detailed CMake API reference information. |
| |
| .. grid-item-card:: :octicon:`code-square` Python API reference |
| :link: module-pw_unit_test-py |
| :link-type: ref |
| :class-item: sales-pitch-cta-secondary |
| |
| Get detailed Python API reference information. |
| |
| .. _module-pw_unit_test-quickstart: |
| |
| ---------- |
| Quickstart |
| ---------- |
| |
| Set up your build system |
| ======================== |
| .. tab-set:: |
| |
| .. tab-item:: Bazel |
| |
| Load the :ref:`module-pw_unit_test-pw_cc_test` rule and create a target |
| that depends on ``@pigweed//pw_unit_test`` as well as the code you want |
| to test: |
| |
| .. code-block:: python |
| |
| load("@pigweed//pw_build:pigweed.bzl", "pw_cc_test") |
| |
| cc_library( |
| name = "mylib", |
| srcs = ["mylib.cc"], |
| hdrs = ["mylib.h"], |
| includes = ["."], |
| deps = ["..."], |
| ) |
| |
| pw_cc_test( |
| name = "mylib_test", |
| srcs = ["mylib_test.cc"], |
| deps = [ |
| "@pigweed//pw_unit_test", |
| ":mylib", |
| ], |
| ) |
| |
| This assumes that your Bazel ``WORKSPACE`` has a `repository |
| <https://bazel.build/concepts/build-ref#repositories>`_ named ``@pigweed`` |
| that points to the upstream Pigweed repository. |
| |
| See also :ref:`module-pw_unit_test-bazel`. |
| |
| .. tab-item:: GN |
| |
| Import ``$dir_pw_unit_test/test.gni`` and create a ``pw_test`` rule that |
| depends on the code you want to test: |
| |
| .. code-block:: python |
| |
| import("$dir_pw_unit_test/test.gni") |
| |
| pw_source_set("mylib") { |
| sources = [ "mylib.cc" ] |
| } |
| |
| pw_test("mylib_test") { |
| sources = [ "mylib_test.cc" ] |
| deps = [ ":mylib" ] |
| } |
| |
| See :ref:`module-pw_unit_test-gn` for more information. |
| |
| ``pw_unit_test`` generates a simple ``main`` function for running tests on |
| :ref:`target-host`. See :ref:`module-pw_unit_test-main` to learn how to |
| create your own ``main`` function for running on-device tests. |
| |
| Write tests |
| =========== |
| Create test suites and test cases: |
| |
| .. code-block:: c++ |
| |
| #include "mylib.h" |
| |
| #include "pw_unit_test/framework.h" |
| |
| namespace { |
| |
| TEST(MyTestSuite, MyTestCase) { |
| pw::InlineString<32> expected = "(╯°□°)╯︵ ┻━┻"; |
| pw::InlineString<32> actual = app::flip_table(); |
| EXPECT_STREQ(expected.c_str(), actual.c_str()); |
| } |
| |
| } |
| |
| ``pw_unit_test`` provides a standard set of ``TEST``, ``EXPECT``, ``ASSERT`` |
| and ``FAIL`` macros. The default backend, ``pw_unit_test:light``, offers an |
| embedded-friendly implementation which prioritizes small code size. |
| |
| Alternativley, users can opt into a larger set of assertion macros, matchers, |
| and more detailed error messages by using the ``pw_unit_test:googletest`` |
| backend. See :ref:`module-pw_unit_test-backends`. |
| |
| See `GoogleTest Primer <https://google.github.io/googletest/primer.html>`_ for |
| the basics of using GoogleTest. |
| |
| Run tests |
| ========= |
| .. tab-set:: |
| |
| .. tab-item:: Bazel |
| |
| .. code-block:: console |
| |
| $ bazel test //src:mylib_test |
| |
| .. tab-item:: GN |
| |
| Run the generated test binary: |
| |
| .. code-block:: console |
| |
| $ ./out/.../mylib_test |
| |
| .. _module-pw_unit_test-guides: |
| |
| ------ |
| Guides |
| ------ |
| |
| .. _module-pw_unit_test-backends: |
| |
| Choose a backend |
| ================ |
| The default backend, ``pw_unit_test:light``, is a lightweight subset of |
| GoogleTest that uses embedded-friendly primitives. It's also highly portable |
| because it offloads the responsibility of test reporting and output to the |
| underlying system, communicating its results through a common interface. This |
| lets you write unit tests once and run them under many different environments. |
| |
| If the :ref:`subset <module-pw_unit_test-compatibility>` of GoogleTest that |
| ``pw_unit_test:light`` supports doesn't meet your needs, you can access the |
| full upstream GoogleTest API through ``pw_unit_test:googletest``. See |
| :ref:`module-pw_unit_test-upstream`. |
| |
| .. _module-pw_unit_test-main: |
| |
| Create a custom ``main`` function |
| ================================= |
| For simple unit tests that run on :ref:`target-host` the workflow outlined in |
| :ref:`module-pw_unit_test-quickstart` is all you need. Pigweed's build templates |
| generate a simple ``main`` function to run the tests with. |
| |
| To do more complex testing, such as on-device testing: |
| |
| 1. Create your own ``main`` function: |
| |
| .. code-block:: c++ |
| |
| #include "pw_unit_test/framework.h" |
| // pw_unit_test:light requires an event handler to be configured. |
| #include "pw_unit_test/simple_printing_event_handler.h" |
| |
| void WriteString(std::string_view string, bool newline) { |
| printf("%s", string.data()); |
| if (newline) { |
| printf("\n"); |
| } |
| } |
| |
| int main() { |
| // Make the binary compatible with pw_unit_test:googletest. Has no effect |
| // when using pw_unit_test:light. |
| testing::InitGoogleTest(); |
| // Set up the event handler for pw_unit_test:light. |
| pw::unit_test::SimplePrintingEventHandler handler(WriteString); |
| pw::unit_test::RegisterEventHandler(&handler); |
| return RUN_ALL_TESTS(); |
| } |
| |
| See :ref:`module-pw_unit_test-event-handlers` for more information about |
| handling events. |
| |
| 2. Set the build argument that instructs your build system to use your custom |
| ``main`` function: |
| |
| * Bazel: :option:`pw_unit_test_main` |
| * GN: :option:`pw_unit_test_MAIN` |
| |
| .. _module-pw_unit_test-event-handlers: |
| |
| Create event handlers |
| ===================== |
| .. _//pw_unit_test/public/pw_unit_test/event_handler.h: https://cs.opensource.google/pigweed/pigweed/+/main:pw_unit_test/public/pw_unit_test/event_handler.h |
| |
| The ``pw::unit_test::EventHandler`` class defines the interface through which |
| ``pw_unit_test:light`` communicates the results of its test runs. If you're |
| using a :ref:`custom main function <module-pw_unit_test-main>` you need to |
| register an event handler to receive test output from the framework. |
| |
| .. _module-pw_unit_test-predefined-event-handlers: |
| |
| Predefined event handlers |
| ------------------------- |
| Pigweed provides some standard event handlers to simplify the process of |
| getting started with ``pw_unit_test:light``. All event handlers provide for |
| GoogleTest-style output using the shared |
| :cpp:class:`pw::unit_test::GoogleTestStyleEventHandler` base. Example |
| output: |
| |
| .. code-block:: |
| |
| [==========] Running all tests. |
| [ RUN ] Status.Default |
| [ OK ] Status.Default |
| [ RUN ] Status.ConstructWithStatusCode |
| [ OK ] Status.ConstructWithStatusCode |
| [ RUN ] Status.AssignFromStatusCode |
| [ OK ] Status.AssignFromStatusCode |
| [ RUN ] Status.CompareToStatusCode |
| [ OK ] Status.CompareToStatusCode |
| [ RUN ] Status.Ok_OkIsTrue |
| [ OK ] Status.Ok_OkIsTrue |
| [ RUN ] Status.NotOk_OkIsFalse |
| [ OK ] Status.NotOk_OkIsFalse |
| [ RUN ] Status.KnownString |
| [ OK ] Status.KnownString |
| [ RUN ] Status.UnknownString |
| [ OK ] Status.UnknownString |
| [==========] Done running all tests. |
| [ PASSED ] 8 test(s). |
| |
| .. _module-pw_unit_test-subset: |
| |
| Run a subset of test suites |
| =========================== |
| .. note:: This feature is only supported in C++17. |
| |
| .. _//pw_unit_test/light_public_overrides/pw_unit_test/framework_backend.h: https://cs.opensource.google/pigweed/pigweed/+/main:pw_unit_test/light_public_overrides/pw_unit_test/framework_backend.h |
| |
| To run only a subset of registered test suites, use the |
| ``pw::unit_test::SetTestSuitesToRun`` function. See |
| `//pw_unit_test/light_public_overrides/pw_unit_test/framework_backend.h`_. |
| |
| This is useful when you've got a lot of test suites bundled up into a |
| :ref:`single test binary <module-pw_unit_test-main>` and you only need |
| to run some of them. |
| |
| .. _module-pw_unit_test-skip: |
| |
| Skip tests in Bazel |
| =================== |
| Use ``target_compatible_with`` in Bazel to skip tests. The following test is |
| skipped when :ref:`using upstream GoogleTest <module-pw_unit_test-upstream>`: |
| |
| .. code-block:: |
| |
| load("//pw_build:pigweed.bzl", "pw_cc_test") |
| |
| pw_cc_test( |
| name = "no_upstream_test", |
| srcs = ["no_upstream_test.cc"], |
| target_compatible_with = select({ |
| "//pw_unit_test:light_setting": [], |
| "//conditions:default": ["@platforms//:incompatible"], |
| }), |
| } |
| |
| .. _module-pw_unit_test-static: |
| |
| Run tests in static libraries |
| ============================= |
| To run tests in a static library, use the |
| :c:macro:`PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST` macro. |
| |
| Linkers usually ignore tests through static libraries (i.e. ``.a`` files) |
| because test registration relies on the test instance's static constructor |
| adding itself to a global list of tests. When linking against a static library, |
| static constructors in an object file are ignored unless at least one entity |
| in that object file is linked. |
| |
| .. _module-pw_unit_test-upstream: |
| |
| Use upstream GoogleTest |
| ======================= |
| To use the upstream GoogleTest backend (``pw_unit_test:googletest``) instead |
| of the default backend: |
| |
| .. _GoogleTestHandlerAdapter: https://cs.opensource.google/pigweed/pigweed/+/main:pw_unit_test/public/pw_unit_test/googletest_handler_adapter.h |
| |
| 1. Clone the GoogleTest repository into your project. See |
| :ref:`module-pw_third_party_googletest`. |
| |
| 2. :ref:`Create a custom main function <module-pw_unit_test-main>`. |
| |
| 3. Combine `GoogleTestHandlerAdapter`_ with a :ref:`predefined event |
| handler <module-pw_unit_test-predefined-event-handlers>` to enable your |
| ``main`` function to work with upstream GoogleTest without modification. |
| |
| .. code-block:: c++ |
| |
| #include "pw_unit_test/framework.h" |
| #include "pw_unit_test/logging_event_handler.h" |
| |
| int main() { |
| testing::InitGoogleTest(); |
| pw::unit_test::LoggingEventHandler logger; |
| pw::unit_test::RegisterEventHandler(&logger); |
| return RUN_ALL_TESTS(); |
| } |
| |
| 4. If your tests needs GoogleTest functionality not included in the default |
| ``pw_unit_test:light`` backend, include the upstream GoogleTest headers |
| (e.g. ``gtest/gtest.h``) directly and guard your target definition to avoid |
| compiling with ``pw_unit_test:light`` (the default backend). |
| |
| .. _module-pw_unit_test-serial-runner: |
| |
| Run tests over serial |
| ===================== |
| To accelerate automated unit test bringup for devices with plain-text logging, |
| ``pw_unit_test`` provides a serial-based test runner in Python that triggers a |
| device flash and evaluates whether the test passed or failed based on the |
| produced output. |
| |
| To set up a serial test runner in Python: |
| |
| .. _//pw_unit_test/py/pw_unit_test/serial_test_runner.py: https://cs.opensource.google/pigweed/pigweed/+/main:pw_unit_test/py/pw_unit_test/serial_test_runner.py |
| |
| 1. Implement a ``SerialTestingDevice`` class for your device. See |
| `//pw_unit_test/py/pw_unit_test/serial_test_runner.py`_. |
| 2. Configure your device code to wait to run unit tests until |
| ``DEFAULT_TEST_START_CHARACTER`` is sent over the serial connection. |
| |
| .. _module-pw_unit_test-rpc: |
| |
| Run tests over RPC |
| ================== |
| .. _//pw_unit_test/pw_unit_test_proto/unit_test.proto: https://cs.opensource.google/pigweed/pigweed/+/main:pw_unit_test/pw_unit_test_proto/unit_test.proto |
| |
| ``pw_unit_test`` provides an RPC service which runs unit tests on demand and |
| streams the results back to the client. The service is defined in |
| `//pw_unit_test/pw_unit_test_proto/unit_test.proto`_. |
| |
| The RPC service is primarily intended for use with the default |
| ``pw_unit_test:light`` backend. It has some support for the upstream GoogleTest |
| backend (``pw_unit_test:googletest``), however some features (such as test suite |
| filtering) are missing. |
| |
| To set up RPC-based unit tests in your application: |
| |
| 1. Depend on the relevant target for your build system: |
| |
| * Bazel: ``@pigweed//pw_unit_test:rpc_service`` |
| * GN: ``$dir_pw_unit_test:rpc_service`` |
| |
| 2. Create a ``pw::unit_test::UnitTestService`` instance. |
| |
| 3. Register the instance with your RPC server. |
| |
| .. code-block:: c++ |
| |
| #include "pw_rpc/server.h" |
| #include "pw_unit_test/unit_test_service.h" |
| |
| pw::rpc::Channel channels[] = { |
| pw::rpc::Channel::Create<1>(&my_output), |
| }; |
| pw::rpc::Server server(channels); |
| |
| pw::unit_test::UnitTestService unit_test_service; |
| |
| void RegisterServices() { |
| server.RegisterService(unit_test_services); |
| } |
| |
| See :ref:`module-pw_rpc` for more guidance around setting up RPC. |
| |
| 4. Run tests that have been flashed to a device by calling |
| ``pw_unit_test.rpc.run_tests()`` in Python. The argument should be an RPC |
| client services object that has the unit testing RPC service enabled. By |
| default, the results output via logging. The return value is a |
| ``TestRecord`` dataclass instance containing the results of the test run. |
| |
| .. code-block:: python |
| |
| import serial |
| |
| from pw_hdlc import rpc |
| from pw_unit_test.rpc import run_tests |
| |
| PROTO = Path( |
| os.environ['PW_ROOT'], |
| 'pw_unit_test/pw_unit_test_proto/unit_test.proto' |
| ) |
| serial_device = serial.Serial(device, baud) |
| with rpc.SerialReader(serial_device) as reader: |
| with rpc.HdlcRpcClient( |
| reader, PROTO, rpc.default_channels(serial_device.write) |
| ) as client: |
| run_tests(client.rpcs()) |
| |
| .. _module-pw_unit_test-cpp: |
| |
| ----------------- |
| C++ API reference |
| ----------------- |
| |
| .. _module-pw_unit_test-compatibility: |
| |
| ``pw_unit_test:light`` API compatibility |
| ======================================== |
| ``pw_unit_test:light`` offers a number of primitives for test declaration, |
| assertion, event handlers, and configuration. |
| |
| .. note:: |
| |
| The ``googletest_test_matchers`` target which provides Pigweed-specific |
| ``StatusIs``, ``IsOkAndHolds``, ``ASSERT_OK``, and ``ASSERT_OK_AND_ASSIGN`` |
| isn't part of the ``pw_unit_test:light`` backend. These matchers are only |
| usable when including the full upstream GoogleTest backend. |
| |
| Missing features include: |
| |
| * GoogleMock and matchers (e.g. :c:macro:`EXPECT_THAT`). |
| * Death tests (e.g. :c:macro:`EXPECT_DEATH`). ``EXPECT_DEATH_IF_SUPPORTED`` |
| does nothing but silently passes. |
| * Value-parameterized tests. |
| * Stream messages (e.g. ``EXPECT_TRUE(...) << "My message"``) will compile, but |
| no message will be logged. |
| |
| See :ref:`module-pw_unit_test-upstream` for guidance on using the |
| upstream GoogleTest backend (``pw_unit_test:googletest``) instead of |
| ``pw_unit_test:light``. |
| |
| .. _module-pw_unit_test-declare: |
| |
| Test declaration |
| ================ |
| Note that ``TEST_F`` may allocate fixtures separately from the stack. |
| Large variables should be stored in test fixture fields, |
| rather than stack variables. This allows the test framework to statically ensure |
| that enough space is available to store these variables. |
| |
| .. doxygendefine:: TEST |
| .. doxygendefine:: GTEST_TEST |
| .. doxygendefine:: TEST_F |
| .. doxygendefine:: FRIEND_TEST |
| |
| .. _module-pw_unit_test-control: |
| |
| Test control |
| ============ |
| |
| .. doxygendefine:: FAIL |
| .. doxygendefine:: GTEST_FAIL |
| .. doxygendefine:: SUCCEED |
| .. doxygendefine:: GTEST_SUCCEED |
| .. doxygendefine:: GTEST_SKIP |
| .. doxygendefine:: ADD_FAILURE |
| .. doxygendefine:: RUN_ALL_TESTS |
| .. doxygendefine:: GTEST_HAS_DEATH_TEST |
| .. doxygendefine:: EXPECT_DEATH_IF_SUPPORTED |
| .. doxygendefine:: ASSERT_DEATH_IF_SUPPORTED |
| |
| .. _module-pw_unit_test-api-expect: |
| |
| Expectations |
| ============ |
| When a test fails an expectation, the framework marks the test as a failure |
| and then continues executing the test. They're useful when you want to |
| verify multiple dimensions of the same feature and see all the errors at the |
| same time. |
| |
| .. doxygendefine:: EXPECT_TRUE |
| .. doxygendefine:: EXPECT_FALSE |
| .. doxygendefine:: EXPECT_EQ |
| .. doxygendefine:: EXPECT_NE |
| .. doxygendefine:: EXPECT_GT |
| .. doxygendefine:: EXPECT_GE |
| .. doxygendefine:: EXPECT_LT |
| .. doxygendefine:: EXPECT_LE |
| .. doxygendefine:: EXPECT_NEAR |
| .. doxygendefine:: EXPECT_FLOAT_EQ |
| .. doxygendefine:: EXPECT_DOUBLE_EQ |
| .. doxygendefine:: EXPECT_STREQ |
| .. doxygendefine:: EXPECT_STRNE |
| |
| .. _module-pw_unit_test-api-assert: |
| |
| Assertions |
| ========== |
| Assertions work the same as expectations except they stop the execution of the |
| test as soon as a failed condition is met. |
| |
| .. doxygendefine:: ASSERT_TRUE |
| .. doxygendefine:: ASSERT_FALSE |
| .. doxygendefine:: ASSERT_EQ |
| .. doxygendefine:: ASSERT_NE |
| .. doxygendefine:: ASSERT_GT |
| .. doxygendefine:: ASSERT_GE |
| .. doxygendefine:: ASSERT_LT |
| .. doxygendefine:: ASSERT_LE |
| .. doxygendefine:: ASSERT_NEAR |
| .. doxygendefine:: ASSERT_FLOAT_EQ |
| .. doxygendefine:: ASSERT_DOUBLE_EQ |
| .. doxygendefine:: ASSERT_STREQ |
| .. doxygendefine:: ASSERT_STRNE |
| |
| .. _module-pw_unit_test-api-event-handlers: |
| |
| Event handlers |
| ============== |
| .. doxygenfunction:: pw::unit_test::RegisterEventHandler(EventHandler* event_handler) |
| .. doxygenclass:: pw::unit_test::EventHandler |
| :members: |
| .. doxygenclass:: pw::unit_test::GoogleTestHandlerAdapter |
| .. doxygenclass:: pw::unit_test::GoogleTestStyleEventHandler |
| .. doxygenclass:: pw::unit_test::SimplePrintingEventHandler |
| .. doxygenclass:: pw::unit_test::LoggingEventHandler |
| .. doxygenclass:: pw::unit_test::PrintfEventHandler |
| .. doxygenclass:: pw::unit_test::MultiEventHandler |
| .. doxygenclass:: pw::unit_test::TestRecordEventHandler |
| |
| .. _module-pw_unit_test-cpp-config: |
| |
| Configuration |
| ============= |
| .. doxygendefine:: PW_UNIT_TEST_CONFIG_EVENT_BUFFER_SIZE |
| .. doxygendefine:: PW_UNIT_TEST_CONFIG_MEMORY_POOL_SIZE |
| |
| .. _module-pw_unit_test-cpp-helpers: |
| |
| Helpers |
| ======= |
| .. doxygendefine:: PW_UNIT_TEST_LINK_FILE_CONTAINING_TEST |
| |
| .. _module-pw_unit_test-py: |
| |
| -------------------- |
| Python API reference |
| -------------------- |
| |
| .. _module-pw_unit_test-py-serial_test_runner: |
| |
| ``pw_unit_test.serial_test_runner`` |
| =================================== |
| .. automodule:: pw_unit_test.serial_test_runner |
| :members: |
| DEFAULT_TEST_START_CHARACTER, |
| SerialTestingDevice, |
| run_device_test, |
| |
| .. _module-pw_unit_test-py-rpc: |
| |
| ``pw_unit_test.rpc`` |
| ==================== |
| .. automodule:: pw_unit_test.rpc |
| :members: EventHandler, run_tests, TestRecord |
| |
| .. _module-pw_unit_test-helpers: |
| |
| ---------------------- |
| Build helper libraries |
| ---------------------- |
| The following helper libraries can simplify setup and are supported in all |
| build systems. |
| |
| .. object:: simple_printing_event_handler |
| |
| When running tests, output test results as plain text over ``pw_sys_io``. |
| |
| .. object:: simple_printing_main |
| |
| Implements a ``main()`` function that simply runs tests using the |
| ``simple_printing_event_handler``. |
| |
| .. object:: logging_event_handler |
| |
| When running tests, log test results as plain text using |
| :ref:`module-pw_log`. Make sure your target has set a ``pw_log`` backend. |
| |
| .. object:: logging_main |
| |
| Implements a ``main()`` function that simply runs tests using the |
| ``logging_event_handler``. |
| |
| .. _module-pw_unit_test-bazel: |
| |
| ------------------- |
| Bazel API reference |
| ------------------- |
| |
| See also :ref:`module-pw_unit_test-helpers`. |
| |
| .. _module-pw_unit_test-pw_cc_test: |
| |
| ``pw_cc_test`` |
| ============== |
| .. _cc_test: https://bazel.build/reference/be/c-cpp#cc_test |
| |
| ``pw_cc_test`` is a wrapper for `cc_test`_ that provides some defaults, such as |
| a dependency on ``@pigweed//pw_unit_test:main``. It supports and passes through |
| all the arguments recognized by ``cc_test``. |
| |
| .. _module-pw_unit_test-bazel-args: |
| |
| Bazel build arguments |
| ===================== |
| .. option:: pw_unit_test_backend <target> |
| |
| The GoogleTest implementation to use for Pigweed unit tests. This library |
| provides ``gtest/gtest.h`` and related headers. Defaults to |
| ``@pigweed//pw_unit_test:light``, which implements a subset of GoogleTest. |
| |
| Type: string (Bazel target label) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_main <target> |
| |
| Implementation of a main function for ``pw_cc_test`` unit test binaries. |
| |
| Type: string (Bazel target label) |
| |
| Usage: toolchain-controlled only |
| |
| .. _module-pw_unit_test-gn: |
| |
| ------------ |
| GN reference |
| ------------ |
| See also :ref:`module-pw_unit_test-helpers`. |
| |
| .. _module-pw_unit_test-pw_test: |
| |
| ``pw_test`` |
| =========== |
| ``pw_test`` defines a single unit test suite. |
| |
| Targets |
| ------- |
| |
| .. object:: <target_name> |
| |
| The test suite within a single binary. The test code is linked against |
| the target set in the build arg ``pw_unit_test_MAIN``. |
| |
| .. object:: <target_name>.run |
| |
| If ``pw_unit_test_AUTOMATIC_RUNNER`` is set, this target runs the test as |
| part of the build. |
| |
| .. object:: <target_name>.lib |
| |
| The test sources without ``pw_unit_test_MAIN``. |
| |
| Arguments |
| --------- |
| All GN executable arguments are accepted and forwarded to the underlying |
| ``pw_executable``. |
| |
| .. option:: enable_if |
| |
| Boolean indicating whether the test should be built. If false, replaces the |
| test with an empty target. Default true. |
| |
| .. _get_target_outputs: https://gn.googlesource.com/gn/+/main/docs/reference.md#func_get_target_outputs |
| |
| .. option:: source_gen_deps |
| |
| List of target labels that generate source files used by this test. The |
| labels must meet the constraints of GN's `get_target_outputs`_, namely they must have been previously defined in the |
| current file. This argument is required if a test uses generated source files |
| and ``enable_if`` can evaluate to false. |
| |
| .. option:: test_main |
| |
| Target label to add to the tests's dependencies to provide the ``main()`` |
| function. Defaults to ``pw_unit_test_MAIN``. Set to ``""`` if ``main()`` |
| is implemented in the test's ``sources``. |
| |
| .. option:: test_automatic_runner_args |
| |
| Array of args to pass to :ref:`automatic test |
| runner <module-pw_unit_test-serial-runner>`. Defaults to |
| ``pw_unit_test_AUTOMATIC_RUNNER_ARGS``. |
| |
| .. option:: envvars |
| |
| Array of ``key=value`` strings representing environment variables to set |
| when invoking the automatic test runner. |
| |
| Example |
| ------- |
| |
| .. code-block:: |
| |
| import("$dir_pw_unit_test/test.gni") |
| |
| pw_test("large_test") { |
| sources = [ "large_test.cc" ] |
| enable_if = device_has_1m_flash |
| } |
| |
| .. _module-pw_unit_test-pw_test_group: |
| |
| ``pw_test_group`` |
| ================= |
| ``pw_test_group`` defines a collection of tests or other test groups. |
| |
| Targets |
| ------- |
| .. object:: <target_name> |
| |
| The test group itself. |
| |
| .. object:: <target_name>.run |
| |
| If ``pw_unit_test_AUTOMATIC_RUNNER`` is set, this target runs all of the |
| tests in the group and all of its group dependencies individually. See |
| :ref:`module-pw_unit_test-serial-runner`. |
| |
| .. object:: <target_name>.lib |
| |
| The sources of all of the tests in this group and their dependencies. |
| |
| .. object:: <target_name>.bundle |
| |
| All of the tests in the group and its dependencies bundled into a single binary. |
| |
| .. object:: <target_name>.bundle.run |
| |
| Automatic runner for the test bundle. |
| |
| Arguments |
| --------- |
| .. option:: tests |
| |
| List of the ``pw_test`` targets in the group. |
| |
| .. option:: group_deps |
| |
| List of other ``pw_test_group`` targets on which this one depends. |
| |
| .. option:: enable_if |
| |
| Boolean indicating whether the group target should be created. If false, an |
| empty GN group is created instead. Default true. |
| |
| Example |
| ------- |
| .. code-block:: |
| |
| import("$dir_pw_unit_test/test.gni") |
| |
| pw_test_group("tests") { |
| tests = [ |
| ":bar_test", |
| ":foo_test", |
| ] |
| } |
| |
| pw_test("foo_test") { |
| # ... |
| } |
| |
| pw_test("bar_test") { |
| # ... |
| } |
| |
| .. _module-pw_unit_test-pw_facade_test: |
| |
| ``pw_facade_test`` |
| ================== |
| Pigweed facade test templates allow individual unit tests to build under the |
| current device target configuration while overriding specific build arguments. |
| This allows these tests to replace a facade's backend for the purpose of testing |
| the facade layer. |
| |
| Facade tests are disabled by default. To build and run facade tests, set the GN |
| arg :option:`pw_unit_test_FACADE_TESTS_ENABLED` to ``true``. |
| |
| .. warning:: |
| Facade tests are costly because each facade test will trigger a re-build of |
| every dependency of the test. While this sounds excessive, it's the only |
| technically correct way to handle this type of test. |
| |
| .. warning:: |
| Some facade test configurations may not be compatible with your target. Be |
| careful when running a facade test on a system that heavily depends on the |
| facade being tested. |
| |
| .. _module-pw_unit_test-gn-args: |
| |
| GN build arguments |
| ================== |
| .. option:: pw_unit_test_BACKEND <source_set> |
| |
| The GoogleTest implementation to use for Pigweed unit tests. This library |
| provides ``gtest/gtest.h`` and related headers. Defaults to |
| ``pw_unit_test:light``, which implements a subset of GoogleTest. |
| |
| Type: string (GN path to a source set) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_MAIN <source_set> |
| |
| Implementation of a main function for ``pw_test`` unit test binaries. |
| See :ref:`module-pw_unit_test-main`. |
| |
| Type: string (GN path to a source set) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_AUTOMATIC_RUNNER <executable> |
| |
| Path to a test runner to automatically run unit tests after they are built. |
| See :ref:`module-pw_unit_test-serial-runner`. |
| |
| If set, a ``pw_test`` target's ``<target_name>.run`` action invokes the |
| test runner specified by this argument, passing the path to the unit test to |
| run. If this is unset, the ``pw_test`` target's ``<target_name>.run`` step |
| will do nothing. |
| |
| Targets that don't support parallelized execution of tests (e.g. an |
| on-device test runner that must flash a device and run the test in serial) |
| should set ``pw_unit_test_POOL_DEPTH`` to ``1``. |
| |
| Type: string (name of an executable on ``PATH``, or a path to an executable) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_AUTOMATIC_RUNNER_ARGS <args> |
| |
| An optional list of strings to pass as args to the test runner specified by |
| ``pw_unit_test_AUTOMATIC_RUNNER``. |
| |
| Type: list of strings (args to pass to ``pw_unit_test_AUTOMATIC_RUNNER``) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_AUTOMATIC_RUNNER_TIMEOUT <timeout_seconds> |
| |
| An optional timeout to apply when running the automatic runner. Timeout is |
| in seconds. Defaults to empty which means no timeout. |
| |
| Type: string (number of seconds to wait before killing test runner) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_POOL_DEPTH <pool_depth> |
| |
| The maximum number of unit tests that may be run concurrently for the |
| current toolchain. Setting this to 0 disables usage of a pool, allowing |
| unlimited parallelization. |
| |
| Note: A single target with two toolchain configurations (e.g. ``release`` |
| and ``debug``) uses two separate test runner pools by default. Set |
| ``pw_unit_test_POOL_TOOLCHAIN`` to the same toolchain for both targets to |
| merge the pools and force serialization. |
| |
| Type: integer |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_POOL_TOOLCHAIN <toolchain> |
| |
| The toolchain to use when referring to the ``pw_unit_test`` runner pool. |
| When this is disabled, the current toolchain is used. This means that every |
| toolchain will use its own pool definition. If two toolchains should share |
| the same pool, this argument should be by one of the toolchains to the GN |
| path of the other toolchain. |
| |
| Type: string (GN path to a toolchain) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_EXECUTABLE_TARGET_TYPE <template name> |
| |
| The name of the GN target type used to build ``pw_unit_test`` executables. |
| |
| Type: string (name of a GN template) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_EXECUTABLE_TARGET_TYPE_FILE <gni file path> |
| |
| The path to the ``.gni`` file that defines |
| ``pw_unit_test_EXECUTABLE_TARGET_TYPE``. |
| |
| If ``pw_unit_test_EXECUTABLE_TARGET_TYPE`` is not the default of |
| ``pw_executable``, this ``.gni`` file is imported to provide the template |
| definition. |
| |
| Type: string (path to a .gni file) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_FACADE_TESTS_ENABLED <boolean> |
| |
| Controls whether to build and run facade tests. Facade tests add considerably |
| to build time, so they are disabled by default. |
| |
| .. option:: pw_unit_test_TESTONLY <boolean> |
| |
| Controls the ``testonly`` variable in ``pw_test``, ``pw_test_group``, and |
| miscellaneous testing targets. This is useful if your test libraries (e.g. |
| GoogleTest) used by pw_unit_test have the ``testonly`` flag set. False by |
| default for backwards compatibility. |
| |
| .. _module-pw_unit_test-cmake: |
| |
| --------------- |
| CMake reference |
| --------------- |
| See also :ref:`module-pw_unit_test-helpers`. |
| |
| .. _module-pw_unit_test-pw_add_test: |
| |
| ``pw_add_test`` |
| =============== |
| ``pw_add_test`` declares a single unit test suite. |
| |
| .. tip:: |
| Upstream Pigweed tests can be disabled in downstream projects by setting |
| ``pw_unit_test_ENABLE_PW_ADD_TEST`` to ``OFF`` before adding the ``pigweed`` |
| directory to an existing cmake build. |
| |
| .. code-block:: cmake |
| |
| set(pw_unit_test_ENABLE_PW_ADD_TEST OFF) |
| add_subdirectory(path/to/pigweed pigweed) |
| set(pw_unit_test_ENABLE_PW_ADD_TEST ON) |
| |
| See also: :ref:`module-pw_build-existing-cmake-project`. |
| |
| Targets |
| ------- |
| .. object:: {NAME} |
| |
| Depends on ``${NAME}.run`` if ``pw_unit_test_AUTOMATIC_RUNNER`` is set, else |
| it depends on ``${NAME}.bin``. |
| |
| .. object:: {NAME}.lib |
| |
| Contains the provided test sources as a library target, which can then be |
| linked into a test executable. |
| |
| .. object:: {NAME}.bin |
| |
| A standalone executable which contains only the test sources specified in the |
| ``pw_unit_test`` template. |
| |
| .. object:: {NAME}.run |
| |
| Runs the unit test executable after building it if |
| ``pw_unit_test_AUTOMATIC_RUNNER`` is set, else it fails to build. |
| |
| Required arguments |
| ------------------ |
| .. option:: NAME |
| |
| Name to use for the produced test targets specified above. |
| |
| Optional arguments |
| ------------------ |
| .. option:: SOURCES |
| |
| Source files for this library. |
| |
| .. option:: HEADERS |
| |
| Header files for this library. |
| |
| .. option:: PRIVATE_DEPS |
| |
| Private ``pw_target_link_targets`` arguments. |
| .. option:: PRIVATE_INCLUDES |
| |
| Public ``target_include_directories`` argument. |
| |
| .. option:: PRIVATE_DEFINES |
| |
| Private ``target_compile_definitions`` arguments. |
| |
| .. option:: PRIVATE_COMPILE_OPTIONS |
| |
| Private ``target_compile_options`` arguments. |
| |
| .. option:: PRIVATE_LINK_OPTIONS |
| |
| Private ``target_link_options`` arguments. |
| |
| Example |
| ------- |
| |
| .. code-block:: |
| |
| include($ENV{PW_ROOT}/pw_unit_test/test.cmake) |
| |
| pw_add_test(my_module.foo_test |
| SOURCES |
| foo_test.cc |
| PRIVATE_DEPS |
| my_module.foo |
| ) |
| |
| .. _module-pw_unit_test-pw_add_test_group: |
| |
| ``pw_add_test_group`` |
| ===================== |
| ``pw_add_test_group`` defines a collection of tests or other test groups. |
| |
| Targets |
| ------- |
| .. object:: {NAME} |
| |
| Depends on ``${NAME}.run`` if ``pw_unit_test_AUTOMATIC_RUNNER`` is set, else |
| it depends on ``${NAME}.bin``. |
| |
| .. object:: {NAME}.bundle |
| |
| Depends on ``${NAME}.bundle.run`` if ``pw_unit_test_AUTOMATIC_RUNNER`` is |
| set, else it depends on ``${NAME}.bundle.bin``. |
| |
| .. object:: {NAME}.lib |
| |
| Depends on ``${NAME}.bundle.lib``. |
| |
| .. object:: {NAME}.bin |
| |
| Depends on the provided ``TESTS``'s ``<test_dep>.bin`` targets. |
| |
| .. object:: {NAME}.run |
| |
| Depends on the provided ``TESTS``'s ``<test_dep>.run`` targets if |
| ``pw_unit_test_AUTOMATIC_RUNNER`` is set, else it fails to build. |
| |
| .. object:: {NAME}.bundle.lib |
| |
| Contains the provided tests bundled as a library target, which can then be |
| linked into a test executable. |
| |
| .. object:: {NAME}.bundle.bin |
| |
| Standalone executable which contains the bundled tests. |
| |
| .. object:: {NAME}.bundle.run |
| |
| Runs the ``{NAME}.bundle.bin`` test bundle executable after building it if |
| ``pw_unit_test_AUTOMATIC_RUNNER`` is set, else it fails to build. |
| |
| Required arguments |
| ------------------ |
| .. option:: NAME |
| |
| The name of the executable target to be created. |
| |
| .. option:: TESTS |
| |
| ``pw_add_test`` targets and ``pw_add_test_group`` bundles to be |
| included in this test bundle. |
| |
| Example |
| ------- |
| .. code-block:: |
| |
| include($ENV{PW_ROOT}/pw_unit_test/test.cmake) |
| |
| pw_add_test_group(tests |
| TESTS |
| bar_test |
| foo_test |
| ) |
| |
| pw_add_test(foo_test |
| # ... |
| ) |
| |
| pw_add_test(bar_test |
| # ... |
| ) |
| |
| .. _module-pw_unit_test-cmake-args: |
| |
| CMake build arguments |
| ===================== |
| .. option:: pw_unit_test_BACKEND <target> |
| |
| The GoogleTest implementation to use for Pigweed unit tests. This library |
| provides ``gtest/gtest.h`` and related headers. Defaults to |
| ``pw_unit_test.light``, which implements a subset of GoogleTest. |
| |
| Type: string (CMake target name) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_AUTOMATIC_RUNNER <executable> |
| |
| Path to a test runner to automatically run unit tests after they're built. |
| |
| If set, a ``pw_test`` target's ``${NAME}`` and ``${NAME}.run`` targets will |
| invoke the test runner specified by this argument, passing the path to the |
| unit test to run. If this is unset, the ``pw_test`` target's ``${NAME}`` will |
| only build the unit test(s) and ``${NAME}.run`` will fail to build. |
| |
| Type: string (name of an executable on the PATH, or path to an executable) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_AUTOMATIC_RUNNER_ARGS <args> |
| |
| An optional list of strings to pass as args to the test runner specified |
| by ``pw_unit_test_AUTOMATIC_RUNNER``. |
| |
| Type: list of strings (args to pass to pw_unit_test_AUTOMATIC_RUNNER) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_AUTOMATIC_RUNNER_TIMEOUT_SECONDS <timeout_seconds> |
| |
| An optional timeout to apply when running the automatic runner. Timeout is |
| in seconds. Defaults to empty which means no timeout. |
| |
| Type: string (number of seconds to wait before killing test runner) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_ADD_EXECUTABLE_FUNCTION <function name> |
| |
| The name of the CMake function used to build ``pw_unit_test`` executables. |
| The provided function must take a ``NAME`` and a ``TEST_LIB`` argument which |
| are the expected name of the executable target and the target which provides |
| the unit test(s). |
| |
| Type: string (name of a CMake function) |
| |
| Usage: toolchain-controlled only |
| |
| .. option:: pw_unit_test_ADD_EXECUTABLE_FUNCTION_FILE <cmake file path> |
| |
| The path to the ``.cmake`` file that defines |
| ``pw_unit_test_ADD_EXECUTABLE_FUNCTION``. |
| |
| Type: string (path to a ``.cmake`` file) |
| |
| Usage: toolchain-controlled only |