micro-test-plus 5.0.1
µTest++ Testing Framework
Loading...
Searching...
No Matches
micro_os_plus::micro_test_plus::runner Class Reference

The test runner for the µTest++ framework. More...

#include "micro-os-plus/micro-test-plus.h"

Inheritance diagram for micro_os_plus::micro_test_plus::runner:

Public Member Functions

 runner (const char *top_suite_name)
 Deprecated constructor for the runner class.
 runner (const runner &)=delete
 Deleted copy constructor to prevent copying.
 runner (runner &&)=delete
 Deleted move constructor to prevent moving.
 runner (void)
 Constructor for the runner class.
virtual ~runner () override
 Destructor for the runner class.
void abort (const reflection::source_location &sl=reflection::source_location::current())
 Aborts test execution immediately.
int exit_code (void)
 Returns 0 if all tests were successful, 1 otherwise.
class suiteinitialise (int argc, char *argv[], const char *top_suite_name="")
 Initialises the test runner with command-line arguments.
const char * name (void) const noexcept
 Gets the node name.
runneroperator= (const runner &)=delete
 Deleted copy assignment operator to prevent copying.
runneroperator= (runner &&)=delete
 Deleted move assignment operator to prevent moving.
class reporter & reporter (void) const noexcept
 Returns a reference to the test reporter.
template<typename Callable_T, typename... Args_T>
void suite (const char *name, Callable_T &&callable, Args_T &&... arguments)
 Adds a test suite to the runner.
size_t suites_count (void) const noexcept
 Returns the count of test suites.
const detail::timestampstimings () const noexcept
 Gets the timings for this runner (const overload).
detail::timestampstimings () noexcept
 Gets the timings for this runner.
virtual size_t total_suites_count (void) const noexcept
 Returns the total count of registered test suites.
const runner_totals & totals () const noexcept
 Gets the totals for the test (const overload).
runner_totals & totals () noexcept
 Gets the totals for the test.

Protected Member Functions

void register_suite_ (std::unique_ptr< class suite > suite)
 Registers a test suite with the runner.
virtual void run_suites_ (void)
 Runs all registered test suites.

Protected Attributes

std::vector< std::unique_ptr< class suite > > children_suites_
 Owning collection of dynamically registered child suites.
const char * name_
 The test node name.
std::unique_ptr< class reporterreporter_
 Pointer to the test reporter used for outputting test results.
detail::timestamps timings_
 Timings for this runner.
class top_suite top_suite_
 The implicit top-level suite; always present and executed first.
std::string top_suite_name_
 Owned storage for the implicit top-suite name.
runner_totals totals_
 Totals for the test node, including nested cases.

Detailed Description

The runner class is responsible for managing the registration and execution of test suites within the µTest++ framework. It maintains a collection of test suites, each of which registers itself automatically upon construction, enabling seamless integration and execution of tests across different components and folders of a project.

The test runner provides methods for initialising the test environment, registering test suites, retrieving the runner's name, and determining the overall test result via an exit code. It also offers an abort mechanism for terminating test execution in exceptional circumstances.

All members and methods are defined within the micro_os_plus::micro_test_plus namespace, ensuring clear separation from user code and minimising the risk of naming conflicts.

Definition at line 143 of file runner.h.

Constructor & Destructor Documentation

◆ runner() [1/4]

micro_os_plus::micro_test_plus::runner::runner ( void )
Parameters
None.

The constructor initialises a new runner instance together with its top suite (top_suite_). If tracing is enabled, it outputs the function signature for diagnostic purposes.

Definition at line 109 of file runner.cpp.

109 : test_node{ "runner" }, top_suite_{ "", *this }
110 {
111#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
112 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name ());
113#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
114 }
const char * name(void) const noexcept
Gets the node name.
test_node(const char *name)
Constructs a test node.
Definition test.cpp:86
class top_suite top_suite_
The implicit top-level suite; always present and executed first.
Definition runner.h:324

References micro_os_plus::micro_test_plus::detail::test_node::test_node(), micro_os_plus::micro_test_plus::detail::test_node::name(), and top_suite_.

Referenced by runner(), runner(), micro_os_plus::micro_test_plus::static_runner::static_runner(), micro_os_plus::micro_test_plus::static_runner::static_runner(), operator=(), operator=(), micro_os_plus::micro_test_plus::static_runner::operator=(), and micro_os_plus::micro_test_plus::static_runner::register_static_suite().

◆ runner() [2/4]

micro_os_plus::micro_test_plus::runner::runner ( const char * top_suite_name)
Parameters
top_suite_nameThe name given to the implicit top suite. Defaults to an empty string.
Deprecated
Use the anonymous constructor.

