- "failure"_test = [] {
- expect(aborts([] { assert(false); }));
- };
-};
+boost::ut::suite errors = [] {
+ using namespace boost::ut;
-int main() { }
+ "exception"_test = [] {
+ expect(throws([] { throw 0; })) << "throws any exception";
+ };
+
+ "failure"_test = [] {
+ expect(aborts([] { assert(false); })); // for Unix-like operating systems
+ };
+ };
+
+int main() {}
```
```
-All tests passed (2 asserts in 2 tests)
+UT starts =====================================================================
+Suite 'unnamed suite': all tests passed (2 asserts in 2 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/_ccGwZ
+> https://godbolt.org/z/6TxWETerc
---
@@ -736,14 +861,17 @@ expect(sum() == 1_i or 2_i == sum()) << "sum?";
```
```
-assertions.cpp:53:FAILED [1 == 2] should fail
-assertions.cpp:54:FAILED [(0 == 1 or 2 == 0)] sum?
+UT starts =====================================================================
+FAILED in: ...\example.cpp:46 - test condition: [1 == 2] should fail
+FAILED in: ...\example.cpp:47 - test condition: [(0 == 1 or 2 == 0)] sum?
===============================================================================
-tests: 0 | 0 failed
+Suite global
+tests: 0 | 0 failed
asserts: 20 | 18 passed | 2 failed
+Completed =====================================================================
```
-> https://godbolt.org/z/E1c7G5
+> https://godbolt.org/z/o5GqKvG87
@@ -755,35 +883,39 @@ asserts: 20 | 18 passed | 2 failed
```cpp
-"run UDL"_test = [] {
- expect(42_i == 42);
-};
-
-skip / "don't run UDL"_test = [] {
- expect(42_i == 43) << "should not fire!";
-};
-```
+#include
-```
-All tests passed (1 asserts in 1 tests)
-1 tests skipped
-```
+int main() {
+ using namespace boost::ut;
+ // use ""_test
+ "run UDL"_test = [] {
+ expect(42_i == 42);
+ };
-```cpp
-test("run function") = [] {
- expect(42_i == 42);
-};
+ skip / "don't run UDL"_test = [] {
+ expect(42_i == 43) << "should not fire!";
+ };
+ // test()
+ test("run function") = [] {
+ expect(42_i == 42);
+ };
-skip / test("don't run function") = [] {
- expect(42_i == 43) << "should not fire!";
-};
+ skip / test("don't run function") = [] {
+ expect(42_i == 43) << "should not fire!";
+ };
+}
```
```
-All tests passed (1 asserts in 1 tests)
-1 tests skipped
+UT starts =====================================================================
+Running "don't run UDL"... SKIPPED
+Running "don't run function"... SKIPPED
+Suite 'global': all tests passed (2 asserts in 2 tests); 2 tests skipped
+Completed =====================================================================
```
+> https://godbolt.org/z/9zr4daoPr
+
```cpp
tag("nightly") / tag("slow") /
"performance"_test= [] {
@@ -805,8 +937,6 @@ All tests passed (1 asserts in 1 tests)
1 tests skipped
```
-> https://godbolt.org/z/X3_kG4
-
@@ -814,30 +944,39 @@ All tests passed (1 asserts in 1 tests)
```cpp
-"[vector]"_test = [] {
- std::vector v(5);
+#include
+#include
- expect(fatal(5_ul == std::size(v)));
+int main() {
+ using namespace boost::ut;
- should("resize bigger") = [=] { // or "resize bigger"_test
- mut(v).resize(10);
- expect(10_ul == std::size(v));
- };
+ "[vector]"_test = [] {
+ std::vector v(5);
- expect(fatal(5_ul == std::size(v)));
+ expect((5_ul == std::size(v)) >> fatal);
- should("resize smaller") = [=]() mutable { // or "resize smaller"_test
- v.resize(0);
- expect(0_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);
+
+ should("resize smaller") = [=]() mutable { // or "resize smaller"_test
+ v.resize(0);
+ expect(0_ul == std::size(v));
+ };
+ };
+}
```
```
-All tests passed (4 asserts in 1 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (4 asserts in 1 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/cE91bj
+> https://godbolt.org/z/rez4qMhxE
@@ -846,21 +985,30 @@ All tests passed (4 asserts in 1 tests)
```cpp
-"Scenario"_test = [] {
- given("I have...") = [] {
- when("I run...") = [] {
- then("I expect...") = [] { expect(1_i == 1); };
- then("I expect...") = [] { expect(1 == 1_i); };
+#include
+
+int main() {
+ using namespace boost::ut;
+ using namespace boost::ut::bdd;
+
+ "scenario"_test = [] {
+ given("I have...") = [] {
+ when("I run...") = [] {
+ then("I expect 1...") = [] { expect(1_i == 1); };
+ then("I expect 2...") = [] { expect(1 == 1_i); };
+ };
+ };
};
- };
-};
+}
```
```
-All tests passed (2 asserts in 1 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (2 asserts in 1 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/mNBySr
+> https://godbolt.org/z/6roq7v1dj
@@ -869,25 +1017,25 @@ All tests passed (2 asserts in 1 tests)
```cpp
+#include
+
int main() {
- bdd::gherkin::steps steps = [](auto& steps) {
- steps.feature("*") = [&] {
- steps.scenario("*") = [&] {
- steps.given("I have a number {value}") = [&](int value) {
- auto number = value;
- steps.when("I add {value} to it") = [&](int value) {
- number += value;
- };
- steps.then("I expect number to be {value}") = [&](int value) {
- expect(that % number == value);
- };
+ using namespace boost::ut;
+
+ bdd::gherkin::steps steps = [](auto& steps) {
+ steps.feature("*") = [&] {
+ steps.scenario("*") = [&] {
+ steps.given("I have a number {value}") = [&](int value) {
+ auto number = value;
+ steps.when("I add {value} to it") = [&](int value) { number += value; };
+ steps.then("I expect number to be {value}") = [&](int value) { expect(that % number == value); };
+ };
+ };
};
- };
};
- };
- "Gherkin"_test = steps |
- R"(
+ "Gherkin"_test = steps |
+ R"(
Feature: Number
Scenario: Addition
Given I have a number 40
@@ -898,10 +1046,12 @@ int main() {
```
```
-All tests passed (1 asserts in 1 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (1 asserts in 1 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/BP3hyt
+> https://godbolt.org/z/YnaeTrboG
@@ -910,19 +1060,26 @@ All tests passed (1 asserts in 1 tests)
```cpp
+#include
+
int main() {
- describe("equality") = [] {
- it("should be equal") = [] { expect(0_i == 0); };
- it("should not be equal") = [] { expect(1_i != 0); };
- };
+ using namespace boost::ut;
+ using namespace boost::ut::spec;
+
+ describe("equality") = [] {
+ it("should be equal") = [] { expect(0_i == 0_i); };
+ it("should not be equal") = [] { expect(1_i != 0_i); };
+ };
}
```
```
-All tests passed (2 asserts in 1 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (2 asserts in 1 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/BXYJ3a
+> https://godbolt.org/z/znPfdn1jM
@@ -931,31 +1088,40 @@ All tests passed (2 asserts in 1 tests)
```cpp
-for (auto i : std::vector{1, 2, 3}) {
- test("parameterized " + std::to_string(i)) = [i] {
- expect(that % i > 0);
- };
-}
+#include
+#include
+#include
+#include
-"args"_test =
- [](auto arg) {
- expect(arg >= 1_i);
+int main() {
+ using namespace boost::ut;
+
+ for (const auto& i : std::vector{ 1, 2, 3 }) {
+ test("parameterized " + std::to_string(i)) = [i] {
+ expect(that % i > 0);
+ };
}
- | std::vector{1, 2, 3};
-"types"_test =
- [] {
- expect(std::is_integral_v) << "all types are integrals";
+ "args"_test =
+ [](const auto& arg) {
+ expect(arg >= 1_i);
+ }
+ | std::vector{ 1, 2, 3 };
+
+ "types"_test =
+ []() {
+ expect(std::is_integral_v) << "all types are integrals";
}
- | std::tuple{};
+ | std::tuple{};
-"args and types"_test =
- [](TArg arg) {
- expect(fatal(std::is_integral_v));
- expect(42_i == arg or "is true"_b == arg);
- expect(type == type or type == type);
+ "args and types"_test =
+ [](const TArg & arg) {
+ expect(std::is_integral_v >> fatal);
+ expect(42_i == static_cast(arg) or arg);
+ expect(type == type or type == type);
}
- | std::tuple{true, 42};
+ | std::tuple{ true, 42 };
+}
```
When using the `operator|` syntax instead of a `for` loop, the test name will automatically
be extended to avoid duplicate names. For example, the test name for the `args and types` test
@@ -970,31 +1136,45 @@ See the [example on parameterized tests](https://github.com/boost-ext/ut/blob/ma
for details.
```
-All tests passed (14 asserts in 10 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (14 asserts in 10 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/4xGGdo
+> https://godbolt.org/z/rEo4Tn4G4
> And whenever I need to know the specific type for which the test failed,
> I can use `reflection::type_name()`, like this:
```cpp
-"types with type name"_test =
- []() {
- expect(std::is_unsigned_v) << reflection::type_name() << "is unsigned";
+#include
+#include
+#include
+
+int main() {
+ using namespace boost::ut;
+
+ "types with type name"_test =
+ []() {
+ expect(std::is_unsigned_v) << reflection::type_name() << "is unsigned";
}
- | std::tuple{};
+ | std::tuple{};
+}
```
```
-Running "types with type name"...PASSED
-Running "types with type name"...
- :10:FAILED [false] float is unsigned
-FAILED
+UT starts =====================================================================
+Running test "types with type name (float)"...
+FAILED in: ...\example.cpp:10 - test condition: [false] float is unsigned
+===============================================================================
+Suite global
+tests: 2 | 1 failed
+asserts: 2 | 1 passed | 1 failed
+Completed =====================================================================
```
-> https://godbolt.org/z/MEnGnbTY4
+> https://godbolt.org/z/oEW3f1dfM
@@ -1007,28 +1187,31 @@ FAILED
```cpp
+#include
+
namespace ut = boost::ut;
ut::suite errors = [] {
- using namespace ut;
+ using namespace ut;
- "throws"_test = [] {
- expect(throws([] { throw 0; }));
- };
-
- "doesn't throw"_test = [] {
- expect(nothrow([]{}));
- };
+ "throws"_test = [] {
+ expect(throws([] { throw 0; }));
+ };
+ "doesn't throw"_test = [] {
+ expect(nothrow([] {}));
+ };
};
-int main() { }
+int main() {}
```
```
-All tests passed (2 asserts in 2 tests)
+UT starts =====================================================================
+Suite 'unnamed suite': all tests passed (2 asserts in 2 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/CFbTP9
+> https://godbolt.org/z/bGs96hdqG
@@ -1040,27 +1223,33 @@ All tests passed (2 asserts in 2 tests)
```cpp
-"logging"_test = [] {
- boost::ut::log << "pre";
- expect(42_i == 43) << "message on failure";
- boost::ut::log << "post";
-};
+#include
+
+int main() {
+ using namespace boost::ut;
+
+ "logging"_test = [] {
+ boost::ut::log << "pre";
+ expect(42_i == 43) << "message on failure";
+ boost::ut::log << "post";
+ };
+}
```
```
-Running "logging"...
+UT starts =====================================================================
+Running test "logging"...
pre
- logging.cpp:8:FAILED [42 == 43] message on failure
+FAILED in: ...\example.cpp:8 - test condition: [42 == 43] message on failure
post
-FAILED
-
===============================================================================
-
+Suite global
tests: 1 | 1 failed
asserts: 1 | 0 passed | 1 failed
+Completed =====================================================================
```
-> https://godbolt.org/z/26fPSY
+> https://godbolt.org/z/odfrY848n
@@ -1070,27 +1259,33 @@ asserts: 1 | 0 passed | 1 failed
This requires using C++20 with a standard library with std::format support.
```cpp
-"logging"_test = [] {
- boost::ut::log("\npre {} == {}\n", 42, 43);
- expect(42_i == 43) << "message on failure";
- boost::ut::log("\npost {} == {} -> {}\n", 42, 43, 42 == 43);
-};
-```
+#include
+
+int main() {
+ using namespace boost::ut;
+ "logging"_test = [] {
+ boost::ut::log("\npre {} == {}", 42, 43);
+ expect(42_i == 43) << "message on failure";
+ boost::ut::log("\npost {} == {} -> {}", 42, 43, 42 == 43);
+ };
+}
```
-Running "logging"...
-pre 42 == 43
- logging.cpp:8:FAILED [42 == 43] message on failure
-post 42 == 43 -> false
-FAILED
+```
+UT starts =====================================================================
+Running test "logging"...
+pre
+FAILED in: ...\example.cpp:8 - test condition: [42 == 43] message on failure
+post
===============================================================================
-
+Suite global
tests: 1 | 1 failed
asserts: 1 | 0 passed | 1 failed
+Completed =====================================================================
```
-> https://godbolt.org/z/26fPSY
+> https://godbolt.org/z/bhxKKPnTh
@@ -1099,23 +1294,31 @@ asserts: 1 | 0 passed | 1 failed
```cpp
-"matchers"_test = [] {
- constexpr auto is_between = [](auto lhs, auto rhs) {
- return [=](auto value) {
- return that % value >= lhs and that % value <= rhs;
- };
- };
+#include
- expect(is_between(1, 100)(42));
- expect(not is_between(1, 100)(0));
-};
+int main() {
+ using namespace boost::ut;
+
+ "matcher"_test = [] {
+ constexpr auto is_between = [](auto lhs, auto rhs) {
+ return [=](auto value) {
+ return that % value >= lhs and that % value <= rhs;
+ };
+ };
+
+ expect(is_between(1, 100)(42));
+ expect(not is_between(1, 100)(0));
+ };
+}
```
```
-All tests passed (2 asserts in 1 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (2 asserts in 1 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/4qwrCi
+> https://godbolt.org/z/348a8zofd
@@ -1124,20 +1327,29 @@ All tests passed (2 asserts in 1 tests)
```cpp
-"exceptions/aborts"_test = [] {
- expect(throws([] { throw std::runtime_error{""}; }))
- << "throws runtime_error";
- expect(throws([] { throw 0; })) << "throws any exception";
- expect(nothrow([]{})) << "doesn't throw";
- expect(aborts([] { assert(false); }));
-};
+#include
+#include
+
+int main() {
+ using namespace boost::ut;
+
+ "exceptions"_test = [] {
+ expect(throws([] {throw std::runtime_error{ "" }; }))
+ << "throws runtime_error";
+ expect(throws([] {throw 0; })) << "throws any exception";
+ expect(nothrow([] {})) << "doesn't throw";
+ expect(aborts([] { assert(false); })); // only for Unix-like operating systems
+ };
+}
```
```
-All tests passed (4 asserts in 1 tests)
+UT starts =====================================================================
+Suite 'global': all tests passed (4 asserts in 1 tests)
+Completed =====================================================================
```
-> https://godbolt.org/z/A2EehK
+> https://godbolt.org/z/1nbqdc9xh
@@ -1232,7 +1444,7 @@ int main() {
}
```
-> https://godbolt.org/z/XCscF9
+> https://godbolt.org/z/cfKoE8P5n
From 9a094389ba528dec8c9f060083a3565fdc5057e6 Mon Sep 17 00:00:00 2001
From: "Otto C." <12378062+ILer32@users.noreply.github.com>
Date: Fri, 26 Dec 2025 13:15:04 +0800
Subject: [PATCH 3/3] revert the macro change
---
include/boost/ut.hpp | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/include/boost/ut.hpp b/include/boost/ut.hpp
index 0dddf894..392ebe29 100644
--- a/include/boost/ut.hpp
+++ b/include/boost/ut.hpp
@@ -5,18 +5,18 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-#ifdef BOOST_UT_CXX_MODULES
+#if defined(BOOST_UT_CXX_MODULES)
#define BOOST_UT_EXPORT export
#else
#pragma once
#define BOOST_UT_EXPORT
#endif
-#ifndef BOOST_UT_CXX_MODULES
+#if !defined(BOOST_UT_CXX_MODULES)
#include
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
#pragma push_macro("min")
#pragma push_macro("max")
#undef min
@@ -33,25 +33,25 @@
#define BOOST_UT_HAS_FORMAT
#endif
-#ifndef __cpp_rvalue_references
+#if not defined(__cpp_rvalue_references)
#error "[Boost::ext].UT requires support for rvalue references";
-#elifndef __cpp_decltype
+#elif not defined(__cpp_decltype)
#error "[Boost::ext].UT requires support for decltype";
-#elifndef __cpp_return_type_deduction
+#elif not defined(__cpp_return_type_deduction)
#error "[Boost::ext].UT requires support for return type deduction";
-#elifndef __cpp_deduction_guides
+#elif not defined(__cpp_deduction_guides)
#error "[Boost::ext].UT requires support for return deduction guides";
-#elifndef __cpp_generic_lambdas
+#elif not defined(__cpp_generic_lambdas)
#error "[Boost::ext].UT requires support for generic lambdas";
-#elifndef __cpp_constexpr
+#elif not defined(__cpp_constexpr)
#error "[Boost::ext].UT requires support for constexpr";
-#elifndef __cpp_alias_templates
+#elif not defined(__cpp_alias_templates)
#error "[Boost::ext].UT requires support for alias templates";
-#elifndef __cpp_variadic_templates
+#elif not defined(__cpp_variadic_templates)
#error "[Boost::ext].UT requires support for variadic templates";
-#elifndef __cpp_fold_expressions
+#elif not defined(__cpp_fold_expressions)
#error "[Boost::ext].UT requires support for return fold expressions";
-#elifndef __cpp_static_assert
+#elif not defined(__cpp_static_assert)
#error "[Boost::ext].UT requires support for static assert";
#else
#define BOOST_UT_VERSION 2'3'1
@@ -61,7 +61,7 @@
#undef __has_builtin
#endif
-#ifndef __has_builtin
+#if not defined(__has_builtin)
#if defined(__GNUC__) and (__GNUC__ >= 9)
#define __has___builtin_FILE 1
#define __has___builtin_LINE 1
@@ -69,7 +69,7 @@
#define __has_builtin(...) __has_##__VA_ARGS__
#endif
-#ifndef BOOST_UT_CXX_MODULES
+#if !defined(BOOST_UT_CXX_MODULES)
#include
#include
#include
@@ -93,7 +93,7 @@
#include
#include
#endif
-#ifdef __cpp_exceptions
+#if defined(__cpp_exceptions)
#include
#endif