1 #ifndef RADARELAB_UTILS_TESTS_H
2 #define RADARELAB_UTILS_TESTS_H
74 std::string local_info;
77 : file(file), line(line), call(call)
82 : file(file), line(line), call(call), local_info(local_info.str())
86 std::string format()
const;
88 void format(std::ostream& out)
const;
91 struct TestStack :
public std::vector<TestStackFrame>
96 std::string backtrace()
const;
99 void backtrace(std::ostream& out)
const;
113 template<
typename ...Args>
114 TestFailed(
const std::exception& e, Args&&... args)
117 add_stack_info(std::forward<Args>(args)...);
120 TestFailed(
const std::string& message) : message(message) {}
122 template<
typename ...Args>
123 TestFailed(
const std::string& message, Args&&... args)
126 add_stack_info(std::forward<Args>(args)...);
129 const char* what()
const noexcept
override {
return message.c_str(); }
131 template<
typename ...Args>
132 void add_stack_info(Args&&... args) { stack.emplace_back(std::forward<Args>(args)...); }
150 #define RADARELAB_UTILS_TEST_INFO(name) \
151 radarelab::utils::tests::LocationInfo radarelab_utils_test_location_info; \
152 radarelab::utils::tests::LocationInfo& name = radarelab_utils_test_location_info
164 void assert_true(
const A& actual)
167 std::stringstream ss;
168 ss <<
"actual value " << actual <<
" is not true";
172 void assert_true(std::nullptr_t actual);
176 void assert_false(
const A& actual)
179 std::stringstream ss;
180 ss <<
"actual value " << actual <<
" is not false";
181 throw TestFailed(ss.str());
184 void assert_false(std::nullptr_t actual);
186 template<
typename LIST>
187 static inline void _format_list(std::ostream& o,
const LIST& list) {
190 for (
const auto& v: list)
202 void assert_equal(
const std::vector<T>& actual,
const std::vector<T>& expected)
204 if (actual == expected)
return;
205 std::stringstream ss;
207 _format_list(ss, actual);
208 ss <<
" is different than the expected ";
209 _format_list(ss, expected);
210 throw TestFailed(ss.str());
214 void assert_equal(
const std::vector<T>& actual,
const std::initializer_list<T>& expected)
216 if (actual == expected)
return;
217 std::stringstream ss;
219 _format_list(ss, actual);
220 ss <<
" is different than the expected ";
221 _format_list(ss, expected);
222 throw TestFailed(ss.str());
229 template<
typename A,
typename E>
230 void assert_equal(
const A& actual,
const E& expected)
232 if (actual == expected)
return;
233 std::stringstream ss;
234 ss <<
"value '" << actual <<
"' is different than the expected '" << expected <<
"'";
235 throw TestFailed(ss.str());
242 template<
typename A,
typename E>
243 void assert_not_equal(
const A& actual,
const E& expected)
245 if (actual != expected)
return;
246 std::stringstream ss;
247 ss <<
"value '" << actual <<
"' is not different than the expected '" << expected <<
"'";
248 throw TestFailed(ss.str());
252 template<
typename A,
typename E>
253 void assert_less(
const A& actual,
const E& expected)
255 if (actual < expected)
return;
256 std::stringstream ss;
257 ss <<
"value '" << actual <<
"' is not less than the expected '" << expected <<
"'";
258 throw TestFailed(ss.str());
262 template<
typename A,
typename E>
263 void assert_less_equal(
const A& actual,
const E& expected)
265 if (actual <= expected)
return;
266 std::stringstream ss;
267 ss <<
"value '" << actual <<
"' is not less than or equals to the expected '" << expected <<
"'";
268 throw TestFailed(ss.str());
272 template<
typename A,
typename E>
273 void assert_greater(
const A& actual,
const E& expected)
275 if (actual > expected)
return;
276 std::stringstream ss;
277 ss <<
"value '" << actual <<
"' is not greater than the expected '" << expected <<
"'";
278 throw TestFailed(ss.str());
282 template<
typename A,
typename E>
283 void assert_greater_equal(
const A& actual,
const E& expected)
285 if (actual >= expected)
return;
286 std::stringstream ss;
287 ss <<
"value '" << actual <<
"' is not greater than or equals to the expected '" << expected <<
"'";
288 throw TestFailed(ss.str());
292 void assert_startswith(
const std::string& actual,
const std::string& expected);
295 void assert_endswith(
const std::string& actual,
const std::string& expected);
298 void assert_contains(
const std::string& actual,
const std::string& expected);
301 void assert_not_contains(
const std::string& actual,
const std::string& expected);
309 void assert_re_matches(
const std::string& actual,
const std::string& expected);
317 void assert_not_re_matches(
const std::string& actual,
const std::string& expected);
324 Actual(
const A& actual) : _actual(actual) {}
327 void istrue()
const { assert_true(_actual); }
328 void isfalse()
const { assert_false(_actual); }
329 template<
typename E>
void operator==(
const E& expected)
const { assert_equal(_actual, expected); }
330 template<
typename E>
void operator!=(
const E& expected)
const { assert_not_equal(_actual, expected); }
331 template<
typename E>
void operator<(
const E& expected)
const {
return assert_less(_actual, expected); }
332 template<
typename E>
void operator<=(
const E& expected)
const {
return assert_less_equal(_actual, expected); }
333 template<
typename E>
void operator>(
const E& expected)
const {
return assert_greater(_actual, expected); }
334 template<
typename E>
void operator>=(
const E& expected)
const {
return assert_greater_equal(_actual, expected); }
340 ActualCString(
const char* s) : _actual(s) {}
342 void istrue()
const {
return assert_true(_actual); }
343 void isfalse()
const {
return assert_false(_actual); }
344 void operator==(
const char* expected)
const;
345 void operator==(
const std::string& expected)
const;
346 void operator!=(
const char* expected)
const;
347 void operator!=(
const std::string& expected)
const;
348 void operator<(
const std::string& expected)
const;
349 void operator<=(
const std::string& expected)
const;
350 void operator>(
const std::string& expected)
const;
351 void operator>=(
const std::string& expected)
const;
352 void startswith(
const std::string& expected)
const;
353 void endswith(
const std::string& expected)
const;
354 void contains(
const std::string& expected)
const;
355 void not_contains(
const std::string& expected)
const;
356 void matches(
const std::string& re)
const;
357 void not_matches(
const std::string& re)
const;
360 struct ActualStdString :
public Actual<std::string>
362 ActualStdString(
const std::string& s) : Actual<std::string>(s) {}
364 using Actual<std::string>::operator==;
365 void operator==(
const std::vector<uint8_t>& expected)
const;
366 using Actual<std::string>::operator!=;
367 void operator!=(
const std::vector<uint8_t>& expected)
const;
368 void startswith(
const std::string& expected)
const;
369 void endswith(
const std::string& expected)
const;
370 void contains(
const std::string& expected)
const;
371 void not_contains(
const std::string& expected)
const;
372 void matches(
const std::string& re)
const;
373 void not_matches(
const std::string& re)
const;
376 struct ActualDouble :
public Actual<double>
378 using Actual::Actual;
380 void almost_equal(
double expected,
unsigned places)
const;
381 void not_almost_equal(
double expected,
unsigned places)
const;
385 inline Actual<A> actual(
const A& actual) {
return Actual<A>(actual); }
386 inline ActualCString actual(
const char* actual) {
return ActualCString(actual); }
387 inline ActualCString actual(
char* actual) {
return ActualCString(actual); }
388 inline ActualStdString actual(
const std::string& actual) {
return ActualStdString(actual); }
389 inline ActualStdString actual(
const std::vector<uint8_t>& actual) {
return ActualStdString(std::string(actual.begin(), actual.end())); }
390 inline ActualDouble actual(
double actual) {
return ActualDouble(actual); }
392 struct ActualFunction :
public Actual<std::function<void()>>
394 using Actual::Actual;
396 void throws(
const std::string& what_match)
const;
399 inline ActualFunction actual_function(std::function<
void()> actual) {
return ActualFunction(actual); }
401 struct ActualFile :
public Actual<std::string>
403 using Actual::Actual;
406 void not_exists()
const;
407 void startswith(
const std::string& data)
const;
409 void not_empty()
const;
410 void contents_equal(
const std::string& data)
const;
411 void contents_equal(
const std::vector<uint8_t>& data)
const;
412 void contents_equal(
const std::initializer_list<std::string>& lines)
const;
413 void contents_match(
const std::string& data_re)
const;
414 void contents_match(
const std::initializer_list<std::string>& lines_re)
const;
417 inline ActualFile actual_file(
const std::string& pathname) {
return ActualFile(pathname); }
426 #define wassert(...) \
429 } catch (radarelab::utils::tests::TestFailed& e) { \
430 e.add_stack_info(__FILE__, __LINE__, #__VA_ARGS__, radarelab_utils_test_location_info); \
432 } catch (std::exception& e) { \
433 throw radarelab::utils::tests::TestFailed(e, __FILE__, __LINE__, #__VA_ARGS__, radarelab_utils_test_location_info); \
437 #define wassert_true(...) wassert(actual(__VA_ARGS__).istrue())
440 #define wassert_false(...) wassert(actual(__VA_ARGS__).isfalse())
447 #define wassert_throws(exc, ...) \
450 wfail_test(#__VA_ARGS__ " did not throw " #exc); \
451 } catch (TestFailed& e) { \
455 } catch (std::exception& e) { \
456 std::string msg(#__VA_ARGS__ " did not throw " #exc " but threw "); \
457 msg += typeid(e).name(); \
469 #define wcallchecked(func) \
472 } catch (radarelab::utils::tests::TestFailed& e) { \
473 e.add_stack_info(__FILE__, __LINE__, #func, radarelab_utils_test_location_info); \
475 } catch (std::exception& e) { \
476 throw radarelab::utils::tests::TestFailed(e, __FILE__, __LINE__, #func, radarelab_utils_test_location_info); \
482 #define wfail_test(msg) wassert(throw radarelab::utils::tests::TestFailed((msg)))
485 struct TestController;
487 struct TestCaseResult;
489 struct TestMethodResult;
607 template<
typename ...Args>
617 template<
typename ...Args>
643 void test_teardown() {}
646 template<
typename Fixture,
typename... Args>
647 static inline Fixture* fixture_factory(Args... args)
655 template<
typename FIXTURE>
659 typedef FIXTURE Fixture;
661 Fixture* fixture =
nullptr;
662 std::function<Fixture*()> make_fixture;
664 template<
typename... Args>
668 make_fixture = std::bind(fixture_factory<FIXTURE, Args...>, args...);
674 fixture = make_fixture();
687 if (fixture) fixture->test_setup();
692 if (fixture) fixture->test_teardown();
700 template<
typename ...Args>
710 template<
typename ...Args>
void method_teardown(TestMethodResult &mr) override
Clean up after the test method is run.
void teardown() override
Clean up after the test case is run.
void setup() override
Set up the test case before it is run.
TestMethod & add_method(const std::string &name, const std::string &doc, std::function< void(FIXTURE &)> test_function)
Register a new test method that takes a reference to the fixture as argument, including documentation...
void method_setup(TestMethodResult &mr) override
Set up before the test method is run.
TestMethod & add_method(const std::string &name, std::function< void(FIXTURE &)> test_function)
Register a new test method that takes a reference to the fixture as argument.
Test case that includes a fixture.
Base class for test fixtures.
std::ostream & operator()()
Clear the current information and return the output stream to which new information can be sent.
Add information to the test backtrace for the tests run in the current scope.
Result of running a whole test case.
std::vector< TestMethod > methods
All registered test methods.
bool tests_registered
Set to true the first time register_tests_once is run.
virtual void teardown()
Clean up after the test case is run.
virtual void setup()
Set up the test case before it is run.
virtual void register_tests()=0
This will be called before running the test case, to populate it with its test methods.
void register_tests_once()
Idempotent wrapper for register_tests()
virtual void method_setup(TestMethodResult &)
Set up before the test method is run.
TestMethod & add_method(const std::string &name)
Register a new test method, with the actual test function to be added later.
virtual TestCaseResult run_tests(TestController &controller)
Call setup(), run all the tests that have been registered, then call teardown().
std::string name
Name of the test case.
TestMethod & add_method(const std::string &name, std::function< void()> test_function)
Register a new test method.
virtual void method_teardown(TestMethodResult &)
Clean up after the test method is run.
virtual TestMethodResult run_test(TestController &controller, TestMethod &method)
Run a test method.
TestMethod & add_method(const std::string &name, const std::string &doc, std::function< void()> test_function)
Register a new test method, including documentation.
Test case collecting several test methods, and self-registering with the singleton instance of TestRe...
Abstract interface for the objects that supervise test execution.
Exception thrown when a test assertion fails, normally by Location::fail_test.
Result of running a test method.
std::string doc
Documentation attached to this test method.
std::string name
Name of the test method.
std::function< void()> test_function
Main body of the test method.
Exception thrown when a test or a test case needs to be skipped.
Information about one stack frame in the test execution stack.