mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 13:26:10 +01:00
Extract the default listing implementation out of reporter interface
Also generalized the implementations to write to the provided output stream, which will be required for the follow up changes, where the listings should happen to the location user asked for by specifying the `-o` flag.
This commit is contained in:
parent
7111b2a8e2
commit
6798c139a6
@ -11,34 +11,15 @@
|
||||
#include <catch2/internal/catch_console_width.hpp>
|
||||
#include <catch2/catch_message.hpp>
|
||||
#include <catch2/internal/catch_list.hpp>
|
||||
#include <catch2/internal/catch_textflow.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/internal/catch_textflow.hpp>
|
||||
#include <catch2/reporters/catch_reporter_helpers.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
void listTestNamesOnly( std::vector<TestCaseHandle> const& tests ) {
|
||||
for ( auto const& test : tests ) {
|
||||
auto const& testCaseInfo = test.getTestCaseInfo();
|
||||
|
||||
if ( startsWith( testCaseInfo.name, '#' ) ) {
|
||||
Catch::cout() << '"' << testCaseInfo.name << '"';
|
||||
} else {
|
||||
Catch::cout() << testCaseInfo.name;
|
||||
}
|
||||
|
||||
Catch::cout() << '\n';
|
||||
}
|
||||
Catch::cout() << std::flush;
|
||||
}
|
||||
} // end unnamed namespace
|
||||
|
||||
|
||||
ReporterConfig::ReporterConfig( IConfig const* _fullConfig )
|
||||
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
|
||||
|
||||
@ -128,89 +109,19 @@ namespace Catch {
|
||||
void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
|
||||
|
||||
void IStreamingReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
|
||||
Catch::cout() << "Available reporters:\n";
|
||||
const auto maxNameLen = std::max_element(descriptions.begin(), descriptions.end(),
|
||||
[](ReporterDescription const& lhs, ReporterDescription const& rhs) { return lhs.name.size() < rhs.name.size(); })
|
||||
->name.size();
|
||||
|
||||
for (auto const& desc : descriptions) {
|
||||
if (m_config->verbosity() == Verbosity::Quiet) {
|
||||
Catch::cout()
|
||||
<< TextFlow::Column(desc.name)
|
||||
.indent(2)
|
||||
.width(5 + maxNameLen) << '\n';
|
||||
} else {
|
||||
Catch::cout()
|
||||
<< TextFlow::Column(desc.name + ":")
|
||||
.indent(2)
|
||||
.width(5 + maxNameLen)
|
||||
+ TextFlow::Column(desc.description)
|
||||
.initialIndent(0)
|
||||
.indent(2)
|
||||
.width(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8)
|
||||
<< '\n';
|
||||
}
|
||||
}
|
||||
Catch::cout() << std::endl;
|
||||
defaultListReporters(
|
||||
Catch::cout(), descriptions, m_config->verbosity() );
|
||||
}
|
||||
|
||||
void IStreamingReporter::listTests(std::vector<TestCaseHandle> const& tests) {
|
||||
// We special case this to provide the equivalent of old
|
||||
// `--list-test-names-only`, which could then be used by the
|
||||
// `--input-file` option.
|
||||
if (m_config->verbosity() == Verbosity::Quiet) {
|
||||
listTestNamesOnly(tests);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_config->hasTestFilters()) {
|
||||
Catch::cout() << "Matching test cases:\n";
|
||||
} else {
|
||||
Catch::cout() << "All available test cases:\n";
|
||||
}
|
||||
|
||||
for (auto const& test : tests) {
|
||||
auto const& testCaseInfo = test.getTestCaseInfo();
|
||||
Colour::Code colour = testCaseInfo.isHidden()
|
||||
? Colour::SecondaryText
|
||||
: Colour::None;
|
||||
Colour colourGuard(colour);
|
||||
|
||||
Catch::cout() << TextFlow::Column(testCaseInfo.name).initialIndent(2).indent(4) << '\n';
|
||||
if (m_config->verbosity() >= Verbosity::High) {
|
||||
Catch::cout() << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << std::endl;
|
||||
}
|
||||
if ( !testCaseInfo.tags.empty() &&
|
||||
m_config->verbosity() > Verbosity::Quiet ) {
|
||||
Catch::cout() << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config->hasTestFilters()) {
|
||||
Catch::cout() << pluralise(tests.size(), "matching test case") << '\n' << std::endl;
|
||||
} else {
|
||||
Catch::cout() << pluralise(tests.size(), "test case") << '\n' << std::endl;
|
||||
}
|
||||
defaultListTests( Catch::cout(),
|
||||
tests,
|
||||
m_config->hasTestFilters(),
|
||||
m_config->verbosity() );
|
||||
}
|
||||
|
||||
void IStreamingReporter::listTags(std::vector<TagInfo> const& tags) {
|
||||
if (m_config->hasTestFilters()) {
|
||||
Catch::cout() << "Tags for matching test cases:\n";
|
||||
} else {
|
||||
Catch::cout() << "All available tags:\n";
|
||||
}
|
||||
|
||||
for (auto const& tagCount : tags) {
|
||||
ReusableStringStream rss;
|
||||
rss << " " << std::setw(2) << tagCount.count << " ";
|
||||
auto str = rss.str();
|
||||
auto wrapper = TextFlow::Column(tagCount.all())
|
||||
.initialIndent(0)
|
||||
.indent(str.size())
|
||||
.width(CATCH_CONFIG_CONSOLE_WIDTH - 10);
|
||||
Catch::cout() << str << wrapper << '\n';
|
||||
}
|
||||
Catch::cout() << pluralise(tags.size(), "tag") << '\n' << std::endl;
|
||||
defaultListTags( Catch::cout(), tags, m_config->hasTestFilters() );
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
@ -21,13 +21,40 @@
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/internal/catch_console_width.hpp>
|
||||
#include <catch2/internal/catch_errno_guard.hpp>
|
||||
#include <catch2/internal/catch_textflow.hpp>
|
||||
#include <catch2/internal/catch_stream.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <catch2/catch_tostring.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <cstdio>
|
||||
#include <ostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
void listTestNamesOnly(std::ostream& out,
|
||||
std::vector<TestCaseHandle> const& tests) {
|
||||
for (auto const& test : tests) {
|
||||
auto const& testCaseInfo = test.getTestCaseInfo();
|
||||
|
||||
if (startsWith(testCaseInfo.name, '#')) {
|
||||
out << '"' << testCaseInfo.name << '"';
|
||||
} else {
|
||||
out << testCaseInfo.name;
|
||||
}
|
||||
|
||||
out << '\n';
|
||||
}
|
||||
out << std::flush;
|
||||
}
|
||||
} // end unnamed namespace
|
||||
|
||||
|
||||
// Because formatting using c++ streams is stateful, drop down to C is
|
||||
// required Alternatively we could use stringstream, but its performance
|
||||
// is... not good.
|
||||
@ -89,6 +116,101 @@ namespace Catch {
|
||||
return out;
|
||||
}
|
||||
|
||||
void
|
||||
defaultListReporters( std::ostream& out,
|
||||
std::vector<ReporterDescription> const& descriptions,
|
||||
Verbosity verbosity ) {
|
||||
out << "Available reporters:\n";
|
||||
const auto maxNameLen =
|
||||
std::max_element( descriptions.begin(),
|
||||
descriptions.end(),
|
||||
[]( ReporterDescription const& lhs,
|
||||
ReporterDescription const& rhs ) {
|
||||
return lhs.name.size() < rhs.name.size();
|
||||
} )
|
||||
->name.size();
|
||||
|
||||
for ( auto const& desc : descriptions ) {
|
||||
if ( verbosity == Verbosity::Quiet ) {
|
||||
out << TextFlow::Column( desc.name )
|
||||
.indent( 2 )
|
||||
.width( 5 + maxNameLen )
|
||||
<< '\n';
|
||||
} else {
|
||||
out << TextFlow::Column( desc.name + ":" )
|
||||
.indent( 2 )
|
||||
.width( 5 + maxNameLen ) +
|
||||
TextFlow::Column( desc.description )
|
||||
.initialIndent( 0 )
|
||||
.indent( 2 )
|
||||
.width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
|
||||
<< '\n';
|
||||
}
|
||||
}
|
||||
out << '\n' << std::flush;
|
||||
}
|
||||
|
||||
void defaultListTags( std::ostream& out,
|
||||
std::vector<TagInfo> const& tags,
|
||||
bool isFiltered ) {
|
||||
if ( isFiltered ) {
|
||||
out << "Tags for matching test cases:\n";
|
||||
} else {
|
||||
out << "All available tags:\n";
|
||||
}
|
||||
|
||||
for ( auto const& tagCount : tags ) {
|
||||
ReusableStringStream rss;
|
||||
rss << " " << std::setw( 2 ) << tagCount.count << " ";
|
||||
auto str = rss.str();
|
||||
auto wrapper = TextFlow::Column( tagCount.all() )
|
||||
.initialIndent( 0 )
|
||||
.indent( str.size() )
|
||||
.width( CATCH_CONFIG_CONSOLE_WIDTH - 10 );
|
||||
out << str << wrapper << '\n';
|
||||
}
|
||||
out << pluralise( tags.size(), "tag" ) << '\n' << std::endl;
|
||||
}
|
||||
|
||||
void defaultListTests(std::ostream& out, std::vector<TestCaseHandle> const& tests, bool isFiltered, Verbosity verbosity) {
|
||||
// We special case this to provide the equivalent of old
|
||||
// `--list-test-names-only`, which could then be used by the
|
||||
// `--input-file` option.
|
||||
if (verbosity == Verbosity::Quiet) {
|
||||
listTestNamesOnly(out, tests);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFiltered) {
|
||||
out << "Matching test cases:\n";
|
||||
} else {
|
||||
out << "All available test cases:\n";
|
||||
}
|
||||
|
||||
for (auto const& test : tests) {
|
||||
auto const& testCaseInfo = test.getTestCaseInfo();
|
||||
Colour::Code colour = testCaseInfo.isHidden()
|
||||
? Colour::SecondaryText
|
||||
: Colour::None;
|
||||
Colour colourGuard(colour);
|
||||
|
||||
out << TextFlow::Column(testCaseInfo.name).initialIndent(2).indent(4) << '\n';
|
||||
if (verbosity >= Verbosity::High) {
|
||||
out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << std::endl;
|
||||
}
|
||||
if (!testCaseInfo.tags.empty() &&
|
||||
verbosity > Verbosity::Quiet) {
|
||||
out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (isFiltered) {
|
||||
out << pluralise(tests.size(), "matching test case") << '\n' << std::endl;
|
||||
} else {
|
||||
out << pluralise(tests.size(), "test case") << '\n' << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
|
||||
|
@ -12,9 +12,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <catch2/internal/catch_list.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct IConfig;
|
||||
class TestCaseHandle;
|
||||
|
||||
// Returns double formatted as %.3f (format expected on output)
|
||||
std::string getFormattedDuration( double duration );
|
||||
@ -31,6 +35,42 @@ namespace Catch {
|
||||
friend std::ostream& operator<<( std::ostream& out, lineOfChars value );
|
||||
};
|
||||
|
||||
/**
|
||||
* Lists reporter descriptions to the provided stream in user-friendly
|
||||
* format
|
||||
*
|
||||
* Used as the default listing implementation by the first party reporter
|
||||
* bases. The output should be backwards compatible with the output of
|
||||
* Catch2 v2 binaries.
|
||||
*/
|
||||
void
|
||||
defaultListReporters( std::ostream& out,
|
||||
std::vector<ReporterDescription> const& descriptions,
|
||||
Verbosity verbosity );
|
||||
|
||||
/**
|
||||
* Lists tag information to the provided stream in user-friendly format
|
||||
*
|
||||
* Used as the default listing implementation by the first party reporter
|
||||
* bases. The output should be backwards compatible with the output of
|
||||
* Catch2 v2 binaries.
|
||||
*/
|
||||
void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
|
||||
|
||||
/**
|
||||
* Lists test case information to the provided stream in user-friendly
|
||||
* format
|
||||
*
|
||||
* Used as the default listing implementation by the first party reporter
|
||||
* bases. The output is backwards compatible with the output of Catch2
|
||||
* v2 binaries, and also supports the format specific to the old
|
||||
* `--list-test-names-only` option, for people who used it in integrations.
|
||||
*/
|
||||
void defaultListTests( std::ostream& out,
|
||||
std::vector<TestCaseHandle> const& tests,
|
||||
bool isFiltered,
|
||||
Verbosity verbosity );
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED
|
||||
|
Loading…
Reference in New Issue
Block a user