The constructor initialises a new runner instance together with its top suite (top_suite_). If tracing is enabled, it outputs the function signature for diagnostic purposes.

Definition at line 122 of file runner.cpp.

123 : test_node{ "runner" }, top_suite_{ top_suite_name, *this }
124 {
125#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
126 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name ());
127#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
128 }

References micro_os_plus::micro_test_plus::detail::test_node::test_node(), micro_os_plus::micro_test_plus::detail::test_node::name(), and top_suite_.

◆ runner() [3/4]

micro_os_plus::micro_test_plus::runner::runner ( const runner & )
delete

References runner().

◆ runner() [4/4]

micro_os_plus::micro_test_plus::runner::runner ( runner && )
delete

References runner().

◆ ~runner()

micro_os_plus::micro_test_plus::runner::~runner ( )
overridevirtual

The reporter_ unique pointer is released automatically. If tracing is enabled, the function signature is output for diagnostic purposes.

Definition at line 135 of file runner.cpp.

136 {
137#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
138 trace::printf ("%s\n", __PRETTY_FUNCTION__);
139#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
140
141 // reporter_ is a unique_ptr; destroyed automatically.
142 }

Member Function Documentation

◆ abort()

void micro_os_plus::micro_test_plus::runner::abort ( const reflection::source_location & sl = reflection::source_location::current ())
Parameters
slThe source location from which the abort is triggered.
Returns
Nothing.

Prints the source location of the fatal error to stderr and then terminates the process via ::abort().

Definition at line 394 of file runner.cpp.

395 {
396#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
397 trace::printf ("%s\n", __PRETTY_FUNCTION__);
398#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
399
400 fprintf (stderr, "\nerror: test execution aborted at %s:%u\n",
401 reflection::short_name (sl.file_name ()), sl.line ());
402
403 ::abort ();
404 }
void abort(const reflection::source_location &sl=reflection::source_location::current())
Aborts test execution immediately.
Definition runner.cpp:394
const char * short_name(const char *name) noexcept
Extract a short type or function name from a fully qualified name.

References abort(), micro_os_plus::micro_test_plus::reflection::source_location::file_name(), micro_os_plus::micro_test_plus::reflection::source_location::line(), and micro_os_plus::micro_test_plus::reflection::short_name().

Referenced by abort().

◆ exit_code()

int micro_os_plus::micro_test_plus::runner::exit_code ( void )
Parameters
None.
Returns
Integer exit code representing the overall test result.

Finalises the top suite by recording its end timestamp and notifying the reporter, then accumulates its totals into the runner totals. Subsequently invokes run_suites_() to sort, execute, and accumulate all registered child suites. Finally, records the session end timestamp, notifies the reporter, and returns 0 if all checks passed or 1 otherwise.

Definition at line 358 of file runner.cpp.

359 {
360#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
361 trace::printf ("%s\n", __PRETTY_FUNCTION__);
362#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
363
364 if (reporter_ == nullptr)
365 {
366 fprintf (stderr, "error: test runner not initialised\n");
367 return 1;
368 }
369
370 top_suite_.timings ().timestamp_end ();
371 reporter_->end_suite (top_suite_);
372 totals_ += top_suite_.totals ();
373
374 run_suites_ ();
375
376 timings_.timestamp_end ();
377 reporter_->end_session (*this);
378
379 const int result = totals_.was_successful () ? 0 : 1;
380
381#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
382 trace::printf ("%s -> %d\n", __PRETTY_FUNCTION__, result);
383#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
384
385 return result;
386 }
runner_totals totals_
Totals for the test node, including nested cases.
Definition test.h:238
detail::timestamps timings_
Timings for this runner.
Definition runner.h:344
std::unique_ptr< class reporter > reporter_
Pointer to the test reporter used for outputting test results.
Definition runner.h:339
virtual void run_suites_(void)
Runs all registered test suites.
Definition runner.cpp:311

References reporter_, run_suites_(), timings_, top_suite_, and micro_os_plus::micro_test_plus::detail::test_node::totals_.

◆ initialise()

suite & micro_os_plus::micro_test_plus::runner::initialise ( int argc,
char * argv[],
const char * top_suite_name = "" )
Parameters
argcThe argument count from main().
argvThe argument vector from main().
top_suite_nameThe name given to the implicit top suite. Defaults to an empty string.
Returns
Reference to the top-level test suite.

Captures command-line arguments, selects the reporter implementation (human or tap), starts session timing, and emits the initial reporter notifications for the session and top suite.

