micro-test-plus 5.0.1
µTest++ Testing Framework
Loading...
Searching...
No Matches
test.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can be
9 * obtained from https://opensource.org/licenses/mit.
10 *
11 * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
12 * released under the terms of the Boost Version 1.0 Software License,
13 * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14 */
15
16// ----------------------------------------------------------------------------
17
47
48#ifndef MICRO_OS_PLUS_MICRO_TEST_PLUS_TEST_H_
49#define MICRO_OS_PLUS_MICRO_TEST_PLUS_TEST_H_
50
51// ----------------------------------------------------------------------------
52
53#if defined(__cplusplus)
54
55// ----------------------------------------------------------------------------
56
57#if __has_include("micro-os-plus/project-config.h")
58#include "micro-os-plus/project-config.h"
59#endif // __has_include("micro-os-plus/project-config.h")
60
61#if __has_include("micro-os-plus/micro-test-plus-defines.h")
62#include "micro-os-plus/micro-test-plus-defines.h"
63#endif // __has_include("micro-os-plus/micro-test-plus-defines.h")
64
65#include "runner-totals.h"
66#include "type-traits.h"
67#include "timings.h"
68#include "reflection.h"
69
70#include <functional>
71#include <memory>
72
73// ----------------------------------------------------------------------------
74
75#if defined(__GNUC__)
76#pragma GCC diagnostic push
77
78#pragma GCC diagnostic ignored "-Wpadded"
79#if defined(__clang__)
80#pragma clang diagnostic ignored "-Wc++98-compat"
81#else // GCC only
82#pragma GCC diagnostic ignored "-Wsuggest-final-types"
83#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
84#pragma GCC diagnostic ignored "-Wredundant-tags"
85#endif // defined(__clang__)
86#endif // defined(__GNUC__)
87
88// =============================================================================
89
91{
92 // --------------------------------------------------------------------------
93
94 class runner;
95 class static_runner;
96 class reporter;
97 class runner_totals;
98 class subtest;
99 class suite;
100 class static_suite;
101
102 namespace detail
103 {
104 // ========================================================================
105
117 runner&
118 to_runner (static_runner& static_runner_ref) noexcept;
119
130 void
131 register_static_suite (static_runner& static_runner_ref,
132 static_suite& static_suite_ref);
133
155 {
156 public:
162 test_node (const char* name);
163
167 test_node (const test_node&) = delete;
168
172 test_node (test_node&&) = delete;
173
177 test_node&
179 = delete;
180
184 test_node&
186 = delete;
187
191 virtual ~test_node ();
192
193 // ----------------------------------------------------------------------
194
202 [[nodiscard]] const char*
203 name (void) const noexcept;
204
205 public:
213 [[nodiscard]] runner_totals&
214 totals () noexcept;
215
223 [[nodiscard]] const runner_totals&
224 totals () const noexcept;
225
226 protected:
233 const char* name_;
234
239 };
240
241 // ========================================================================
242
263 {
264 public:
273 runnable_base (const char* name, runner& runner, size_t own_index);
274
278 runnable_base (const runnable_base&) = delete;
279
284
290 = delete;
291
297 = delete;
298
302 virtual ~runnable_base () override;
303
304 // ----------------------------------------------------------------------
305
313 [[nodiscard]] size_t
314 own_index () const noexcept;
315
327 void
328 own_index (size_t index) noexcept;
329
337 [[nodiscard]] size_t
338 current_subtest_index () const noexcept;
339
347 size_t
348 increment_subtest_index () noexcept;
349
357 [[nodiscard]] size_t
358 children_subtests_count (void) const noexcept;
359
367 [[nodiscard]] class reporter&
368 reporter (void) const noexcept;
369
377 [[noreturn]] void
378 abort (const reflection::source_location& sl
379 = reflection::source_location::current ());
380
388 [[nodiscard]] class runner&
389 runner (void) const noexcept;
390
391 protected:
402 void
403 after_subtest_create_ (std::unique_ptr<subtest> child_test,
404 suite& suite);
405
406 protected:
411
416
427
436 std::vector<std::unique_ptr<subtest>> children_subtests_;
437 };
438
439 // ========================================================================
440
451 template <typename Self_T>
453 {
454 public:
468 template <typename Callable_T, typename... Args_T>
469 runnable (const char* name, class runner& runner, size_t own_index,
470 Callable_T&& callable, Args_T&&... arguments);
471
475 runnable (const runnable&) = delete;
476
480 runnable (runnable&&) = delete;
481
485 runnable&
487 = delete;
488
492 runnable&
494 = delete;
495
499 virtual ~runnable () override;
500
501 // ----------------------------------------------------------------------
502
512 virtual void
513 run (void)
514 = 0;
515
516 protected:
521 std::function<void (Self_T&)> callable_;
522 };
523
524 // ------------------------------------------------------------------------
525 } // namespace detail
526
527 // ==========================================================================
528
550 class subtest : public detail::runnable<subtest>
551 {
552 public:
571 template <typename Callable_T, typename... Args_T>
572 subtest (const char* name, class runner& runner, suite& parent_suite,
573 size_t own_index, size_t nesting_depth, Callable_T&& callable,
574 Args_T&&... arguments);
575
579 subtest (const subtest&) = delete;
580
584 subtest (subtest&&) = delete;
585
589 subtest&
590 operator= (const subtest&)
591 = delete;
592
596 subtest&
597 operator= (subtest&&)
598 = delete;
599
603 virtual ~subtest () override;
604
605 // ------------------------------------------------------------------------
606
619 template <typename Callable_T, typename... Args_T>
620 void
621 test (const char* name, Callable_T&& callable, Args_T&&... arguments);
622
623 // ------------------------------------------------------------------------
624
639 template <class Expr_T>
641 auto
642 expect (const Expr_T& expr, const reflection::source_location& sl
644
659 template <class Expr_T>
661 auto
662 assume (const Expr_T& expr, const reflection::source_location& sl
664
665 // ------------------------------------------------------------------------
666
675 virtual void
676 run (void) override;
677
685 [[nodiscard]] size_t
686 nesting_depth () const noexcept;
687
688 protected:
693
698 };
699
700 // ==========================================================================
701
722 class suite : public detail::runnable<suite>
723 {
724 public:
739 template <typename Callable_T, typename... Args_T>
740 suite (const char* name, class runner& runner, Callable_T&& callable,
741 Args_T&&... arguments);
742
746 suite (const suite&) = delete;
747
751 suite (suite&&) = delete;
752
756 suite&
757 operator= (const suite&)
758 = delete;
759
763 suite&
764 operator= (suite&&)
765 = delete;
766
770 virtual ~suite () override;
771
772 // ------------------------------------------------------------------------
773
786 template <typename Callable_T, typename... Args_T>
787 void
788 test (const char* name, Callable_T&& callable, Args_T&&... arguments);
789
790 // ------------------------------------------------------------------------
791
799 [[nodiscard]] detail::timestamps&
800 timings () noexcept;
801
809 [[nodiscard]] const detail::timestamps&
810 timings () const noexcept;
811
820 virtual void
821 run (void) override;
822
823 protected:
827 detail::timestamps timings_;
828 };
829
830 // ==========================================================================
831
847 class top_suite : public suite
848 {
849 public:
850 // Expose the accessor for the suite name from the base test_node class,
851 // since the top_suite may need to change its name after construction, and
852 // the base class provides the necessary interface for that purpose.
854
861 top_suite (const char* name, class runner& runner);
862
866 top_suite (const top_suite&) = delete;
867
871 top_suite (top_suite&&) = delete;
872
876 top_suite&
877 operator= (const top_suite&)
878 = delete;
879
883 top_suite&
884 operator= (top_suite&&)
885 = delete;
886
890 virtual ~top_suite () override;
891
897 void
898 name (const char* new_name) noexcept;
899 };
900
901 // ==========================================================================
902
932 class static_suite : public suite
933 {
934 public:
948 template <typename Callable_T, typename... Args_T>
949 static_suite (const char* name, static_runner& runner,
950 Callable_T&& callable, Args_T&&... arguments);
951
955 static_suite (const static_suite&) = delete;
956
961
966 operator= (const static_suite&)
967 = delete;
968
973 operator= (static_suite&&)
974 = delete;
975
979 virtual ~static_suite () override;
980
981 // ------------------------------------------------------------------------
982
991 virtual void
992 run (void) override;
993
994 protected:
999 std::function<void (static_suite&)> static_callable_;
1000 };
1001
1002 // --------------------------------------------------------------------------
1003} // namespace micro_os_plus::micro_test_plus
1004
1005#if defined(__GNUC__)
1006#pragma GCC diagnostic pop
1007#endif // defined(__GNUC__)
1008
1009// ----------------------------------------------------------------------------
1010
1011#endif // defined(__cplusplus)
1012
1013// ============================================================================
1014// Templates, inlines & constexpr implementations.
1015
1016#include "inlines/test-inlines.h"
1017
1018// ----------------------------------------------------------------------------
1019
1020#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TEST_H_
1021
1022// ----------------------------------------------------------------------------
runnable_base(const runnable_base &)=delete
Deleted copy constructor to prevent copying.
class runner & runner(void) const noexcept
Gets the test runner associated with this test runnable.
size_t current_subtest_index() const noexcept
Returns the index of the most recently created child subtest.
runnable_base(const char *name, runner &runner, size_t own_index)
Constructs a runnable_base with a name, runner, and index.
Definition test.cpp:118
runnable_base(runnable_base &&)=delete
Deleted move constructor to prevent moving.
void after_subtest_create_(std::unique_ptr< subtest > child_test, suite &suite)
Registers a newly constructed child subtest and executes it immediately.
Definition test.cpp:177
size_t own_index_
The test index, counting from 1.
Definition test.h:415
size_t own_index() const noexcept
Returns the positional index of this object within its parent.
size_t current_subtest_index_
The subtest index, counting from 1.
Definition test.h:426
class reporter & reporter(void) const noexcept
Gets the test reporter associated with this test runnable.
Definition test.cpp:149
size_t children_subtests_count(void) const noexcept
Returns the number of direct child subtests owned by this node.
class runner & runner_
Reference to the test runner that owns this object.
Definition test.h:410
void abort(const reflection::source_location &sl=reflection::source_location::current())
Aborts test execution via the owning runner.
Definition test.cpp:161
size_t increment_subtest_index() noexcept
Increments and returns the child subtest sequential index.
std::vector< std::unique_ptr< subtest > > children_subtests_
Owning collection of direct child subtests.
Definition test.h:436
CRTP base class factoring out callable storage, rule-of-five, and run() logic shared by subtest and s...
Definition test.h:453
std::function< void(Self_T &)> callable_
Callable storing the test body and any bound arguments. Invoked with a reference to the derived Self_...
Definition test.h:521
runnable(const char *name, class runner &runner, size_t own_index, Callable_T &&callable, Args_T &&... arguments)
Class template constructor.
runnable(const runnable &)=delete
Deleted copy constructor to prevent copying.
runnable(runnable &&)=delete
Deleted move constructor to prevent moving.
virtual void run(void)=0
Runs the test function by invoking the stored callable with the derived self instance.
Aggregated pass/fail/subtest counters for a node in the test tree.
const char * name(void) const noexcept
Gets the node name.
virtual ~test_node()
Virtual destructor for the test_node class.
Definition test.cpp:99
runner_totals totals_
Totals for the test node, including nested cases.
Definition test.h:238
runner_totals & totals() noexcept
Gets the totals for the test.
test_node(const char *name)
Constructs a test node.
Definition test.cpp:86
test_node(test_node &&)=delete
Deleted move constructor to prevent moving.
const char * name_
The test node name.
Definition test.h:233
test_node(const test_node &)=delete
Deleted copy constructor to prevent copying.
test_node & operator=(const test_node &)=delete
Deleted copy assignment operator to prevent copying.
A begin/end timestamp pair used to measure elapsed time.
Definition timings.h:214
Local implementation of source location information for diagnostics.
Definition reflection.h:150
static constexpr source_location current(const char *file="unknown", unsigned int line={}) noexcept
Obtain the current source location.
Reporter to display test results, including operand values and types for failures.
Definition reporter.h:195
The test runner for the µTest++ framework.
Definition runner.h:144
A runner variant that also manages statically-registered test suites.
Definition runner.h:378
A test suite designed for static (namespace-scope) registration with a static_runner.
Definition test.h:933
std::function< void(static_suite &)> static_callable_
Callable storing the static suite body and any bound arguments. Invoked with a reference to the concr...
Definition test.h:999
static_suite(static_suite &&)=delete
Deleted move constructor to prevent moving.
virtual void run(void) override
Executes the static suite body using the stored static callable.
Definition test.cpp:345
static_suite(const char *name, static_runner &runner, Callable_T &&callable, Args_T &&... arguments)
Class template constructor for static_suite.
static_suite(const static_suite &)=delete
Deleted copy constructor to prevent copying.
A named, runnable test case that lives inside a suite.
Definition test.h:551
suite & parent_suite_
Reference to the parent suite that owns this subtest.
Definition test.h:692
subtest(subtest &&)=delete
Deleted move constructor to prevent moving.
void test(const char *name, Callable_T &&callable, Args_T &&... arguments)
Adds a test case to the suite.
subtest(const char *name, class runner &runner, suite &parent_suite, size_t own_index, size_t nesting_depth, Callable_T &&callable, Args_T &&... arguments)
Constructs a subtest with a name, runner, parent suite, index, nesting depth, and callable.
virtual void run(void) override
Executes the subtest body by invoking the stored callable.
Definition test.cpp:230
subtest(const subtest &)=delete
Deleted copy constructor to prevent copying.
size_t nesting_depth_
The nesting depth of this subtest within the suite.
Definition test.h:697
size_t nesting_depth() const noexcept
Returns the nesting depth of this subtest.
A named, runnable test suite registered with the test runner.
Definition test.h:723
suite(const char *name, class runner &runner, Callable_T &&callable, Args_T &&... arguments)
Constructs a suite with a name, runner, and callable body.
virtual void run(void) override
Executes the suite body by invoking the stored callable.
Definition test.cpp:271
suite(const suite &)=delete
Deleted copy constructor to prevent copying.
detail::timestamps timings_
Timing measurements for this suite's execution.
Definition test.h:827
detail::timestamps & timings() noexcept
Gets the timings for this suite.
suite(suite &&)=delete
Deleted move constructor to prevent moving.
void test(const char *name, Callable_T &&callable, Args_T &&... arguments)
Adds a test case to the suite.
top_suite(top_suite &&)=delete
Deleted move constructor to prevent moving.
void name(const char *new_name) noexcept
Sets the name of the top-level suite.
top_suite(const char *name, class runner &runner)
Constructs the top-level suite with a name and runner reference.
Definition test.cpp:299
top_suite(const top_suite &)=delete
Deleted copy constructor to prevent copying.
C++20 concept satisfied when a type can be used as a test expression in expect() or assume().
auto assume(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current())
Check a condition and, if false, abort test execution.
auto expect(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current())
Evaluate a generic condition and report the results.
Internal implementation details for the µTest++ framework.
runner & to_runner(static_runner &static_runner_ref) noexcept
Converts a static_runner reference to a runner reference.
Definition runner.cpp:83
void register_static_suite(static_runner &static_runner_ref, static_suite &static_suite_ref)
Registers a static suite with a static runner.
Definition runner.cpp:95
Reflection utilities for the µTest++ testing framework.
Primary namespace for the µTest++ testing framework.
C++ header file with declarations for the µTest++ reflection utilities.
C++ header file with declarations for the µTest++ runner totals.
C++ header file with inline implementations for the µTest++ test suite.
C++ header file with declarations for the µTest++ timing utilities.
C++ header file with declarations for the µTest++ type trait utilities and metaprogramming support.