|
1 | 1 | #include "fly/logger/styler.hpp"
|
2 | 2 | #include "fly/types/string/string.hpp"
|
3 | 3 |
|
4 |
| -//clang-format off |
| 4 | +// clang-format off |
5 | 5 | // Due to a missing #include in catch_reporter_registrars.hpp, this must be included first.
|
6 | 6 | #include "catch2/interfaces/catch_interfaces_reporter.hpp"
|
7 |
| -//clang-format on |
| 7 | +// clang-format on |
8 | 8 |
|
9 | 9 | #include "catch2/catch_reporter_registrars.hpp"
|
10 | 10 | #include "catch2/catch_session.hpp"
|
11 | 11 | #include "catch2/catch_test_case_info.hpp"
|
12 | 12 | #include "catch2/reporters/catch_reporter_console.hpp"
|
13 | 13 |
|
| 14 | +#include <chrono> |
| 15 | +#include <cstdint> |
| 16 | +#include <string> |
| 17 | +#include <vector> |
| 18 | + |
14 | 19 | /**
|
15 | 20 | * A Catch2 test reporter for reporting colorful test and section names to console.
|
16 | 21 | */
|
17 | 22 | class FlyReporter : public Catch::ConsoleReporter
|
18 | 23 | {
|
19 | 24 | public:
|
20 |
| - FlyReporter(const Catch::ReporterConfig &config) : Catch::ConsoleReporter(config) |
| 25 | + explicit FlyReporter(const Catch::ReporterConfig &config) : Catch::ConsoleReporter(config) |
21 | 26 | {
|
22 | 27 | }
|
23 | 28 |
|
@@ -52,66 +57,88 @@ class FlyReporter : public Catch::ConsoleReporter
|
52 | 57 |
|
53 | 58 | void testCaseStarting(const Catch::TestCaseInfo &info) override
|
54 | 59 | {
|
55 |
| - const auto style = fly::logger::Styler(fly::logger::Style::Bold, fly::logger::Color::Green); |
56 |
| - stream << style << fly::String::format("[{:=>4}{} Test{:=<4}]\n", ' ', info.name, ' '); |
57 |
| - |
58 | 60 | Catch::ConsoleReporter::testCaseStarting(info);
|
59 | 61 |
|
| 62 | + stream_header(fly::logger::Color::Green, fly::String::format("{} Test", info.name)); |
60 | 63 | m_current_test_case_start = std::chrono::steady_clock::now();
|
61 |
| - m_current_test_case = info.name; |
62 | 64 | }
|
63 | 65 |
|
64 | 66 | void sectionStarting(const Catch::SectionInfo &info) override
|
65 | 67 | {
|
66 |
| - if (info.name != m_current_test_case) |
| 68 | + Catch::ConsoleReporter::sectionStarting(info); |
| 69 | + std::size_t level = m_section_level++; |
| 70 | + |
| 71 | + if (level == 0) |
67 | 72 | {
|
68 |
| - const auto style = |
69 |
| - fly::logger::Styler(fly::logger::Style::Italic, fly::logger::Color::Cyan); |
70 |
| - stream << style << fly::String::format("[ {} ]\n", info.name); |
| 73 | + m_sections.push_back(info.name); |
| 74 | + return; |
71 | 75 | }
|
72 | 76 |
|
73 |
| - Catch::ConsoleReporter::sectionStarting(info); |
| 77 | + auto path = fly::String::join('/', m_sections.back(), info.name); |
| 78 | + |
| 79 | + if (auto it = std::find(m_sections.begin(), m_sections.end(), path); it != m_sections.end()) |
| 80 | + { |
| 81 | + std::swap(*it, *(m_sections.end() - 1)); |
| 82 | + return; |
| 83 | + } |
| 84 | + |
| 85 | + const fly::logger::Styler style(fly::logger::Color::Cyan, fly::logger::Style::Italic); |
| 86 | + stream << style << "[ "; |
| 87 | + |
| 88 | + if (level != 1) |
| 89 | + { |
| 90 | + stream << fly::String::format("{: >{}}└─➤ ", "", (level - 2) * 4); |
| 91 | + } |
| 92 | + |
| 93 | + stream << fly::String::format("{} ]\n", info.name); |
| 94 | + |
| 95 | + m_sections.push_back(std::move(path)); |
| 96 | + } |
| 97 | + |
| 98 | + void sectionEnded(const Catch::SectionStats &stats) override |
| 99 | + { |
| 100 | + Catch::ConsoleReporter::sectionEnded(stats); |
| 101 | + --m_section_level; |
74 | 102 | }
|
75 | 103 |
|
76 | 104 | void testCaseEnded(const Catch::TestCaseStats &stats) override
|
77 | 105 | {
|
| 106 | + Catch::ConsoleReporter::testCaseEnded(stats); |
| 107 | + |
78 | 108 | const auto end = std::chrono::steady_clock::now();
|
79 | 109 | const auto duration = std::chrono::duration<double>(end - m_current_test_case_start);
|
80 | 110 |
|
81 | 111 | const std::string &name = stats.testInfo->name;
|
82 | 112 |
|
83 | 113 | if (stats.totals.assertions.allOk())
|
84 | 114 | {
|
85 |
| - const auto style = |
86 |
| - fly::logger::Styler(fly::logger::Style::Bold, fly::logger::Color::Green); |
87 |
| - stream << style; |
88 |
| - |
89 |
| - stream << fly::String::format( |
90 |
| - "[==== PASSED {} ({:.3f} seconds) ====]\n\n", |
91 |
| - name, |
92 |
| - duration.count()); |
| 115 | + stream_header( |
| 116 | + fly::logger::Color::Green, |
| 117 | + fly::String::format("PASSED {} ({:.3f} seconds)", name, duration.count())); |
93 | 118 | }
|
94 | 119 | else
|
95 | 120 | {
|
96 |
| - const auto style = |
97 |
| - fly::logger::Styler(fly::logger::Style::Bold, fly::logger::Color::Red); |
98 |
| - stream << style; |
99 |
| - |
100 |
| - stream << fly::String::format( |
101 |
| - "[==== FAILED {} ({:.3f} seconds) ====]\n\n", |
102 |
| - name, |
103 |
| - duration.count()); |
| 121 | + stream_header( |
| 122 | + fly::logger::Color::Red, |
| 123 | + fly::String::format("FAILED {} ({:.3f} seconds)", name, duration.count())); |
104 | 124 | }
|
105 | 125 |
|
106 |
| - Catch::ConsoleReporter::testCaseEnded(stats); |
107 |
| - m_current_test_case.clear(); |
| 126 | + stream << '\n'; |
| 127 | + m_sections.clear(); |
108 | 128 | }
|
109 | 129 |
|
110 | 130 | private:
|
111 |
| - std::chrono::steady_clock::time_point m_test_start; |
| 131 | + void stream_header(fly::logger::Color::StandardColor color, std::string message) |
| 132 | + { |
| 133 | + stream << fly::logger::Styler(fly::logger::Style::Bold, color) |
| 134 | + << fly::String::format("[==== {} ====]\n", message); |
| 135 | + } |
112 | 136 |
|
| 137 | + std::chrono::steady_clock::time_point m_test_start; |
113 | 138 | std::chrono::steady_clock::time_point m_current_test_case_start;
|
114 |
| - std::string m_current_test_case; |
| 139 | + |
| 140 | + std::vector<std::string> m_sections; |
| 141 | + std::size_t m_section_level {0}; |
115 | 142 | };
|
116 | 143 |
|
117 | 144 | CATCH_REGISTER_REPORTER("libfly", FlyReporter)
|
|
0 commit comments