If the top suite name is not provided, it attempts to derive a name from argv[0] or defaults to "default suite".

If tracing is enabled, the command-line arguments are also logged for diagnostic purposes.

Definition at line 165 of file runner.cpp.

166 {
167#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
168 trace::printf ("%s\n", __PRETTY_FUNCTION__);
169
170#if !(defined(MICRO_OS_PLUS_STARTUP_ENABLED) \
171 && defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED))
172#if defined(MICRO_OS_PLUS_DEBUG_ENABLED)
173 trace::printf ("argv[");
174 for (int i = 0; i < argc; ++i)
175 {
176 if (i > 0)
177 {
178 trace::printf (", ");
179 }
180 trace::printf ("'%s'", argv[i]);
181 }
182 trace::puts ("]");
183#endif // defined(MICRO_OS_PLUS_DEBUG_ENABLED)
184#endif // !defined(MICRO_OS_PLUS_STARTUP_ENABLED)
185#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
186
187 if (strlen (top_suite_name) > 0)
188 {
189 // If provided by this call, use it, possibly override the
190 // deprecated constructor.
191 top_suite_name_ = top_suite_name;
192 top_suite_.name (top_suite_name_.c_str ());
193 }
194 else if (strlen (top_suite_.name ()) == 0)
195 {
196 // If not provided by the constructor or by this call, try to extract a
197 // name from argv[0], which is commonly the executable name. If that
198 // fails, use a default name.
199 if (argc > 0 && argv != nullptr && argv[0] != nullptr)
200 {
201 std::string_view top_suite_name_view{ utility::extract_file_name (
202 argv[0]) };
203
204 const auto dot_pos = top_suite_name_view.rfind ('.');
205 if (dot_pos != std::string_view::npos)
206 {
207 top_suite_name_view = top_suite_name_view.substr (0, dot_pos);
208 }
209
210 top_suite_name_ = top_suite_name_view;
211 }
212 else
213 {
214 top_suite_name_ = "default suite";
215 }
216 top_suite_.name (top_suite_name_.c_str ());
217 }
218
219 std::vector<std::string_view> argvs (argv, argv + argc);
220
221 std::string_view reporter_name{ "tap" };
222 static constexpr std::string_view reporter_prefix{ "--reporter=" };
223 for (size_t i = 0; i < argvs.size (); ++i)
224 {
225 if (argvs[i].starts_with (reporter_prefix))
226 {
227 reporter_name = argvs[i].substr (reporter_prefix.size ());
228 }
229 else if (argvs[i]
230 == reporter_prefix.substr (0, reporter_prefix.size () - 1))
231 {
232 if (i + 1 < argvs.size ())
233 {
234 reporter_name = argvs[++i];
235 }
236 else
237 {
238 fprintf (stderr, "error: --reporter option requires a "
239 "reporter name argument\n");
240 exit (1);
241 }
242 }
243 }
244
245 // Initialise and configure the reporter.
246 if (reporter_name == "human")
247 {
248 reporter_ = std::make_unique<reporter_human> (
249 std::make_unique<std::vector<std::string_view>> (
250 std::move (argvs)));
251 }
252 else if (reporter_name == "tap")
253 {
254 reporter_ = std::make_unique<reporter_tap> (
255 std::make_unique<std::vector<std::string_view>> (
256 std::move (argvs)));
257 }
258 else
259 {
260 fprintf (stderr, "error: unknown reporter '%.*s'\n",
261 static_cast<int> (reporter_name.size ()),
262 reporter_name.data ());
263 exit (1);
264 }
265
266 // ------------------------------------------------------------------------
267
268 timings_.timestamp_begin ();
269 reporter_->begin_session (*this);
270
271 top_suite_.timings ().timestamp_begin ();
272 reporter_->begin_suite (top_suite_);
273
274 return top_suite_;
275 }
std::string top_suite_name_
Owned storage for the implicit top-suite name.
Definition runner.h:349
const char * extract_file_name(const char *path) noexcept
Extracts the file name component from a full path.
Definition utility.cpp:87

References micro_os_plus::micro_test_plus::utility::extract_file_name(), reporter_, timings_, top_suite_, and top_suite_name_.

◆ name()

const char * micro_os_plus::micro_test_plus::detail::test_node::name ( void ) const
inlinenodiscardnoexceptinherited

◆ operator=() [1/2]

runner & micro_os_plus::micro_test_plus::runner::operator= ( const runner & )
delete

References runner().

◆ operator=() [2/2]

◆ register_suite_()

