diff --git a/README.md b/README.md index 4922563e..67e1e648 100644 --- a/README.md +++ b/README.md @@ -339,21 +339,23 @@ Completed ===================================================================== int main() { using namespace boost::ut; - expect((1 == 2_i) >> fatal); // fatal assertion - expect(1_i == 2); // not executed + expect(fatal(1 == 2_i)); // fatal assertion + expect(1_i == 2); // not executed } ``` ``` UT starts ===================================================================== FAILED in: ...\example.cpp:6 - test condition: [1 == 2] +=> terminated for the fatal issue =============================================================================== Suite global tests: 0 | 0 failed asserts: 1 | 0 passed | 1 failed +Completed ===================================================================== ``` -> https://godbolt.org/z/6Mvex8TaT +> https://godbolt.org/z/xohGacdWc > But my expression is more complex than just simple comparisons. > Not a problem, logic operators are also supported in the `expect` 👍. @@ -425,6 +427,7 @@ int main() { UT starts ===================================================================== Running test "lazy log"... FAILED in: ...\example.cpp:8 - test condition: [false] lazy evaluated +=> terminated for the fatal issue =============================================================================== Suite global tests: 1 | 1 failed @@ -550,7 +553,7 @@ int main() { "vector"_test = [] { given("I have a vector") = [] { std::vector v(5); - expect((5_ul == std::size(v)) >> fatal); + expect(fatal(5_ul == std::size(v))); when("I resize bigger") = [=] { mut(v).resize(10); @@ -570,7 +573,7 @@ Suite 'global': all tests passed (2 asserts in 1 tests) Completed ===================================================================== ``` -> https://godbolt.org/z/4YY7KzG64 +> https://godbolt.org/z/e73b7WTGE > On top of that, `feature/scenario` aliases can be leveraged. @@ -586,7 +589,7 @@ int main() { scenario("size") = [] { given("I have a vector") = [] { std::vector v(5); - expect((5_ul == std::size(v)) >> fatal); + expect(fatal(5_ul == std::size(v))); when("I resize bigger") = [=] { mut(v).resize(10); @@ -607,7 +610,7 @@ Suite 'global': all tests passed (2 asserts in 1 tests) Completed ===================================================================== ``` -> https://godbolt.org/z/qxdrKxxqn +> https://godbolt.org/z/nPcGqcn8f > Can I use `Gherkin`? > Yeah, let's rewrite the example using `Gherkin` specification @@ -623,7 +626,7 @@ int main() { steps.scenario("*") = [&] { steps.given("I have a vector") = [&] { std::vector v(5); - expect((5_ul == std::size(v)) >> fatal); + expect(fatal(5_ul == std::size(v))); steps.when("I resize bigger") = [&] { v.resize(10); }; steps.then("The size should increase") = [&] { expect(10_ul == std::size(v)); }; }; @@ -648,7 +651,7 @@ Suite 'global': all tests passed (2 asserts in 1 tests) Completed ===================================================================== ``` -> https://godbolt.org/z/nxW6dsPvj +> https://godbolt.org/z/K69ha16rE > Nice, is `Spec` notation supported as well? @@ -662,7 +665,7 @@ int main() { describe("vector") = [] { std::vector v(5); - expect((5_ul == std::size(v)) >> fatal); + expect(fatal(5_ul == std::size(v))); it("should resize bigger") = [v] { mut(v).resize(10); @@ -678,7 +681,7 @@ Suite 'global': all tests passed (2 asserts in 1 tests) Completed ===================================================================== ``` -> https://godbolt.org/z/Y76sKKs4e +> https://godbolt.org/z/5vbTs77ff > That's great, but how can call the same tests with different arguments/types to be DRY (Don't Repeat Yourself)? > Parameterized tests to the rescue! @@ -935,14 +938,14 @@ int main() { "[vector]"_test = [] { std::vector v(5); - expect((5_ul == std::size(v)) >> fatal); + expect(fatal(5_ul == std::size(v))); should("resize bigger") = [=]() mutable { // or "resize bigger"_test v.resize(10); expect(10_ul == std::size(v)); }; - expect((5_ul == std::size(v)) >> fatal); + expect(fatal(5_ul == std::size(v))); should("resize smaller") = [=]() mutable { // or "resize smaller"_test v.resize(0); @@ -958,7 +961,7 @@ Suite 'global': all tests passed (4 asserts in 1 tests) Completed ===================================================================== ``` -> https://godbolt.org/z/rez4qMhxE +> https://godbolt.org/z/EjTEqMvzv

diff --git a/example/fatal.cpp b/example/fatal.cpp index 2b6b2dea..de0e1375 100644 --- a/example/fatal.cpp +++ b/example/fatal.cpp @@ -19,7 +19,7 @@ int main() { using boost::ut::expect; std::optional o{42}; - expect(fatal(o.has_value())) << "fatal assertion"; + expect(fatal(o.has_value())); expect(*o == 42_i); }; @@ -28,7 +28,7 @@ int main() { using boost::ut::expect; std::optional o{42}; - expect(fatal(o.has_value())) << "fatal assertion"; + expect(o.has_value()) << "log messages...." << fatal; expect(*o == 42_i); }; @@ -38,21 +38,20 @@ int main() { using boost::ut::that; std::optional o{42}; - expect(fatal(that % o.has_value()) and that % *o == 42) - << "fatal assertion"; + expect(fatal(that % o.has_value()) and that % *o == 42); }; "fatal terse"_test = [] { using namespace boost::ut::operators::terse; std::optional o{42}; - (o.has_value() >> fatal and *o == 42_i) << "fatal assertion"; + (fatal(o.has_value()) and *o == 42_i); }; using namespace boost::ut::operators; using boost::ut::expect; std::vector v{1u}; - expect(fatal(std::size(v) == 1_ul)) << "fatal assertion"; + expect(fatal(std::size(v) == 1_ul)); expect(v[0] == 1_u); } diff --git a/include/boost/ut.hpp b/include/boost/ut.hpp index 4785b405..5c020635 100644 --- a/include/boost/ut.hpp +++ b/include/boost/ut.hpp @@ -1653,8 +1653,10 @@ class reporter_junit { ? FAILED : (current_node_->skipped ? SKIPPED : PASSED); auto parent = current_node_->parent; if (parent != nullptr) { - parent->n_tests += current_node_->n_tests; - parent->fail_tests += current_node_->fail_tests; + parent->n_tests += 1LU; + if ((current_node_->fails > 0 || current_node_->fail_tests > 0)) { + parent->fail_tests++; + } parent->assertions += current_node_->assertions; parent->skipped += current_node_->skipped; parent->fails += current_node_->fails; @@ -1735,10 +1737,6 @@ class reporter_junit { } } reset_printer(); - current_node_->n_tests = 1LU; - if (current_node_->fails > 0 || current_node_->fail_tests > 0) { - current_node_->fail_tests = 1LU; - } count_result(); } @@ -1825,7 +1823,18 @@ class reporter_junit { } } - auto on(const events::fatal_assertion&) -> void {} + auto on(const events::fatal_assertion&) -> void { + TPrinter ss{}; + ss << ss_out_.str() << "\n=> " << color_.fail << "terminated for the fatal issue" << color_.none; + current_node_->report_string += ss.str(); + reset_printer(); + if (report_type_ == CONSOLE) { + lcout_ << ss.str(); + } + while (current_node_->parent != nullptr) { + count_result(); + } + } auto on(events::summary) -> void { std::cout.flush(); @@ -2102,10 +2111,7 @@ class runner { #if defined(__cpp_exceptions) try { -#endif test(); -#if defined(__cpp_exceptions) - } catch (const events::fatal_assertion&) { } catch (const std::exception& exception) { ++fails_; reporter_.on(events::exception{exception.what()}); @@ -2154,19 +2160,7 @@ class runner { auto on(events::fatal_assertion fatal_assertion) { reporter_.on(fatal_assertion); - -#if defined(__cpp_exceptions) - if (not level_) { - report_summary(); - } - throw fatal_assertion; -#else - if (level_) { - reporter_.on(events::test_end{}); - } - report_summary(); - std::abort(); -#endif + std::exit(-1); } template diff --git a/test/ut/ut.cpp b/test/ut/ut.cpp index a1546630..4111ef66 100644 --- a/test/ut/ut.cpp +++ b/test/ut/ut.cpp @@ -818,15 +818,6 @@ int main() { // NOLINT(readability-function-size) test_assert(1 == reporter.tests_.skip); run = options{}; - run.on(events::test{.type = "test", - .name = "fatal", - .location = {}, - .arg = none{}, - .run = test_assertions{run}}); - test_assert(5 == reporter.tests_.pass); - test_assert(7 == reporter.tests_.fail); - test_assert(1 == reporter.tests_.skip); - run.on( events::test{.type = "test", .name = "normal", @@ -834,8 +825,17 @@ int main() { // NOLINT(readability-function-size) .arg = none{}, .run = test_assertion_true{run}}); test_assert(6 == reporter.tests_.pass); - test_assert(7 == reporter.tests_.fail); + test_assert(6 == reporter.tests_.fail); test_assert(1 == reporter.tests_.skip); + + /*run.on(events::test{.type = "test", + .name = "fatal", + .location = {}, + .arg = none{}, + .run = test_assertions{run}}); + test_assert(6 == reporter.tests_.pass); + test_assert(7 == reporter.tests_.fail); + test_assert(1 == reporter.tests_.skip);*/ reporter = printer{}; }