Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_unit_test / docs.rst
1 .. _module-pw_unit_test:
2
3 ------------
4 pw_unit_test
5 ------------
6 ``pw_unit_test`` unit testing library with a `Google Test`_-compatible API,
7 built on top of embedded-friendly primitives.
8
9 .. _Google Test: https://github.com/google/googletest/blob/master/googletest/docs/primer.md
10
11 ``pw_unit_test`` is a portable library which can run on almost any system from
12 from bare metal to a full-fledged desktop OS. It does this by offloading the
13 responsibility of test reporting and output to the underlying system,
14 communicating its results through a common interface. Unit tests can be written
15 once and run under many different environments, empowering developers to write
16 robust, high quality code.
17
18 ``pw_unit_test`` is still under development and lacks many features expected in
19 a complete testing framework; nevertheless, it is already used heavily within
20 Pigweed.
21
22 .. note::
23
24   This documentation is currently incomplete.
25
26 Writing unit tests
27 ==================
28
29 ``pw_unit_test``'s interface is largely compatible with `Google Test`_. Refer to
30 the Google Test documentation for examples of to define unit test cases.
31
32 .. note::
33
34   A lot of Google Test's more advanced features are not yet implemented. To
35   request a feature addition, please
36   `let us know <mailto:pigweed@googlegroups.com>`_.
37
38 Using the test framework
39 ========================
40
41 The EventHandler interface
42 ^^^^^^^^^^^^^^^^^^^^^^^^^^
43 The ``EventHandler`` class in ``public/pw_unit_test/event_handler.h`` defines
44 the interface through which ``pw_unit_test`` communicates the results of its
45 test runs. A platform using ``pw_unit_test`` must register an event handler with
46 the unit testing framework to receive test output.
47
48 As the framework runs tests, it calls the event handler's callback functions to
49 notify the system of various test events. The system can then choose to perform
50 any necessary handling or aggregation of these events, and report them back to
51 the developer.
52
53 Predefined event handlers
54 -------------------------
55 Pigweed provides some standard event handlers upstream to simplify the process
56 of getting started using ``pw_unit_test``.
57
58 * ``SimplePrintingEventHandler``: An event handler that writes Google Test-style
59   output to a specified sink.
60
61   .. code::
62
63     [==========] Running all tests.
64     [ RUN      ] Status.Default
65     [       OK ] Status.Default
66     [ RUN      ] Status.ConstructWithStatusCode
67     [       OK ] Status.ConstructWithStatusCode
68     [ RUN      ] Status.AssignFromStatusCode
69     [       OK ] Status.AssignFromStatusCode
70     [ RUN      ] Status.CompareToStatusCode
71     [       OK ] Status.CompareToStatusCode
72     [ RUN      ] Status.Ok_OkIsTrue
73     [       OK ] Status.Ok_OkIsTrue
74     [ RUN      ] Status.NotOk_OkIsFalse
75     [       OK ] Status.NotOk_OkIsFalse
76     [ RUN      ] Status.KnownString
77     [       OK ] Status.KnownString
78     [ RUN      ] Status.UnknownString
79     [       OK ] Status.UnknownString
80     [==========] Done running all tests.
81     [  PASSED  ] 8 test(s).
82
83
84 * ``LoggingEventHandler``: An event handler which uses the ``pw_log`` module to
85   output test results, to integrate with the system's existing logging setup.
86
87 .. _running-tests:
88
89 Running tests
90 ^^^^^^^^^^^^^
91 To run unit tests, link the tests into a single binary with the unit testing
92 framework, register an event handler, and call the ``RUN_ALL_TESTS`` macro.
93
94 .. code:: cpp
95
96   #include "pw_unit_test/framework.h"
97   #include "pw_unit_test/simple_printing_event_handler.h"
98
99   void WriteString(const std::string_view& string, bool newline) {
100     printf("%s", string.data());
101     if (newline) {
102       printf("\n");
103     }
104   }
105
106   int main() {
107     pw::unit_test::SimplePrintingEventHandler handler(WriteString);
108     pw::unit_test::RegisterEventHandler(&handler);
109     return RUN_ALL_TESTS();
110   }
111
112 Build system integration
113 ^^^^^^^^^^^^^^^^^^^^^^^^
114 ``pw_unit_test`` integrates directly into Pigweed's GN build system. To define
115 simple unit tests, set the ``pw_unit_test_MAIN`` build variable to a target
116 which configures the test framework as described in the :ref:`running-tests`
117 section, and use the ``pw_test`` template to register your test code.
118
119 .. code::
120
121   import("$dir_pw_unit_test/test.gni")
122
123   pw_test("foo_test") {
124     sources = [ "foo_test.cc" ]
125   }
126
127 The ``pw_unit_test`` module provides a few optional libraries to simplify setup:
128
129  - ``simple_printing_event_handler```: When running tests, output test results
130    as plain text over ``pw_sys_io``.
131  - ``simple_printing_main``: Implements a ``main()`` function that simply runs
132    tests using the ``simple_printing_event_handler``.
133  - ``logging_event_handler``: When running tests, log test results as
134    plain text using pw_log (ensure your target has set a ``pw_log`` backend).
135  - ``logging_main``: Implements a ``main()`` function that simply runs tests
136    using the ``logging_event_handler``.
137
138
139 pw_test template
140 ----------------
141 ``pw_test`` defines a single unit test suite. It creates several sub-targets.
142
143 * ``<target_name>``: The test suite within a single binary. The test code is
144   linked against the target set in the build arg ``pw_unit_test_MAIN``.
145 * ``<target_name>.run``: If ``pw_unit_test_AUTOMATIC_RUNNER`` is set, this
146   target runs the test as part of the build.
147 * ``<target_name>.lib``: The test sources without ``pw_unit_test_MAIN``.
148
149 **Arguments**
150
151 * All GN executable arguments are accepted and forwarded to the underlying
152   ``pw_executable``.
153 * ``enable_if``: Boolean indicating whether the test should be built. If false,
154   replaces the test with an empty target. Default true.
155 * ``test_main``: Target label to add to the tests's dependencies to provide the
156   ``main()`` function. Defaults to ``pw_unit_test_MAIN``. Set to ``""`` if
157   ``main()`` is implemented in the test's ``sources``.
158
159 **Example**
160
161 .. code::
162
163   import("$dir_pw_unit_test/test.gni")
164
165   pw_test("large_test") {
166     sources = [ "large_test.cc" ]
167     enable_if = device_has_1m_flash
168   }
169
170
171 pw_test_group template
172 ----------------------
173 ``pw_test_group`` defines a collection of tests or other test groups. It creates
174 several sub-targets:
175
176 * ``<target_name>``: The test group itself.
177 * ``<target_name>.run``: If ``pw_unit_test_AUTOMATIC_RUNNER`` is set, this
178   target runs all of the tests in the group and all of its group dependencies
179   individually.
180 * ``<target_name>.lib``: The sources of all of the tests in this group and its
181   dependencies.
182 * ``<target_name>.bundle``: All of the tests in the group and its dependencies
183   bundled into a single binary.
184 * ``<target_name>.bundle.run``: Automatic runner for the test bundle.
185
186 **Arguments**
187
188 * ``tests``: List of the ``pw_test`` targets in the group.
189 * ``group_deps``: List of other ``pw_test_group`` targets on which this one
190   depends.
191 * ``enable_if``: Boolean indicating whether the group target should be created.
192   If false, an empty GN group is created instead. Default true.
193
194 **Example**
195
196 .. code::
197
198   import("$dir_pw_unit_test/test.gni")
199
200   pw_test_group("tests") {
201     tests = [
202       ":bar_test",
203       ":foo_test",
204     ]
205   }
206
207   pw_test("foo_test") {
208     # ...
209   }
210
211   pw_test("bar_test") {
212     # ...
213   }
214
215 RPC service
216 ===========
217 ``pw_unit_test`` provides an RPC service which runs unit tests on demand and
218 streams the results back to the client. The service is defined in
219 ``pw_unit_test_proto/unit_test.proto``, and implemented by the GN target
220 ``$dir_pw_unit_test:rpc_service``.
221
222 To set up RPC-based unit tests in your application, instantiate a
223 ``pw::unit_test::UnitTestService`` and register it with your RPC server.
224
225 .. code:: c++
226
227   #include "pw_rpc/server.h"
228   #include "pw_unit_test/unit_test_service.h"
229
230   // Server setup; refer to pw_rpc docs for more information.
231   pw::rpc::Channel channels[] = {
232    pw::rpc::Channel::Create<1>(&my_output),
233   };
234   pw::rpc::Server server(channels);
235
236   pw::unit_test::UnitTestService unit_test_service;
237
238   void RegisterServices() {
239     server.RegisterService(unit_test_services);
240   }
241
242 All tests flashed to an attached device can be run via python by calling
243 ``pw_unit_test.rpc.run_tests()`` with a RPC client services object that has
244 the unit testing RPC service enabled. By default, the results will output via
245 logging.
246
247 .. code:: python
248
249   from pw_hdlc.rpc import HdlcRpcClient
250   from pw_unit_test.rpc import run_tests
251
252   PROTO = Path(os.environ['PW_ROOT'],
253                'pw_unit_test/pw_unit_test_proto/unit_test.proto')
254
255   client = HdlcRpcClient(serial.Serial(device, baud), PROTO)
256   run_tests(client.rpcs())