void micro_os_plus::micro_test_plus::runner::register_suite_ ( std::unique_ptr< class suite > suite)
protected
Parameters
suiteOwning pointer to the test suite to register.
Returns
Nothing.

Takes ownership of the supplied suite unique pointer and appends it to the internal children_suites_ vector, deferring execution until run_suites_() is called. If tracing is enabled, the suite name is logged for diagnostic purposes.

Definition at line 291 of file runner.cpp.

292 {
293#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
294 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, suite->name ());
295#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
296
297 children_suites_.push_back (std::move (suite));
298 }
void suite(const char *name, Callable_T &&callable, Args_T &&... arguments)
Adds a test suite to the runner.
std::vector< std::unique_ptr< class suite > > children_suites_
Owning collection of dynamically registered child suites.
Definition runner.h:334

References children_suites_, and suite().

Referenced by operator=(), and suite().

◆ reporter()

class reporter & micro_os_plus::micro_test_plus::runner::reporter ( void ) const
inlinenodiscardnoexcept
Parameters
None.
Returns
Reference to the test reporter.

Returns a reference to the reporter object stored in the unique pointer.

Definition at line 79 of file runner-inlines.h.

80 {
81 return *reporter_;
82 }

References reporter_.

Referenced by operator=().

◆ run_suites_()

void micro_os_plus::micro_test_plus::runner::run_suites_ ( void )
protectedvirtual
Parameters
None.

Sorts children_suites_ alphabetically by suite name using a selection sort on unique_ptr::swap, avoiding the -Waggregate-return diagnostic that std::sort would trigger on unique-pointer iterators. Each suite is assigned a 1-based index offset by the top-suite index, executed via suite::run(), and its totals are accumulated into the runner totals. The executed-subtest counter is not incremented; suites are not counted as subtests.

Reimplemented in micro_os_plus::micro_test_plus::static_runner.

Definition at line 311 of file runner.cpp.

312 {
313 // Use selection sort with unique_ptr::swap (returns void) to avoid
314 // std::sort triggering -Waggregate-return via std::move_backward,
315 // which returns a class-type iterator when operating on unique_ptr
316 // elements.
317 const size_t n = children_suites_.size ();
318 for (size_t i = 0; i < n; ++i)
319 {
320 size_t min_idx = i;
321 for (size_t j = i + 1; j < n; ++j)
322 {
323 if (std::string_view{ children_suites_[j]->name () }
324 < std::string_view{ children_suites_[min_idx]->name () })
325 min_idx = j;
326 }
327 if (min_idx != i)
328 children_suites_[i].swap (children_suites_[min_idx]);
329 }
330
331 for (size_t i = 0; i < n; ++i)
332 {
333 auto* suite_ptr = children_suites_[i].get ();
334
335 // +1 for 1-based index, +1 for top suite
336 suite_ptr->own_index (i + 1 + 1);
337
338 // Run the child suite immediately.
339 suite_ptr->run ();
340
341 // Accumulate the totals from the child suite into the runner
342 // totals.
343 // DO NOT increment executed_subtests here.
344 totals_ += suite_ptr->totals ();
345 }
346 }

References children_suites_, and micro_os_plus::micro_test_plus::detail::test_node::totals_.

Referenced by exit_code(), operator=(), and micro_os_plus::micro_test_plus::static_runner::run_suites_().

◆ suite()

template<typename Callable_T, typename... Args_T>
void micro_os_plus::micro_test_plus::runner::suite ( const char * name,
Callable_T && callable,
Args_T &&... arguments )
Template Parameters
Callable_TThe type of a callable object.
Args_TThe types of the callable arguments.
Parameters
nameThe test suite name or description, used in reports.
callableA generic callable object, usually a lambda, invoked to perform the test suite.
argumentsA possibly empty list of arguments to be passed to the callable.
Returns
Nothing.

Constructs a suite object on the heap, binding the callable and any additional arguments, then transfers ownership to the runner via register_suite_(). The suite runs immediately as part of the registration process.

Definition at line 115 of file runner-inlines.h.

117 {
118#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
119 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
120#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
121
122 auto child_suite = std::make_unique<class suite> (
123 name, *this, std::forward<Callable_T> (callable),
124 std::forward<Args_T> (arguments)...);
125
126 register_suite_ (std::move (child_suite));
127 }
void register_suite_(std::unique_ptr< class suite > suite)
Registers a test suite with the runner.
Definition runner.cpp:291

References micro_os_plus::micro_test_plus::detail::test_node::name(), and register_suite_().

Referenced by operator=(), micro_os_plus::micro_test_plus::static_runner::operator=(), micro_os_plus::micro_test_plus::static_runner::register_static_suite(), and register_suite_().

