1 #ifndef RADARELAB_UTILS_TESTS_H
2 #define RADARELAB_UTILS_TESTS_H
73 std::string local_info;
76 : file(file), line(line), call(call)
81 : file(file), line(line), call(call), local_info(local_info.str())
85 std::string format()
const;
87 void format(std::ostream& out)
const;
90 struct TestStack :
public std::vector<TestStackFrame>
95 std::string backtrace()
const;
98 void backtrace(std::ostream& out)
const;
112 template<
typename ...Args>
113 TestFailed(
const std::exception& e, Args&&... args)
116 add_stack_info(std::forward<Args>(args)...);
119 TestFailed(
const std::string& message) : message(message) {}
121 template<
typename ...Args>
122 TestFailed(
const std::string& message, Args&&... args)
125 add_stack_info(std::forward<Args>(args)...);
128 const char* what()
const noexcept
override {
return message.c_str(); }
130 template<
typename ...Args>
131 void add_stack_info(Args&&... args) { stack.emplace_back(std::forward<Args>(args)...); }
149 #define RADARELAB_UTILS_TEST_INFO(name) \
150 radarelab::utils::tests::LocationInfo radarelab_utils_test_location_info; \
151 radarelab::utils::tests::LocationInfo& name = radarelab_utils_test_location_info
163 void assert_true(
const A& actual)
166 std::stringstream ss;
167 ss <<
"actual value " << actual <<
" is not true";
171 void assert_true(std::nullptr_t actual);
175 void assert_false(
const A& actual)
178 std::stringstream ss;
179 ss <<
"actual value " << actual <<
" is not false";
180 throw TestFailed(ss.str());
183 void assert_false(std::nullptr_t actual);
185 template<
typename LIST>
186 static inline void _format_list(std::ostream& o,
const LIST& list) {
189 for (
const auto& v: list)
201 void assert_equal(
const std::vector<T>& actual,
const std::vector<T>& expected)
203 if (actual == expected)
return;
204 std::stringstream ss;
206 _format_list(ss, actual);
207 ss <<
" is different than the expected ";
208 _format_list(ss, expected);
209 throw TestFailed(ss.str());
213 void assert_equal(
const std::vector<T>& actual,
const std::initializer_list<T>& expected)
215 if (actual == expected)
return;
216 std::stringstream ss;
218 _format_list(ss, actual);
219 ss <<
" is different than the expected ";
220 _format_list(ss, expected);
221 throw TestFailed(ss.str());
228 template<
typename A,
typename E>
229 void assert_equal(
const A& actual,
const E& expected)
231 if (actual == expected)
return;
232 std::stringstream ss;
233 ss <<
"value '" << actual <<
"' is different than the expected '" << expected <<
"'";
234 throw TestFailed(ss.str());
241 template<
typename A,
typename E>
242 void assert_not_equal(
const A& actual,
const E& expected)
244 if (actual != expected)
return;
245 std::stringstream ss;
246 ss <<
"value '" << actual <<
"' is not different than the expected '" << expected <<
"'";
247 throw TestFailed(ss.str());
251 template<
typename A,
typename E>
252 void assert_less(
const A& actual,
const E& expected)
254 if (actual < expected)
return;
255 std::stringstream ss;
256 ss <<
"value '" << actual <<
"' is not less than the expected '" << expected <<
"'";
257 throw TestFailed(ss.str());
261 template<
typename A,
typename E>
262 void assert_less_equal(
const A& actual,
const E& expected)
264 if (actual <= expected)
return;
265 std::stringstream ss;
266 ss <<
"value '" << actual <<
"' is not less than or equals to the expected '" << expected <<
"'";
267 throw TestFailed(ss.str());
271 template<
typename A,
typename E>
272 void assert_greater(
const A& actual,
const E& expected)
274 if (actual > expected)
return;
275 std::stringstream ss;
276 ss <<
"value '" << actual <<
"' is not greater than the expected '" << expected <<
"'";
277 throw TestFailed(ss.str());
281 template<
typename A,
typename E>
282 void assert_greater_equal(
const A& actual,
const E& expected)
284 if (actual >= expected)
return;
285 std::stringstream ss;
286 ss <<
"value '" << actual <<
"' is not greater than or equals to the expected '" << expected <<
"'";
287 throw TestFailed(ss.str());
291 void assert_startswith(
const std::string& actual,
const std::string& expected);
294 void assert_endswith(
const std::string& actual,
const std::string& expected);
297 void assert_contains(
const std::string& actual,
const std::string& expected);
300 void assert_not_contains(
const std::string& actual,
const std::string& expected);
308 void assert_re_matches(
const std::string& actual,
const std::string& expected);
316 void assert_not_re_matches(
const std::string& actual,
const std::string& expected);
323 Actual(
const A& actual) : _actual(actual) {}
326 void istrue()
const { assert_true(_actual); }
327 void isfalse()
const { assert_false(_actual); }
328 template<
typename E>
void operator==(
const E& expected)
const { assert_equal(_actual, expected); }
329 template<
typename E>
void operator!=(
const E& expected)
const { assert_not_equal(_actual, expected); }
330 template<
typename E>
void operator<(
const E& expected)
const {
return assert_less(_actual, expected); }
331 template<
typename E>
void operator<=(
const E& expected)
const {
return assert_less_equal(_actual, expected); }
332 template<
typename E>
void operator>(
const E& expected)
const {
return assert_greater(_actual, expected); }
333 template<
typename E>
void operator>=(
const E& expected)
const {
return assert_greater_equal(_actual, expected); }
339 ActualCString(
const char* s) : _actual(s) {}
341 void istrue()
const {
return assert_true(_actual); }
342 void isfalse()
const {
return assert_false(_actual); }
343 void operator==(
const char* expected)
const;
344 void operator==(
const std::string& expected)
const;
345 void operator!=(
const char* expected)
const;
346 void operator!=(
const std::string& 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 startswith(
const std::string& expected)
const;
352 void endswith(
const std::string& expected)
const;
353 void contains(
const std::string& expected)
const;
354 void not_contains(
const std::string& expected)
const;
355 void matches(
const std::string& re)
const;
356 void not_matches(
const std::string& re)
const;
359 struct ActualStdString :
public Actual<std::string>
361 ActualStdString(
const std::string& s) : Actual<std::string>(s) {}
363 using Actual<std::string>::operator==;
364 void operator==(
const std::vector<uint8_t>& expected)
const;
365 using Actual<std::string>::operator!=;
366 void operator!=(
const std::vector<uint8_t>& expected)
const;
367 void startswith(
const std::string& expected)
const;
368 void endswith(
const std::string& expected)
const;
369 void contains(
const std::string& expected)
const;
370 void not_contains(
const std::string& expected)
const;
371 void matches(
const std::string& re)
const;
372 void not_matches(
const std::string& re)
const;
375 struct ActualDouble :
public Actual<double>
377 using Actual::Actual;
379 void almost_equal(
double expected,
unsigned places)
const;
380 void not_almost_equal(
double expected,
unsigned places)
const;
384 inline Actual<A> actual(
const A& actual) {
return Actual<A>(actual); }
385 inline ActualCString actual(
const char* actual) {
return ActualCString(actual); }
386 inline ActualCString actual(
char* actual) {
return ActualCString(actual); }
387 inline ActualStdString actual(
const std::string& actual) {
return ActualStdString(actual); }
388 inline ActualStdString actual(
const std::vector<uint8_t>& actual) {
return ActualStdString(std::string(actual.begin(), actual.end())); }
389 inline ActualDouble actual(
double actual) {
return ActualDouble(actual); }
391 struct ActualFunction :
public Actual<std::function<void()>>
393 using Actual::Actual;
395 void throws(
const std::string& what_match)
const;
398 inline ActualFunction actual_function(std::function<
void()> actual) {
return ActualFunction(actual); }
400 struct ActualFile :
public Actual<std::string>
402 using Actual::Actual;
405 void not_exists()
const;
406 void startswith(
const std::string& data)
const;
408 void not_empty()
const;
409 void contents_equal(
const std::string& data)
const;
410 void contents_equal(
const std::vector<uint8_t>& data)
const;
411 void contents_equal(
const std::initializer_list<std::string>& lines)
const;
412 void contents_match(
const std::string& data_re)
const;
413 void contents_match(
const std::initializer_list<std::string>& lines_re)
const;
416 inline ActualFile actual_file(
const std::string& pathname) {
return ActualFile(pathname); }
425 #define wassert(...) \
428 } catch (radarelab::utils::tests::TestFailed& e) { \
429 e.add_stack_info(__FILE__, __LINE__, #__VA_ARGS__, radarelab_utils_test_location_info); \
431 } catch (std::exception& e) { \
432 throw radarelab::utils::tests::TestFailed(e, __FILE__, __LINE__, #__VA_ARGS__, radarelab_utils_test_location_info); \
436 #define wassert_true(...) wassert(actual(__VA_ARGS__).istrue())
439 #define wassert_false(...) wassert(actual(__VA_ARGS__).isfalse())
446 #define wassert_throws(exc, ...) \
449 wfail_test(#__VA_ARGS__ " did not throw " #exc); \
450 } catch (TestFailed& e) { \
454 } catch (std::exception& e) { \
455 std::string msg(#__VA_ARGS__ " did not throw " #exc " but threw "); \
456 msg += typeid(e).name(); \
468 #define wcallchecked(func) \
471 } catch (radarelab::utils::tests::TestFailed& e) { \
472 e.add_stack_info(__FILE__, __LINE__, #func, radarelab_utils_test_location_info); \
474 } catch (std::exception& e) { \
475 throw radarelab::utils::tests::TestFailed(e, __FILE__, __LINE__, #func, radarelab_utils_test_location_info); \
481 #define wfail_test(msg) wassert(throw radarelab::utils::tests::TestFailed((msg)))
484 struct TestController;
486 struct TestCaseResult;
488 struct TestMethodResult;
606 template<
typename ...Args>
616 template<
typename ...Args>
642 void test_teardown() {}
645 template<
typename Fixture,
typename... Args>
646 static inline Fixture* fixture_factory(Args... args)
654 template<
typename FIXTURE>
658 typedef FIXTURE Fixture;
660 Fixture* fixture =
nullptr;
661 std::function<Fixture*()> make_fixture;
663 template<
typename... Args>
667 make_fixture = std::bind(fixture_factory<FIXTURE, Args...>, args...);
673 fixture = make_fixture();
686 if (fixture) fixture->test_setup();
691 if (fixture) fixture->test_teardown();
699 template<
typename ...Args>
709 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.