le_test.h

Go to the documentation of this file.
1 /**
2  * @page c_test Unit Testing API
3  *
4  * @ref le_test.h "API Reference"
5  *
6  * <HR>
7  *
8  * Unit testing is an important aspect of a quantifiable quality assurance methodology. Although
9  * unit testing requires some extra overhead (the writing of the unit tests) during the development
10  * process it can provide enormous benefits during the project life cycle.
11  *
12  * One benefit of writing unit tests is that it gets the developer using the interface to the
13  * unit they designed. This forces the developer to think about, and hopefully design for,
14  * usability of the interface early in the development cycle.
15  *
16  * Another major benefit to unit testing is that it provides a documented and verifiable level of
17  * correctness for the designed unit. This allows the developer to refactor the code more
18  * aggressively and to quickly verify its correctness. Unit tests can also be used to perform
19  * regression testing when adding new features.
20  *
21  * Despite the benefits of unit testing, unit tests are often omitted because of the initial
22  * overhead of writing the tests and the complexity of testing frameworks. Legato's Unit Test
23  * Framework is simple to use and very flexible and lightweight consisting of some
24  * handy macros.
25  *
26  * The Legato test framework outputs test results to the log in TAP format (prefixed by "TAP |")
27  * This allows test results to be processed with many test harnasses.
28  *
29  * @section c_test_setup Setting Up the Test Framework
30  *
31  * To setup the Legato Test Framework, call the @c LE_TEST_PLAN macro, once before any tests
32  * are started. The macro takes the total number of planned tests as single argument.
33  *
34  * @section c_test_testing Performing Tests
35  *
36  * To perform tests, call the @c LE_TEST_OK macro. The first argument is whether the
37  * test passed (true or false). The second argument is the name of the test.
38  *
39  * For example:
40  *
41  * @code
42  * #include "legato.h"
43  *
44  * // Returns true if the test passes, otherwise returns false.
45  * bool ComplexTest(void)
46  * {
47  * int expectedValue;
48  *
49  * // Do some initializations and/or calculations.
50  * ...
51  *
52  * // Call one of the unit-under-test's interface function and check it's return value against
53  * // an expected value that was calculated earlier.
54  * return (unitUnderTest_foo2() == expectedValue);
55  * }
56  *
57  *
58  * int main (void)
59  * {
60  * // Setup the Legato Test Framework.
61  * LE_TEST_PLAN(2);
62  *
63  * // Run the tests.
64  * // Do some initializations and/or calculations.
65  * ...
66  *
67  * LE_TEST_OK(TestFunction(arguments) == EXPECTED_VALUE, "simple test");
68  * LE_TEST_OK(ComplexTest(), "complex test");
69  *
70  * // Exit with the number of failed tests as the exit code.
71  * LE_TEST_EXIT;
72  * }
73  * @endcode
74  *
75  * @section c_test_exit Exiting a Test Program
76  *
77  * When a test program is finished executing tests and needs to exit, it should exit
78  * using the LE_TEST_EXIT macro.
79  *
80  * If a test suite needs to exit early it should use the LE_TEST_FATAL() macro. This will
81  * log a message indicating the test suite has been aborted. LE_ASSERT()
82  * and LE_FATAL() macros should not be used as they will not print this message.
83  *
84  * As a convenience you can also use the LE_TEST_ASSERT() macro which will abort the test suite
85  * if the test fails. This is useful if running further test cases is pointless after this failure.
86  *
87  * @section c_test_result Test Results
88  *
89  * The LE_TEST_EXIT macro will cause the process to exit with the number of failed tests as the exit
90  * code.
91  *
92  * @note The log message format depends on the current log settings.
93  *
94  * @section c_test_multiThread Multi-Threaded Tests
95  *
96  * For unit tests that contain multiple threads run the various tests, these macros can still
97  * be used. However your test program should ensure that only one thread uses the unit test
98  * API at a time.
99  *
100  * <HR>
101  *
102  * Copyright (C) Sierra Wireless Inc.
103  */
104 
105 //--------------------------------------------------------------------------------------------------
106 /** @file le_test.h
107  *
108  * Legato @ref c_test include file.
109  *
110  * Copyright (C) Sierra Wireless Inc.
111  */
112 
113 #ifndef LEGATO_TEST_INCLUDE_GUARD
114 #define LEGATO_TEST_INCLUDE_GUARD
115 
116 
117 //--------------------------------------------------------------------------------------------------
118 /**
119  * @name Local definitions that should not be used directly.
120  *
121  * @{
122  */
123 //--------------------------------------------------------------------------------------------------
124 void _le_test_Init(int testCount);
125 void _le_test_Exit(void) __attribute__((noreturn));
126 bool _le_test_CheckNeedsPlan(void);
127 void _le_test_Fail(void);
128 int _le_test_NumberTest(void);
129 int _le_test_GetNumTests(void);
130 int _le_test_GetNumFailures(void);
131 bool _le_test_SetTodo(bool todo);
132 void _le_test_Skip(int count);
133 bool _le_test_IsSkipping(void);
134 const char* _le_test_GetTag(void);
135 #define LE_TEST_OUTPUT(format, ...) LE_INFO("TAP | " format, ##__VA_ARGS__)
136 // @}
137 
138 //--------------------------------------------------------------------------------------------------
139 /**
140  * Indicate the number of tests is not known in advance.
141  */
142 //--------------------------------------------------------------------------------------------------
143 #define LE_TEST_NO_PLAN -1
144 
145 //--------------------------------------------------------------------------------------------------
146 /**
147  * Initializes a test plan. Must be called once before any tests are performed.
148  *
149  * @param testCount Number of tests expected in this test case.
150  */
151 //--------------------------------------------------------------------------------------------------
152 #define LE_TEST_PLAN(testCount) do { \
153  if (testCount >= 0) { LE_TEST_OUTPUT("1..%d", testCount); } \
154  _le_test_Init(testCount); \
155  } while(0)
156 
157 
158 //--------------------------------------------------------------------------------------------------
159 /**
160  * Initializes the testing framework. Must be called once before any tests are performed.
161  *
162  * Obselete synonym for LE_TEST_PLAN(LE_TEST_NO_PLAN)
163  */
164 //--------------------------------------------------------------------------------------------------
165 #define LE_TEST_INIT LE_TEST_PLAN(LE_TEST_NO_PLAN)
166 
167 
168 //--------------------------------------------------------------------------------------------------
169 /**
170  * Perform the test
171  */
172 //--------------------------------------------------------------------------------------------------
173 #define LE_TEST_OK(test, testName, ...) do { \
174  if (test) \
175  { \
176  LE_TEST_OUTPUT("ok %d - " testName "%s", \
177  _le_test_NumberTest(), \
178  ##__VA_ARGS__, \
179  _le_test_GetTag()); \
180  } \
181  else \
182  { \
183  LE_TEST_OUTPUT("not ok %d - " testName "%s", \
184  _le_test_NumberTest(), \
185  ##__VA_ARGS__, \
186  _le_test_GetTag()); \
187  _le_test_Fail(); \
188  } \
189  } while(0)
190 
191 //--------------------------------------------------------------------------------------------------
192 /**
193  * Performs the test.
194  *
195  * For new tests, LE_TEST_OK is preferred which gives an option to set the test name.
196  */
197 //--------------------------------------------------------------------------------------------------
198 #define LE_TEST(testResult) LE_TEST_OK((testResult), #testResult)
199 
200 
201 //--------------------------------------------------------------------------------------------------
202 /**
203  * Bail out of a test suite early.
204  *
205  * Using this instead of LE_FATAL ensures the test harness is notified the test suite is
206  * exiting abnormally.
207  */
208 //--------------------------------------------------------------------------------------------------
209 #define LE_TEST_FATAL(...) do { \
210  LE_TEST_OUTPUT("Bail out! " __VA_ARGS__); \
211  _le_test_Exit(); \
212  } while(0)
213 
214 //--------------------------------------------------------------------------------------------------
215 /**
216  * Perform a test, and bail out if the test fails.
217  *
218  * This should only be used if a test suite cannot continue if this test fails. Generally
219  * LE_TEST_OK should be used instead.
220  */
221 //--------------------------------------------------------------------------------------------------
222 #define LE_TEST_ASSERT(test, testName, ...) do { \
223  if (test) \
224  { \
225  LE_TEST_OUTPUT("ok %d - " testName "%s", \
226  _le_test_NumberTest(), \
227  ##__VA_ARGS__, \
228  _le_test_GetTag()); \
229  } \
230  else \
231  { \
232  LE_TEST_OUTPUT("not ok %d - " testName "%s", \
233  _le_test_NumberTest(), \
234  ##__VA_ARGS__, \
235  _le_test_GetTag()); \
236  _le_test_Fail(); \
237  LE_TEST_FATAL(); \
238  } \
239  } while(0)
240 
241 
242 //--------------------------------------------------------------------------------------------------
243 /**
244  * Ouptut some diagnostic information. In tests this should be used instead of LE_INFO so
245  * the output appears in the test results
246  */
247 //--------------------------------------------------------------------------------------------------
248 #define LE_TEST_INFO(...) LE_TEST_OUTPUT("# " __VA_ARGS__)
249 
250 //--------------------------------------------------------------------------------------------------
251 /**
252  * Mark a test as not yet implemented. Todo tests will still be run, but are expected to fail.
253  *
254  * Begins a block which must be terminated by LE_TEST_END_TODO()
255  */
256 //--------------------------------------------------------------------------------------------------
257 #define LE_TEST_BEGIN_TODO(cond) do { \
258  bool _le_test_OldTodo = _le_test_SetTodo(cond); \
259 
260 //--------------------------------------------------------------------------------------------------
261 /**
262  * End a block of tests which may not be implemented yet.
263  */
264 //--------------------------------------------------------------------------------------------------
265 #define LE_TEST_END_TODO() \
266  _le_test_SetTodo(_le_test_OldTodo); \
267  } while(0)
268 
269 
270 //--------------------------------------------------------------------------------------------------
271 /**
272  * Mark a test as skipped. Skipped tests will not be run, and will always pass.
273  *
274  * Begins a block which must be terminated by LE_TEST_END_SKIP()
275  */
276 //--------------------------------------------------------------------------------------------------
277 #define LE_TEST_BEGIN_SKIP(cond, count) do { \
278  if (cond) \
279  { \
280  _le_test_Skip(count); \
281  break; \
282  }
283 
284 //--------------------------------------------------------------------------------------------------
285 /**
286  * End a block of tests which may not be implemented yet.
287  */
288 //--------------------------------------------------------------------------------------------------
289 #define LE_TEST_END_SKIP() \
290  } while(0)
291 
292 
293 //--------------------------------------------------------------------------------------------------
294 /**
295  * Exits the process and returns the number of failed tests.
296  */
297 //--------------------------------------------------------------------------------------------------
298 #define LE_TEST_EXIT do { \
299  if (_le_test_CheckNeedsPlan()) \
300  { \
301  LE_TEST_OUTPUT("1..%d", _le_test_GetNumTests()); \
302  } \
303  _le_test_Exit(); \
304  } while(0)
305 
306 /// <b> *DEPRECATED* </b> old name for LE_TEST_EXIT.
307 #define LE_TEST_SUMMARY LE_TEST_EXIT
308 
309 
310 #endif // LEGATO_TEST_INCLUDE_GUARD