◆ suites_count()

size_t micro_os_plus::micro_test_plus::runner::suites_count ( void ) const
nodiscardnoexcept
Parameters
None.
Returns
The number of test suites, including the top one.

Returns the number of registered child suites plus one, accounting for the top suite.

Definition at line 412 of file runner.cpp.

413 {
414 return children_suites_.size () + 1;
415 }

References children_suites_.

Referenced by operator=(), micro_os_plus::micro_test_plus::static_runner::run_suites_(), total_suites_count(), and micro_os_plus::micro_test_plus::static_runner::total_suites_count().

◆ timings() [1/2]

const detail::timestamps & micro_os_plus::micro_test_plus::runner::timings ( ) const
inlinenodiscardnoexcept
Parameters
None.
Returns
A const reference to the timestamps instance.

Returns a const reference to the timestamps member.

Definition at line 99 of file runner-inlines.h.

100 {
101 return timings_;
102 }

References timings_.

◆ timings() [2/2]

detail::timestamps & micro_os_plus::micro_test_plus::runner::timings ( )
inlinenodiscardnoexcept
Parameters
None.
Returns
A reference to the timestamps instance.

Returns a reference to the timestamps member.

Definition at line 89 of file runner-inlines.h.

90 {
91 return timings_;
92 }

References timings_.

Referenced by micro_os_plus::micro_test_plus::reporter_human::end_session(), micro_os_plus::micro_test_plus::reporter_tap::end_session(), and operator=().

◆ total_suites_count()

size_t micro_os_plus::micro_test_plus::runner::total_suites_count ( void ) const
nodiscardvirtualnoexcept
Parameters
None.
Returns
The total number of test suites managed by this runner.

For the base runner, the total suite count equals suites_count(), as there are no additional static suites.

Reimplemented in micro_os_plus::micro_test_plus::static_runner.

Definition at line 423 of file runner.cpp.

424 {
425 return suites_count ();
426 }
size_t suites_count(void) const noexcept
Returns the count of test suites.
Definition runner.cpp:412

References suites_count().

Referenced by micro_os_plus::micro_test_plus::reporter_human::end_session(), and micro_os_plus::micro_test_plus::reporter_tap::end_session().

◆ totals() [1/2]

const runner_totals & micro_os_plus::micro_test_plus::detail::test_node::totals ( ) const
inlinenodiscardnoexceptinherited
Parameters
None.
Returns
A const reference to the runner_totals instance.

Returns a const reference to the runner_totals member.

Definition at line 114 of file test-inlines.h.

115 {
116 return totals_;
117 }

References totals_.

◆ totals() [2/2]

runner_totals & micro_os_plus::micro_test_plus::detail::test_node::totals ( )
inlinenodiscardnoexceptinherited

Member Data Documentation

◆ children_suites_

std::vector<std::unique_ptr<class suite> > micro_os_plus::micro_test_plus::runner::children_suites_
protected

Each call to runner::suite() appends a new suite to this vector and runs it immediately. The vector retains ownership of all suites for the lifetime of the runner.

Definition at line 334 of file runner.h.

Referenced by register_suite_(), run_suites_(), and suites_count().

◆ name_

const char* micro_os_plus::micro_test_plus::detail::test_node::name_
protectedinherited
Note
Derived classes may access this member directly in addition to the public name() getter.

Definition at line 233 of file test.h.

Referenced by test_node(), micro_os_plus::micro_test_plus::detail::runnable< Self_T >::~runnable(), micro_os_plus::micro_test_plus::detail::runnable_base::~runnable_base(), ~test_node(), and name().

◆ reporter_

std::unique_ptr<class reporter> micro_os_plus::micro_test_plus::runner::reporter_
protected

Definition at line 339 of file runner.h.

Referenced by exit_code(), initialise(), and reporter().

◆ timings_

detail::timestamps micro_os_plus::micro_test_plus::runner::timings_
protected

Definition at line 344 of file runner.h.

Referenced by exit_code(), initialise(), timings(), and timings().

◆ top_suite_

class top_suite micro_os_plus::micro_test_plus::runner::top_suite_
protected

Definition at line 324 of file runner.h.

Referenced by runner(), runner(), exit_code(), and initialise().

◆ top_suite_name_

std::string micro_os_plus::micro_test_plus::runner::top_suite_name_
protected

Definition at line 349 of file runner.h.

Referenced by initialise().

◆ totals_

runner_totals micro_os_plus::micro_test_plus::detail::test_node::totals_
protectedinherited

The documentation for this class was generated from the following files: