blob: 4963b760d0b70cf7acddfeb8834cd744148aa52f [file] [log] [blame]
Imre Kis1d2fbdd2019-12-13 11:42:08 +01001CppUTest
2========
3
4This document is based on CppUTest v3.8. CppUtest is a unit testing framework
5for testing C and C++ code. This document introduces the basic features of the
6framework. For further information check the `official manual of CppUTest`_.
7
8
9Why CppUTest?
10-------------
11
12First of all it was not our goal to develop a new unit testing framework while
13plenty of open source solutions are already available. There were no special
14requirements agains the unit testing framework that would rule out all existing
15frameworks so we only had to choose a suitable one for our current and possible
16future needs.
17
18We ended up selecting CppUTest because of its small footprint and easy
19portability. It also goes along with the standard xUnit frameworks' principles
20and provides a standard interface to the outside world. Some details are listed
21below.
22
23- C/C++ support
24- Small footprint (compared to Google Test)
25- Easy to use on embedded systems
26- Built-in mocking system (CppUMock)
27- Implements four-phase testing pattern (setup, exercise, verify, teardown)
28- Selective run of test cases
29- Standard output format (JUnit, TeamCity)
30
31
32Assertions
33----------
34
35Generally is a good practice to use more specific assertions because it can
36output more informative error messages in case of a failure. The generic form or
37assertions is ``assert(expected, actual)``. Each assert type has a _TEXT variant
38for user defined error messages as last parameter.
39
40- Boolean
41
42 - ``CHECK(condition)`` - Same as ``CHECK_TRUE``
43 - ``CHECK_TRUE(condition)``
44 - ``CHECK_FALSE(condition)``
45
46- C string
47
48 - ``STRCMP_EQUAL(expected, actual)``
49 - ``STRNCMP_EQUAL(expected, actual, length)``
50 - ``STRCMP_NOCASE_EQUAL(expected, actual)``
51 - ``STRCMP_CONTAINS(expected, actual)``
52 - ``STRCMP_NOCASE_CONTAINS(expected, actual)``
53
54- Integer
55
56 - ``LONGS_EQUAL(expected, actual)``
57 - ``UNSIGNED_LONGS_EQUAL(expected, actual)``
58 - ``LONGLONGS_EQUAL(expected, actual)``
59 - ``UNSIGNED_LONGLONGS_EQUAL(expected, actual)``
60 - ``BYTES_EQUAL(expected, actual)``
61 - ``SIGNED_BYTES_EQUAL(expected, actual)``
62 - ``POINTERS_EQUAL(expected, actual)``
63 - ``FUNCTIONPOINTERS_EQUAL(expected, actual)``
64
65- Enums
66
67 - ``ENUMS_EQUAL_INT(expected, actual)``
68 - ``ENUMS_EQUAL_TYPE(underlying_type, expected, actual)``
69
70- Other assertions
71
72 - ``CHECK_EQUAL(expected, actual)`` - Requires ``operator=`` and
73 ``StringFrom(type)`` to be implemented
74 - ``CHECK_COMPARE(first, relop, second)`` - Same as ``CHECK_EQUAL`` but with
75 any type of compare
76 - ``DOUBLES_EQUAL(expected, actual, threshold)``
77 - ``MEMCMP_EQUAL(expected, actual, size)``
78 - ``BITS_EQUAL(expected, actual, mask)``
79 - ``FAIL()`` or ``FAIL_TEST()`` - Test case fails if called
80 - ``CHECK_THROWS(expected, expression)`` - Catching C++ exceptions
81
82- Miscellaneous macros
83
84 - ``IGNORE_TEST`` - Same as ``TEST`` but it’s not called
85 - ``TEST_EXIT`` - Exists test
86 - ``UT_CRASH()`` - Crashes the test which is easy to catch with debugger
87 - ``UT_PRINT(text)`` - Generic print function
88
89
90Test runner
91-----------
92
93Test cases are collected automatically. Under the hood the ``TEST`` macros are
94creating global instances of classes and their constructor registers the test
95cases into the test registry. This happens before entering the ``main``
96function. In the ``main`` function only the ``RUN_ALL_TESTS`` macro needs to be
97placed with the command line arguments passed to it. On executing the binary the
98command line arguments will control the behaviour of the test process.
99
100.. code-block:: C++
101
102 #include "CppUTest/CommandLineTestRunner.h"
103
104 int main(int argc, char* argv[]) {
105 return RUN_ALL_TESTS(argc, argv);
106 }
107
108The default ``main`` implementation is added to all unit test suites by the
109build system.
110
111
112Command line options
113--------------------
114
115Command line options are available mainly for configuring the output format of
116the test binary and for filtering test groups or cases.
117
118- Output
119
120 - ``-v`` - Prints each test name before running them
121 - ``-c`` - Colorized output
122 - ``-o{normal, junit, teamcity}`` - Output format, junit can be processed by
123 most CIs
124 - ``-k packageName`` - Package name for junit output
125 - ``-lg`` - List test groups
126 - ``-ln`` - List test cases
127
128- Other
129
130 - ``-p`` - Runs each test case in separate processes
131 - ``-ri`` - Runs ignored test cases
132 - ``-r#`` - Repeats testing ``#`` times
133 - ``-s seed`` - Shuffles tests
134
135- Filtering test cases
136
137 - ``"TEST(groupName, testName)"`` - Running single test
138 - ``"IGNORE_TEST(groupName, testName)"`` -- Running single ignored test
139 - ``-g text`` - Runing groups containing text
140 - ``-n text`` - Runing tests containing text
141 - ``-sg text`` - Runing groups matching text
142 - ``-sn text`` - Runing tests matching text
143 - ``-xg text`` - Excluding groups containing text
144 - ``-xn text`` - Excluding tests containing text
145 - ``-xsg text`` - Excluding groups matching text
146 - ``-xsn text`` - Excluding tests matching text
147
148
149Troubleshooting
150---------------
151
152Output messages
153^^^^^^^^^^^^^^^
154
155When one of tests fails the first step is to run it separately and check its
156output message. Usually it shows the exact line of the file where the error
157happened.
158
159::
160
161 test_memcmp.cpp:17: error: Failure in TEST(memcmp, empty)
162 expected <1 0x1>
163 but was <0 0x0>
164
165The executed tests can be followed by adding ``-v`` command line option.
166
167::
168
169 ./memcmp -v
170 TEST(memcmp, different) - 0 ms
171 TEST(memcmp, same) - 0 ms
172 TEST(memcmp, empty) - 0 ms
173
174 OK (3 tests, 3 ran, 1 checks, 0 ignored, 0 filtered out, 0 ms)
175
176
177Catching failure with debugger
178^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
179
180If a failure happens in a helper function or in a loop where the assertion
181is called multiple times it is harder to get the exact environment of a failure.
182In this case it's a good practice to put a ``UT_CRASH()`` call into a
183conditional block which hits when the failure happens. This way the debugger can
184stop on failure because the code emits a signal.
185
186.. code-block:: C++
187
188 TEST(magic, iterate) {
189 int result;
190
191 for(int i = 0; i < 1000; i++) {
192 result = magic_function(i);
193
194 // Debug code
195 if (result) {
196 UT_CRASH();
197 }
198
199 LONGS_EQUAL(0, result);
200 }
201 }
202
203
204Using ``FAIL`` macro
205^^^^^^^^^^^^^^^^^^^^
206
207It's recommended to use ``FAIL`` macro in conditions that should never occur in
208tests. For example if a test case loads test data from an external file but the
209file could not be opened the ``FAIL`` macro should be used with an informative
210message.
211
212.. code-block:: C++
213
214 fd = open("test.bin", O_RDONLY);
215 if (fd < 0) {
216 FAIL("test.bin open failed");
217 }
218
219
220Interference between test cases
221^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
222
223Test cases can interfere if there's a global resource which was not restored to
224its original state after leaving a test case. This can be hard to find but at
225least the it's easy to make sure that this is root case of an error. Let's
226assume there's a global variable which is set during the test case but it
227original value is not restore at the end. CppUTest has an command line option
228for running each test case in separate process. This makes the global variable
229to have its original value at the beginning of the test cases. Basically if the
230test works by passing argument ``-p`` when running but fails without it, there's
231a good chance for having an interference between test cases.
232
233.. code-block:: C++
234
235 int x = 0;
236
237 TEST_GROUP(crosstalk) {
238 };
239
240 TEST(crosstalk, a) {
241 LONGS_EQUAL(0, x);
242 x = 1;
243 }
244
245 TEST(crosstalk, b) {
246 LONGS_EQUAL(0, x);
247 x = 1;
248 }
249
250 TEST(crosstalk, c) {
251 LONGS_EQUAL(0, x);
252 x = 1;
253 }
254
255By running the test executable with different command line arguments it produces
256a different result.
257
258.. code-block::
259
260 ./crosstalk -v
261
262 TEST(crosstalk, c) - 0 ms
263 TEST(crosstalk, b)
264 test_crosstalk.cpp:37: error:
265 Failure in TEST(crosstalk, b)
266 expected <0 0x0>
267 but was <1 0x1>
268
269 - 0 ms
270 TEST(crosstalk, a)
271 test_crosstalk.cpp:32: error: Failure in TEST(crosstalk, a)
272 expected <0 0x0>
273 but was <1 0x1>
274
275 - 0 ms
276
277 Errors (2 failures, 3 tests, 3 ran, 3 checks, 0 ignored, 0 filtered out, 0 ms)
278
279 ./crosstalk -v -p
280 TEST(crosstalk, c) - 1 ms
281 TEST(crosstalk, b) - 0 ms
282 TEST(crosstalk, a) - 0 ms
283
284 OK (3 tests, 0 ran, 0 checks, 0 ignored, 0 filtered out, 2 ms)
285
286
287--------------
288
289*Copyright (c) 2019, Arm Limited. All rights reserved.*
290
291.. _`official manual of CppUTest`: https://cpputest.github.io/