Skip to main content

The test-reporter.cpp File Reference

C++ source file with implementations for the µTest++ test reporter methods. More...

Included Headers

Namespaces Index

namespacemicro_os_plus

The primary namespace for the µOS++ framework. More...

namespacemicro_os_plus::micro_test_plus

Primary namespace for the µTest++ testing framework. More...

Functions Index

test_reporter &endl (test_reporter &stream)

Output stream manipulator for ending a line in test reports. More...

Description

C++ source file with implementations for the µTest++ test reporter methods.

This source file contains the core implementations for the test reporting facilities of the µTest++ framework. It provides the logic for formatting and outputting test results, including operator overloads for a wide range of value types, containers, and comparison expressions, as well as structured output for logical and exception-related assertions.

The test reporter is responsible for presenting test outcomes in a clear, consistent, and expressive manner, supporting both value and pointer semantics, and providing detailed diagnostics for both successful and failed test cases. Special attention is given to formatting, colour highlighting, and extensibility, enabling professional and readable test reports suitable for embedded and general C++ development.

All definitions reside within the micro_os_plus::micro_test_plus namespace, ensuring clear separation from user code and minimising the risk of naming conflicts.

This file must be included when building the µTest++ library.

Functions

endl()

test_reporter & micro_os_plus::micro_test_plus::endl (test_reporter & stream)

Output stream manipulator for ending a line in test reports.

Parameters
streamReference to the test_reporter instance.
Returns

Reference to the same test_reporter instance, enabling chaining of output operations.

The endl function inserts a newline character into the specified test_reporter stream and flushes its output buffer. This operation ensures that each test output line is clearly separated and immediately visible, facilitating the readability and clarity of test results across all test cases and folders within the µTest++ framework.

Definition at line 73 of file test-reporter.cpp.

File Listing

The file content with the documentation metadata removed is:

