Skip to content

Commit d04c01c

Browse files
committed
De-duplicate logging of repeated Catch2 section names
Previously, for a Catch2 section hierarchy of: CATCH_SECTION("Section 1") CATCH_SECTION("Section 2") CATCH_SECTION("Section 3") CATCH_SECTION("Section 4") The libfly Catch2 reporter would display these sections as: [ Section 1 ] [ Section 2 ] [ Section 3 ] [ Section 1 ] [ Section 2 ] [ Section 4 ] It now tracks what higher-level sections is has already logged, and will indicate the depth of the current section: [ Section 1 ] [ └─➤ Section 2 ] [ └─➤ Section 3 ] [ └─➤ Section 4 ]
1 parent 00fe583 commit d04c01c

File tree

1 file changed

+59
-32
lines changed

1 file changed

+59
-32
lines changed

test/main.cpp

+59-32
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
#include "fly/logger/styler.hpp"
22
#include "fly/types/string/string.hpp"
33

4-
//clang-format off
4+
// clang-format off
55
// Due to a missing #include in catch_reporter_registrars.hpp, this must be included first.
66
#include "catch2/interfaces/catch_interfaces_reporter.hpp"
7-
//clang-format on
7+
// clang-format on
88

99
#include "catch2/catch_reporter_registrars.hpp"
1010
#include "catch2/catch_session.hpp"
1111
#include "catch2/catch_test_case_info.hpp"
1212
#include "catch2/reporters/catch_reporter_console.hpp"
1313

14+
#include <chrono>
15+
#include <cstdint>
16+
#include <string>
17+
#include <vector>
18+
1419
/**
1520
* A Catch2 test reporter for reporting colorful test and section names to console.
1621
*/
1722
class FlyReporter : public Catch::ConsoleReporter
1823
{
1924
public:
20-
FlyReporter(const Catch::ReporterConfig &config) : Catch::ConsoleReporter(config)
25+
explicit FlyReporter(const Catch::ReporterConfig &config) : Catch::ConsoleReporter(config)
2126
{
2227
}
2328

@@ -52,66 +57,88 @@ class FlyReporter : public Catch::ConsoleReporter
5257

5358
void testCaseStarting(const Catch::TestCaseInfo &info) override
5459
{
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-
5860
Catch::ConsoleReporter::testCaseStarting(info);
5961

62+
stream_header(fly::logger::Color::Green, fly::String::format("{} Test", info.name));
6063
m_current_test_case_start = std::chrono::steady_clock::now();
61-
m_current_test_case = info.name;
6264
}
6365

6466
void sectionStarting(const Catch::SectionInfo &info) override
6567
{
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)
6772
{
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;
7175
}
7276

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;
74102
}
75103

76104
void testCaseEnded(const Catch::TestCaseStats &stats) override
77105
{
106+
Catch::ConsoleReporter::testCaseEnded(stats);
107+
78108
const auto end = std::chrono::steady_clock::now();
79109
const auto duration = std::chrono::duration<double>(end - m_current_test_case_start);
80110

81111
const std::string &name = stats.testInfo->name;
82112

83113
if (stats.totals.assertions.allOk())
84114
{
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()));
93118
}
94119
else
95120
{
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()));
104124
}
105125

106-
Catch::ConsoleReporter::testCaseEnded(stats);
107-
m_current_test_case.clear();
126+
stream << '\n';
127+
m_sections.clear();
108128
}
109129

110130
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+
}
112136

137+
std::chrono::steady_clock::time_point m_test_start;
113138
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};
115142
};
116143

117144
CATCH_REGISTER_REPORTER("libfly", FlyReporter)

0 commit comments

Comments
 (0)