diff --git a/README.md b/README.md
index 8cdaaa3c..cbd621f6 100644
--- a/README.md
+++ b/README.md
@@ -106,6 +106,7 @@ Sounds intriguing/interesting? Learn more at:
* Easy to use ([Minimal API](#api) - `expect, test, suite`)
* Fast to compile/execute ([Benchmarks](#benchmarks))
* Features ([Assertions](example/expect.cpp), [Suites](example/suite.cpp), [Tests](example/skip.cpp), [Sections](example/section.cpp), [Parameterized](example/parameterized.cpp), [BDD](example/BDD.cpp), [Matchers](example/matcher.cpp), [Logging](example/log.cpp), [Runners](example/cfg/runner.cpp), [Reporters](example/cfg/reporter.cpp), [...](example))
+* Integrations ([ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp/releases/tag/v.7.0.0))
> `*` - Limitations may apply
@@ -783,8 +784,8 @@ namespace cfg {
public:
template auto on(ut::events::test test) { test(); }
template auto on(ut::events::skip) {}
- template
- auto on(ut::events::assertion) -> bool { return true; }
+ template
+ auto on(ut::events::assertion) -> bool { return true; }
auto on(ut::events::fatal_assertion) {}
template auto on(ut::events::log) {}
};
@@ -812,10 +813,10 @@ namespace cfg {
auto on(ut::events::test_skip) -> void {}
auto on(ut::events::test_end) -> void {}
template auto on(ut::events::log) -> void {}
- template
- auto on(ut::events::assertion_pass) -> void {}
- template
- auto on(ut::events::assertion_fail) -> void {}
+ template
+ auto on(ut::events::assertion_pass) -> void {}
+ template
+ auto on(ut::events::assertion_fail) -> void {}
auto on(ut::events::fatal_assertion) -> void {}
auto on(ut::events::exception) -> void {}
auto on(ut::events::summary) -> void {}
@@ -1066,7 +1067,11 @@ namespace boost::ut::inline v1_1_4 {
class runner {
public:
/**
- * @example cfg = { .filter = "test.section.*", .colors = { .none = "" }, .dry__run = true };
+ * @example cfg = {
+ .filter = "test.section.*",
+ .colors = { .none = "" },
+ .dry__run = true
+ };
* @param options.filter {default: "*"} runs all tests which names matches test.section.* filter
* @param options.colors {default: {
.none = "\033[0m",
@@ -1106,12 +1111,12 @@ namespace boost::ut::inline v1_1_4 {
/**
* @example file.cpp:42: expect(42_i == 42);
- * @param assertion.location { "file.cpp", 42 }
* @param assertion.expr 42_i == 42
+ * @param assertion.location { "file.cpp", 42 }
* @return true if expr passes, false otherwise
*/
- template
- auto on(ut::events::assertion) -> bool;
+ template
+ auto on(ut::events::assertion) -> bool;
/**
* @example !expect(2_i == 1)
@@ -1147,9 +1152,10 @@ namespace boost::ut::inline v1_1_4 {
class reporter {
public:
/**
- * @example "name"_test = [] {};
+ * @example file.cpp:42: "name"_test = [] {};
* @param test_begin.type ["test", "given", "when", "then"]
* @param test_begin.name "name"
+ * @param test_begin.location { "file.cpp", 42 }
*/
auto on(ut::events::test_begin) -> void;
@@ -1183,19 +1189,19 @@ namespace boost::ut::inline v1_1_4 {
/**
* @example file.cpp:42: expect(42_i == 42);
- * @param assertion_pass.location { "file.cpp", 42 }
* @param assertion_pass.expr 42_i == 42
+ * @param assertion_pass.location { "file.cpp", 42 }
*/
- template
- auto on(ut::events::assertion_pass) -> void;
+ template
+ auto on(ut::events::assertion_pass) -> void;
/**
* @example file.cpp:42: expect(42_i != 42);
- * @param assertion_fail.location { "file.cpp", 42 }
* @param assertion_fail.expr 42_i != 42
+ * @param assertion_fail.location { "file.cpp", 42 }
*/
- template
- auto on(ut::events::assertion_fail) -> void;
+ template
+ auto on(ut::events::assertion_fail) -> void;
/**
* @example !expect(2_i == 1)
@@ -1464,6 +1470,34 @@ All tests passed (4 asserts in 3 tests)
+ Standardization?
+
+
+Personally, I believe that C++ standard could benefit from common testing primitives (`expect`, `""_test`) because:
+
+* It lowers the entry-level to the language (no need for third-party libraries)
+* It improves the education aspect (one standard way of doing it)
+* It makes the language more coherent/stable (consistent design with other features, stable API)
+* It makes the testing a first class citizen (shows that the community cares about this aspect of the language)
+* It allows to publish tests for the Standard Library (STL) in the standard way (coherency, easier to extend)
+* It allows to act as additional documentation as a way to verify whether a particular implementation is conforming (quality, self-verification)
+* It helps with establishing standard vocabulary for testing (common across STL and other projects)
+
+
+
+
+ Mocks/Stubs/Fakes?
+
+
+Consider integrating one of the following frameworks:
+
+* https://github.com/cpp-testing/GUnit/blob/master/docs/GMock.md
+* https://github.com/eranpeer/FakeIt
+* https://github.com/dascandy/hippomocks
+
+
+
+
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index f5600323..73b5b7ed 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -53,10 +53,12 @@ example(test _test)
example(tmp tmp)
example(using using)
-set(CMAKE_CXX_STANDARD 17)
-example(expect expect_cpp17)
-example(test test_cpp17)
-example(suite suite_cpp17)
-example(section section_cpp17)
-example(should should_cpp17)
-example(skip skip_cpp17)
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set(CMAKE_CXX_STANDARD 17)
+ example(expect expect_cpp17)
+ example(test test_cpp17)
+ example(suite suite_cpp17)
+ example(section section_cpp17)
+ example(should should_cpp17)
+ example(skip skip_cpp17)
+endif()
diff --git a/example/cfg/reporter.cpp b/example/cfg/reporter.cpp
index 9761c16d..e0dbb5e7 100644
--- a/example/cfg/reporter.cpp
+++ b/example/cfg/reporter.cpp
@@ -19,10 +19,10 @@ class reporter {
auto on(ut::events::test_end) -> void {}
template
auto on(ut::events::log) -> void {}
- template
- auto on(ut::events::assertion_pass) -> void {}
- template
- auto on(ut::events::assertion_fail) -> void {}
+ template
+ auto on(ut::events::assertion_pass) -> void {}
+ template
+ auto on(ut::events::assertion_fail) -> void {}
auto on(ut::events::fatal_assertion) -> void {}
auto on(ut::events::exception) -> void {}
auto on(ut::events::summary) -> void {}
diff --git a/example/cfg/runner.cpp b/example/cfg/runner.cpp
index 2a65c21c..ed8d2c77 100644
--- a/example/cfg/runner.cpp
+++ b/example/cfg/runner.cpp
@@ -18,8 +18,8 @@ class runner {
}
template
auto on(ut::events::skip) {}
- template
- auto on(ut::events::assertion) -> bool {
+ template
+ auto on(ut::events::assertion) -> bool {
return true;
}
auto on(ut::events::fatal_assertion) {}
diff --git a/include/boost/ut.hpp b/include/boost/ut.hpp
index ae5765f9..8b2c60e9 100644
--- a/include/boost/ut.hpp
+++ b/include/boost/ut.hpp
@@ -202,18 +202,18 @@ class function {
namespace reflection {
class source_location {
public:
-#if (__GNUC__ >= 9 or __clang_major__ >= 9)
[[nodiscard]] static constexpr auto current(
- const char* file = __builtin_FILE(),
- int line = __builtin_LINE()) noexcept {
+#if (__GNUC__ >= 9 or __clang_major__ >= 9)
+ const char* file = __builtin_FILE(), int line = __builtin_LINE()
+#else
+ const char* file = {}, int line = {}
+#endif
+ ) noexcept {
source_location sl{};
sl.file_ = file;
sl.line_ = line;
return sl;
}
-#else
- [[nodiscard]] static constexpr auto current() { return source_location{}; }
-#endif
[[nodiscard]] constexpr auto file_name() const noexcept { return file_; }
[[nodiscard]] constexpr auto line() const noexcept { return line_; }
@@ -861,9 +861,9 @@ template
struct test {
utility::string_view type{};
utility::string_view name{};
+ reflection::source_location location{};
TArg arg{};
Test run{};
- reflection::source_location location{};
constexpr auto operator()() { run_impl(static_cast(run), arg); }
constexpr auto operator()() const { run_impl(static_cast(run), arg); }
@@ -884,8 +884,8 @@ struct test {
}
};
template
-test(utility::string_view, utility::string_view, TArg, Test,
- reflection::source_location)
+test(utility::string_view, utility::string_view, reflection::source_location,
+ TArg, Test)
->test;
template
struct suite {
@@ -911,33 +911,33 @@ struct test_skip {
utility::string_view type{};
utility::string_view name{};
};
-template
+template
struct assertion {
- TLocation location{};
TExpr expr{};
+ reflection::source_location location{};
};
-template
-assertion(TLocation, TExpr)->assertion;
+template
+assertion(TExpr, reflection::source_location)->assertion;
#if defined(BOOST_UT_FORWARD) or defined(BOOST_UT_IMPLEMENTATION)
struct expr {
bool result;
utility::function out;
};
#endif
-template
+template
struct assertion_pass {
- TLocation location{};
TExpr expr{};
+ reflection::source_location location{};
};
-template
-assertion_pass(TLocation, TExpr)->assertion_pass;
-template
+template
+assertion_pass(TExpr)->assertion_pass;
+template
struct assertion_fail {
- TLocation location{};
TExpr expr{};
+ reflection::source_location location{};
};
-template
-assertion_fail(TLocation, TExpr)->assertion_fail;
+template
+assertion_fail(TExpr)->assertion_fail;
struct test_end {
utility::string_view type{};
utility::string_view name{};
@@ -946,7 +946,7 @@ template
struct log {
TMsg msg{};
};
-template
+template
log(TMsg)->log;
struct fatal_assertion {};
struct exception {
@@ -1145,13 +1145,13 @@ class reporter {
++tests_.except;
}
- template
- auto on(events::assertion_pass) -> void {
+ template
+ auto on(events::assertion_pass) -> void {
++asserts_.pass;
}
- template
- auto on(events::assertion_fail assertion) -> void {
+ template
+ auto on(events::assertion_fail assertion) -> void {
constexpr auto short_name = [](std::string_view name) {
return name.rfind('/') != std::string_view::npos
? name.substr(name.rfind('/') + 1)
@@ -1287,9 +1287,10 @@ class runner {
if (filter_(level_, path_)) {
if (not level_++) {
- reporter_.on(events::test_begin{test.type, test.name, test.location});
+ reporter_.on(events::test_begin{
+ .type = test.type, .name = test.name, .location = test.location});
} else {
- reporter_.on(events::test_run{test.type, test.name});
+ reporter_.on(events::test_run{.type = test.type, .name = test.name});
}
if (dry_run_) {
@@ -1316,50 +1317,52 @@ class runner {
#endif
if (not--level_) {
- reporter_.on(events::test_end{test.type, test.name});
+ reporter_.on(events::test_end{.type = test.type, .name = test.name});
}
}
}
template
auto on(events::skip test) {
- reporter_.on(events::test_skip{test.type, test.name});
+ reporter_.on(events::test_skip{.type = test.type, .name = test.name});
}
- template
- [[nodiscard]] auto on(events::assertion assertion) -> bool {
+ template
+ [[nodiscard]] auto on(events::assertion assertion) -> bool {
if (dry_run_) {
return true;
}
if (static_cast(assertion.expr)) {
- reporter_.on(events::assertion_pass{assertion.location, assertion.expr});
+ reporter_.on(events::assertion_pass{
+ .expr = assertion.expr, .location = assertion.location});
return true;
} else {
++fails_;
- reporter_.on(events::assertion_fail{assertion.location, assertion.expr});
+ reporter_.on(events::assertion_fail{
+ .expr = assertion.expr, .location = assertion.location});
return false;
}
}
#if defined(BOOST_UT_IMPLEMENTATION)
- [[nodiscard]] auto on(
- events::assertion assertion)
- -> bool {
+ [[nodiscard]] auto on(events::assertion assertion) -> bool {
if (dry_run_) {
return true;
}
if (assertion.expr.result) {
- reporter_.on(events::assertion_pass{
- assertion.location,
- static_cast(assertion.expr.out)});
+ reporter_.on(events::assertion_pass{
+ .expr =
+ static_cast(assertion.expr.out),
+ .location = assertion.location});
return true;
} else {
++fails_;
- reporter_.on(events::assertion_fail{
- assertion.location,
- static_cast(assertion.expr.out)});
+ reporter_.on(events::assertion_fail{
+ .expr =
+ static_cast(assertion.expr.out),
+ .location = assertion.location});
return false;
}
}
@@ -1425,8 +1428,7 @@ extern void on(events::suite);
extern void on(events::test);
extern void on(events::test>);
extern void on(events::skip<>);
-[[nodiscard]] extern auto on(
- events::assertion) -> bool;
+[[nodiscard]] extern auto on(events::assertion) -> bool;
extern void on(events::fatal_assertion);
extern void on(events::log);
#endif
@@ -1438,9 +1440,7 @@ void on(events::test> test) {
cfg.on(static_cast(test));
}
void on(events::skip<> skip) { cfg.on(skip); }
-[[nodiscard]] auto on(
- events::assertion assertion)
- -> bool {
+[[nodiscard]] auto on(events::assertion assertion) -> bool {
return cfg.on(static_cast(assertion));
}
void on(events::fatal_assertion assertion) { cfg.on(assertion); }
@@ -1459,17 +1459,19 @@ constexpr auto on(const TEvent& event) {
template
auto on(events::test test) -> void {
- link::on(events::test>{test.type, test.name, TArg{},
- test.run});
+ link::on(events::test, TArg>{
+ .type = test.type, .name = test.name, .arg = TArg{}, .run = test.run});
}
-template
-[[nodiscard]] auto on(events::assertion assertion) -> bool {
- return link::on(events::assertion{
- assertion.location,
- {assertion.expr, [assertion](io::ostream& os) -> io::ostream& {
- return (os << assertion.expr);
- }}});
+template
+[[nodiscard]] auto on(events::assertion assertion) -> bool {
+ return link::on(events::assertion{
+ .expr = {assertion.expr,
+ [assertion](io::ostream& os) -> io::ostream& {
+ return (os << assertion.expr);
+ }},
+ .location = assertion.location,
+ });
}
#else
template
@@ -1496,7 +1498,11 @@ struct test {
template
constexpr auto operator=(test_location test) {
- on(events::test{type, name, none{}, test.test, test.location});
+ on(events::test{.type = type,
+ .name = name,
+ .location = test.location,
+ .arg = none{},
+ .run = test.test});
return test;
}
@@ -1505,7 +1511,8 @@ struct test {
not type_traits::is_convertible_v> = 0>
constexpr auto operator=(Test test) ->
typename type_traits::identity::type {
- on(events::test{type, name, none{}, test, {}});
+ on(events::test{
+ .type = type, .name = name, .location = {}, .arg = {}, .run = test});
return test;
}
@@ -1529,7 +1536,7 @@ class test_skip {
template
constexpr auto operator=(void (*test)()) {
- on(events::skip{t_.type, t_.name, none{}});
+ on(events::skip<>{.type = t_.type, .name = t_.name, .arg = none{}});
return test;
}
@@ -1538,7 +1545,7 @@ class test_skip {
not type_traits::is_convertible_v> = 0>
constexpr auto operator=(Test test) ->
typename type_traits::identity::type {
- on(events::skip{t_.type, t_.name, none{}});
+ on(events::skip{.type = t_.type, .name = t_.name, .arg = none{}});
return test;
}
@@ -1826,7 +1833,8 @@ template (events::test{"test", name, arg, f, {}});
+ detail::on(events::test{
+ .type = "test", .name = name, .location = {}, .arg = arg, .run = f});
}
};
}
@@ -1838,7 +1846,12 @@ template <
return [f, t](auto name) {
apply(
[f, name](const auto&... args) {
- (detail::on(events::test{"test", name, args, f, {}}), ...);
+ (detail::on(events::test{.type = "test",
+ .name = name,
+ .location = {},
+ .arg = args,
+ .run = f}),
+ ...);
},
t);
};
@@ -1851,7 +1864,8 @@ template {detail::on(events::assertion{sl, expr})};
+ return detail::expect_{detail::on(
+ events::assertion{.expr = expr, .location = sl})};
}
#if defined(__cpp_nontype_template_parameter_class)
@@ -1913,7 +1927,8 @@ struct suite {
template
constexpr /*explicit(false)*/ suite(TSuite suite) {
static_assert(1 == sizeof(suite));
- detail::on(events::suite{+suite});
+ detail::on(
+ events::suite{.run = +suite});
}
};
diff --git a/test/ut/ut.cpp b/test/ut/ut.cpp
index 94a15919..55756ea9 100644
--- a/test/ut/ut.cpp
+++ b/test/ut/ut.cpp
@@ -50,7 +50,7 @@ struct fake_cfg {
run_calls.push_back({test.type, test.name, test.arg});
try {
test();
- } catch (boost::ut::events::exception exception) {
+ } catch (const ut::events::exception& exception) {
exception_calls.push_back(exception.what());
} catch (const std::exception& exception) {
exception_calls.push_back(exception.what());
@@ -61,12 +61,14 @@ struct fake_cfg {
}
template
auto on(ut::events::skip test) {
- skip_calls.push_back({test.type, test.name, test.arg});
+ skip_calls.push_back(
+ {.type = test.type, .name = test.name, .arg = test.arg});
}
- template
- auto on(ut::events::assertion assertion) -> bool {
- assertion_calls.push_back(
- {assertion.location, to_string(assertion.expr), assertion.expr});
+ template
+ auto on(ut::events::assertion assertion) -> bool {
+ assertion_calls.push_back({.location = assertion.location,
+ .str = to_string(assertion.expr),
+ .result = assertion.expr});
return assertion.expr;
}
auto on(ut::events::fatal_assertion) { ++fatal_assertion_calls; }
@@ -322,12 +324,6 @@ int main() {
};
{
- struct fake_source_location {
- [[nodiscard]] constexpr auto file_name() const noexcept {
- return "file/name";
- }
- [[nodiscard]] constexpr auto line() const noexcept { return 42; }
- };
std::stringstream out{};
std::stringstream err{};
auto old_cout = std::cout.rdbuf(out.rdbuf());
@@ -337,8 +333,12 @@ int main() {
reporter.on(events::test_begin{});
reporter.on(events::test_run{});
- reporter.on(events::assertion_pass{fake_source_location{}, true});
- reporter.on(events::assertion_fail{fake_source_location{}, false});
+ reporter.on(events::assertion_pass{
+ .expr = true,
+ .location = reflection::source_location::current("file/name.cpp", 42)});
+ reporter.on(events::assertion_fail{
+ .expr = false,
+ .location = reflection::source_location::current("file/name.cpp", 42)});
reporter.on(events::fatal_assertion{});
reporter.on(events::test_end{});
@@ -370,166 +370,187 @@ int main() {
auto& reporter = run.reporter_;
run.run_ = true;
- run.on(events::test{"test", "run", none{}, [] {}, {}});
+ const auto test_empty = [] {};
+ run.on(events::test{.type = "test",
+ .name = "run",
+ .location = {},
+ .arg = none{},
+ .run = test_empty});
test_assert(1 == reporter.tests_.pass);
test_assert(0 == reporter.tests_.fail);
test_assert(0 == reporter.tests_.skip);
- run.on(events::skip{"test", "skip", none{}});
+ run.on(events::skip<>{.type = "test", .name = "skip", .arg = none{}});
test_assert(1 == reporter.tests_.pass);
test_assert(0 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
- run = {"unknown"};
- run.on(events::test{"test", "filter", none{}, [] {}, {}});
+ run = {.filter = "unknown"};
+ run.on(events::test{.type = "test",
+ .name = "filter",
+ .location = {},
+ .arg = none{},
+ .run = test_empty});
test_assert(1 == reporter.tests_.pass);
test_assert(0 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
run = options{};
- run = {"filter"};
- run.on(events::test{"test", "filter", none{}, [] {}, {}});
+ run = {.filter = "filter"};
+ run.on(events::test{.type = "test",
+ .name = "filter",
+ .location = {},
+ .arg = none{},
+ .run = test_empty});
test_assert(2 == reporter.tests_.pass);
test_assert(0 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
run = options{};
- run.on(events::test{
- "test",
- "pass",
- none{},
- [&run] {
- void(run.on(events::assertion{reflection::source_location{}, true}));
- },
- {}});
+ const auto test_assertion_true = [&run] {
+ void(run.on(events::assertion{.expr = true, .location = {}}));
+ };
+ run.on(events::test{
+ .type = "test",
+ .name = "pass",
+ .location = {},
+ .arg = none{},
+ .run = test_assertion_true});
test_assert(3 == reporter.tests_.pass);
test_assert(0 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
- run.on(events::test{
- "test",
- "fail",
- none{},
- [&run] {
- void(run.on(events::assertion{reflection::source_location{}, false}));
- },
- {}});
+ const auto test_assertion_false = [&run] {
+ void(run.on(events::assertion{.expr = false, .location = {}}));
+ };
+ run.on(events::test{
+ .type = "test",
+ .name = "fail",
+ .location = {},
+ .arg = none{},
+ .run = test_assertion_false});
test_assert(3 == reporter.tests_.pass);
test_assert(1 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
- run.on(events::test{"test", "exception", none{}, [] { throw 42; }, {}});
+ const auto test_throw = [] { throw 42; };
+ run.on(events::test{.type = "test",
+ .name = "exception",
+ .location = {},
+ .arg = none{},
+ .run = test_throw});
test_assert(3 == reporter.tests_.pass);
test_assert(2 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
test_assert(1 == reporter.tests_.except);
- run.on(events::test{"test", "exception", none{},
- [] { throw std::runtime_error("exception"); }, {}});
+ const auto test_throw_runtime_error = [] {
+ throw std::runtime_error("exception");
+ };
+ run.on(events::test{
+ .type = "test",
+ .name = "exception",
+ .location = {},
+ .arg = none{},
+ .run = test_throw_runtime_error});
test_assert(3 == reporter.tests_.pass);
test_assert(3 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
test_assert(2 == reporter.tests_.except);
- run.on(events::test{
- "test",
- "section",
- none{},
- [&run] {
- run.on(events::test{"test", "sub-section", none{}, [] {}, {}});
- },
- {}});
+ const auto test_sub_section = [&run, test_empty] {
+ run.on(events::test{.type = "test",
+ .name = "sub-section",
+ .location = {},
+ .arg = none{},
+ .run = test_empty});
+ };
+ run.on(events::test{.type = "test",
+ .name = "section",
+ .location = {},
+ .arg = none{},
+ .run = test_sub_section});
test_assert(4 == reporter.tests_.pass);
test_assert(3 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
- run = {"section"};
- run.on(events::test{
- "test",
- "section",
- none{},
- [&run] {
- run.on(events::test{"test", "sub-section-1", none{}, [] {}, {}});
- run.on(events::test{
- "test", "sub-section-2", none{}, [] { throw 0; }, {}});
- },
- {}});
+ const auto test_sub_sections = [&run, test_empty, test_throw] {
+ run.on(events::test{.type = "test",
+ .name = "sub-section-1",
+ .location = {},
+ .arg = none{},
+ .run = test_empty});
+ run.on(events::test{.type = "test",
+ .name = "sub-section-2",
+ .location = {},
+ .arg = none{},
+ .run = test_throw});
+ };
+ run = {.filter = "section"};
+ run.on(events::test{.type = "test",
+ .name = "section",
+ .location = {},
+ .arg = none{},
+ .run = test_sub_sections});
test_assert(4 == reporter.tests_.pass);
test_assert(4 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
run = options{};
- run = {"section.sub-section-1"};
- run.on(events::test{
- "test",
- "section",
- none{},
- [&run] {
- run.on(events::test{"test", "sub-section-1", none{}, [] {}, {}});
- run.on(events::test{
- "test", "sub-section-2", none{}, [] { throw 0; }, {}});
- },
- {}});
+ run = {.filter = "section.sub-section-1"};
+ run.on(events::test{.type = "test",
+ .name = "section",
+ .location = {},
+ .arg = none{},
+ .run = test_sub_sections});
test_assert(5 == reporter.tests_.pass);
test_assert(4 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
run = options{};
- run = {"section.sub-section-2"};
- run.on(events::test{
- "test",
- "section",
- none{},
- [&run] {
- run.on(events::test{"test", "sub-section-1", none{}, [] {}, {}});
- run.on(events::test{
- "test", "sub-section-2", none{}, [] { throw 0; }, {}});
- },
- {}});
+ run = {.filter = "section.sub-section-2"};
+ run.on(events::test{.type = "test",
+ .name = "section",
+ .location = {},
+ .arg = none{},
+ .run = test_sub_sections});
test_assert(5 == reporter.tests_.pass);
test_assert(5 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
run = options{};
- run = {"section.sub-section-*"};
- run.on(events::test{
- "test",
- "section",
- none{},
- [&run] {
- run.on(events::test{"test", "sub-section-1", none{}, [] {}, {}});
- run.on(events::test{
- "test", "sub-section-2", none{}, [] { throw 0; }, {}});
- },
- {}});
+ run = {.filter = "section.sub-section-*"};
+ run.on(events::test{.type = "test",
+ .name = "section",
+ .location = {},
+ .arg = none{},
+ .run = test_sub_sections});
test_assert(5 == reporter.tests_.pass);
test_assert(6 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
run = options{};
- run.on(events::test{
- "test",
- "fatal",
- none{},
- [&run] {
- void(run.on(events::assertion{reflection::source_location{}, false}));
- run.on(events::fatal_assertion{});
- void(run.on(events::assertion{reflection::source_location{}, true}));
- },
- {}});
+ const auto test_assertions = [&run] {
+ void(run.on(events::assertion{.expr = false, .location = {}}));
+ run.on(events::fatal_assertion{});
+ void(run.on(events::assertion{.expr = true, .location = {}}));
+ };
+ run.on(events::test{.type = "test",
+ .name = "fatal",
+ .location = {},
+ .arg = none{},
+ .run = test_assertions});
test_assert(5 == reporter.tests_.pass);
test_assert(7 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
- run.on(events::test{
- "test",
- "normal",
- none{},
- [&run] {
- void(run.on(events::assertion{reflection::source_location{}, true}));
- },
- {}});
+ run.on(events::test{
+ .type = "test",
+ .name = "normal",
+ .location = {},
+ .arg = none{},
+ .run = test_assertion_true});
test_assert(6 == reporter.tests_.pass);
test_assert(7 == reporter.tests_.fail);
test_assert(1 == reporter.tests_.skip);
@@ -1009,7 +1030,7 @@ int main() {
};
"events::exception throw"_test = [] {
- throw events::exception{"events::exception message"};
+ throw events::exception{.msg = "events::exception message"};
};
"generic throw"_test = [] { throw 0; };