1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2021 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any 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
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 Software License,
13 * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14 */
15
16// ----------------------------------------------------------------------------
17
43
44// ----------------------------------------------------------------------------
45
46#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
47#include <micro-os-plus/config.h>
48#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
49
51
52// ----------------------------------------------------------------------------
53
54#pragma GCC diagnostic ignored "-Waggregate-return"
55#if defined(__clang__)
56#pragma clang diagnostic ignored "-Wc++98-compat"
57#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
58#endif
59
61{
62 // --------------------------------------------------------------------------
63
74 {
75 reporter.endline ();
76 return stream;
77 }
78
79 // --------------------------------------------------------------------------
80
93 void
94 test_reporter::output_pass_prefix_ (std::string& message)
95 {
96 *this << colors_.pass;
98 {
99 *this << " ";
100 }
101 *this << " ✓ ";
102 *this << colors_.none;
103 if (!message.empty ())
104 {
105 *this << message.c_str ();
106 }
107 }
108
124 void
126 {
127 *this << endl;
128
129 flush ();
130 }
131
143 void
145 std::string& message, const reflection::source_location& location)
146 {
147 *this << colors_.fail;
149 {
150 *this << " ";
151 }
152 *this << " ✗ ";
153 *this << colors_.none;
154 if (!message.empty ())
155 {
156 *this << message.c_str ();
157 *this << " ";
158 }
159 *this << colors_.fail << "FAILED" << colors_.none;
160#pragma GCC diagnostic push
161#if defined(__clang__)
162#pragma clang diagnostic ignored "-Wsign-conversion"
163#elif defined(__GNUC__)
164#pragma GCC diagnostic ignored "-Wnarrowing"
165#pragma GCC diagnostic ignored "-Wsign-conversion"
166#endif
167 *this << " (" << reflection::short_name (location.file_name ()) << ":"
169 location.line ()
170 };
171#pragma GCC diagnostic pop
172 }
173
183 void
185 {
186 *this << ")";
187 if (abort)
188 {
189 *this << " aborted...";
190 }
191 *this << endl;
192
193 flush ();
194 }
195
207 {
208 // Call the endl function.
209 (*func) (*this);
210 return *this;
211 }
212
221 void
223 {
224 out_.append ("\n");
225 flush ();
226 }
227
235 void
237 {
238 fflush (stdout); // Sync STDOUT.
239 }
240
250 test_reporter::operator<<(std::string_view sv)
251 {
252 out_.append (sv);
253 return *this;
254 }
255
265 {
266 out_.append (1, c);
267 return *this;
268 }
269
279 test_reporter::operator<<(const char* s)
280 {
281 out_.append (s);
282 return *this;
283 }
284
295 {
296 out_.append (s);
297 return *this;
298 }
299
310 {
311 out_.append (v ? "true" : "false");
312 return *this;
313 }
314
323 test_reporter::operator<<(std::nullptr_t)
324 {
325 out_.append ("nullptr");
326 return *this;
327 }
328
338 test_reporter::operator<<(signed char c)
339 {
340 out_.append (std::to_string (c));
341 out_.append ("c");
342 return *this;
343 }
344
354 test_reporter::operator<<(unsigned char c)
355 {
356 out_.append (std::to_string (static_cast<int> (c)));
357 out_.append ("uc");
358 return *this;
359 }
360
370 test_reporter::operator<<(signed short v)
371 {
372 out_.append (std::to_string (v));
373 out_.append ("s");
374 return *this;
375 }
376
386 test_reporter::operator<<(unsigned short v)
387 {
388 out_.append (std::to_string (static_cast<long> (v)));
389 out_.append ("us");
390 return *this;
391 }
392
402 test_reporter::operator<<(signed int v)
403 {
404 out_.append (std::to_string (v));
405 return *this;
406 }
407
417 test_reporter::operator<<(unsigned int v)
418 {
419 out_.append (std::to_string (v));
420 out_.append ("u");
421 return *this;
422 }
423
433 test_reporter::operator<<(signed long v)
434 {
435 out_.append (std::to_string (v));
436 out_.append ("l");
437 return *this;
438 }
439
449 test_reporter::operator<<(unsigned long v)
450 {
451 out_.append (std::to_string (v));
452 out_.append ("ul");
453 return *this;
454 }
455
465 test_reporter::operator<<(signed long long v)
466 {
467 out_.append (std::to_string (v));
468 out_.append ("ll");
469 return *this;
470 }
471
481 test_reporter::operator<<(unsigned long long v)
482 {
483 out_.append (std::to_string (v));
484 out_.append ("ull");
485 return *this;
486 }
487
498 {
499 out_.append (std::to_string (v));
500 out_.append ("f");
501 return *this;
502 }
503
514 {
515 out_.append (std::to_string (v));
516 return *this;
517 }
518
529 test_reporter::operator<<(long double v)
530 {
531 out_.append (std::to_string (v));
532 out_.append ("l");
533 return *this;
534 }
535
547 void
548 test_reporter::begin_test_case ([[maybe_unused]] const char* name)
549 {
550 is_in_test_case_ = true;
551
552 if (!out_.empty () && (verbosity == verbosity::verbose))
553 {
555 {
556 printf ("\n");
557 }
558 output ();
559 add_empty_line = true;
560 }
561
562 out_.clear ();
563
564 flush ();
565 }
566
579 void
580 test_reporter::end_test_case ([[maybe_unused]] const char* name)
581 {
583 {
584 if (current_test_suite->current_test_case.failed_checks > 0)
585 {
586 if (true /* add_empty_line */)
587 {
588 printf ("\n");
589 }
590 printf (" • %s - test case started\n", name);
591 output ();
592 printf (
593 " %s✗%s %s - test case %sFAILED%s (%d %s passed, %d "
594 "failed)\n",
595 colors_.fail, colors_.none, name, colors_.fail, colors_.none,
596 current_test_suite->current_test_case.successful_checks,
597 current_test_suite->current_test_case.successful_checks == 1
598 ? "check"
599 : "checks",
600 current_test_suite->current_test_case.failed_checks);
601 add_empty_line = true;
602 }
603 else
604 {
606 {
607 printf ("\n");
608 }
610 {
611 printf (" • %s - test case started\n", name);
612 output ();
613 printf (
614 " %s✓%s %s - test case passed (%d %s)\n", colors_.pass,
615 colors_.none, name,
616 current_test_suite->current_test_case.successful_checks,
617 current_test_suite->current_test_case.successful_checks
618 == 1
619 ? "check"
620 : "checks");
621
622 add_empty_line = true;
623 }
624 else
625 {
626 printf (
627 " %s✓%s %s - test case passed (%d %s)\n", colors_.pass,
628 colors_.none, name,
629 current_test_suite->current_test_case.successful_checks,
630 current_test_suite->current_test_case.successful_checks
631 == 1
632 ? "check"
633 : "checks");
634
635 add_empty_line = false;
636 }
637 }
638 }
639
640 out_.clear ();
641 flush ();
642
643 is_in_test_case_ = false;
644 }
645
656 void
658 {
660 {
661 flush ();
662 printf ("\n");
663 }
664
666 {
667 add_empty_line = false;
668 return;
669 }
670
671 printf ("• %s - test suite started\n", name);
672
673 add_empty_line = true;
674 }
675
688 void
690 {
692 {
693 return;
694 }
695
696 if (suite.test_cases () > 0 && verbosity != verbosity::quiet)
697 {
698 printf ("\n");
699 add_empty_line = true;
700 }
701
702 // Also fail if none passed.
703 if (suite.failed_checks () == 0 && suite.successful_checks () != 0)
704 {
705 printf ("%s✓%s %s - test suite passed (%d %s in %d test %s)\n",
706 colors_.pass, colors_.none, suite.name (),
707 suite.successful_checks (),
708 suite.successful_checks () == 1 ? "check" : "checks",
709 suite.test_cases (),
710 suite.test_cases () == 1 ? "case" : "cases");
711 }
712 else
713 {
714 printf ("%s✗%s %s - test suite %sFAILED%s (%d %s passed, %d failed, "
715 "in %d test %s)\n",
716 colors_.fail, colors_.none, suite.name (), colors_.fail,
717 colors_.none, suite.successful_checks (),
718 suite.successful_checks () == 1 ? "check" : "checks",
719 suite.failed_checks (), suite.test_cases (),
720 suite.test_cases () == 1 ? "case" : "cases");
721 }
722 flush ();
723 }
724
734 void
736 {
737 printf ("%s", out_.c_str ()); // No `\n` here.
738 out_.clear ();
739 }
740
741 // --------------------------------------------------------------------------
742} // namespace micro_os_plus::micro_test_plus
743
744// ----------------------------------------------------------------------------

Generated via docusaurus-plugin-doxygen by Doxygen 1.14.0.