mirror of https://github.com/catchorg/Catch2.git
Use new line wrapper to show test case list, with tags, in columns
This commit is contained in:
parent
9e8abc33e7
commit
15fd032608
|
@ -174,9 +174,9 @@
|
|||
#else
|
||||
#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
|
||||
#endif
|
||||
#define GIVEN( desc ) SECTION( "Given: " desc, "" )
|
||||
#define GIVEN( desc ) SECTION( " Given: " desc, "" )
|
||||
#define WHEN( desc ) SECTION( " When: " desc, "" )
|
||||
#define AND_WHEN( desc ) SECTION( " And: " desc, "" )
|
||||
#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
|
||||
#define THEN( desc ) SECTION( " Then: " desc, "" )
|
||||
#define AND_THEN( desc ) SECTION( " And: " desc, "" )
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace Catch {
|
|||
|
||||
// Handle list request
|
||||
if( config.listSpec != List::None ) {
|
||||
List( config );
|
||||
list( config );
|
||||
Catch::cleanUp();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace Catch {
|
|||
|
||||
class LineWrapper {
|
||||
public:
|
||||
LineWrapper( std::size_t _right );
|
||||
LineWrapper();
|
||||
|
||||
LineWrapper& setIndent( std::size_t _indent );
|
||||
|
@ -29,17 +28,22 @@ namespace Catch {
|
|||
|
||||
const_iterator begin() const { return lines.begin(); }
|
||||
const_iterator end() const { return lines.end(); }
|
||||
std::size_t size() const { return lines.size(); }
|
||||
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
|
||||
|
||||
friend std::ostream& operator << ( std::ostream& _stream, LineWrapper const& _lineWrapper );
|
||||
|
||||
private:
|
||||
void wrapInternal( std::string const& _str );
|
||||
void addLine( const std::string& _line );
|
||||
bool isWrapPoint( char c );
|
||||
|
||||
std::string indent;
|
||||
std::size_t right;
|
||||
std::size_t nextTab;
|
||||
std::size_t tab;
|
||||
std::string wrappableChars;
|
||||
int recursionCount;
|
||||
std::vector<std::string> lines;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,15 +12,12 @@
|
|||
|
||||
namespace Catch {
|
||||
|
||||
LineWrapper::LineWrapper( std::size_t _right )
|
||||
: right( _right ),
|
||||
nextTab( 0 ),
|
||||
tab( 0 )
|
||||
{}
|
||||
LineWrapper::LineWrapper()
|
||||
: right( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
|
||||
nextTab( 0 ),
|
||||
tab( 0 )
|
||||
tab( 0 ),
|
||||
wrappableChars( " [({.," ),
|
||||
recursionCount( 0 )
|
||||
{}
|
||||
|
||||
LineWrapper& LineWrapper::setIndent( std::size_t _indent ) {
|
||||
|
@ -36,7 +33,12 @@ namespace Catch {
|
|||
wrapInternal( _str );
|
||||
return *this;
|
||||
}
|
||||
bool LineWrapper::isWrapPoint( char c ) {
|
||||
return wrappableChars.find( c ) != std::string::npos;
|
||||
}
|
||||
void LineWrapper::wrapInternal( std::string const& _str ) {
|
||||
assert( ++recursionCount < 100 );
|
||||
|
||||
std::size_t width = right - indent.size();
|
||||
std::size_t wrapPoint = width-tab;
|
||||
for( std::size_t pos = 0; pos < _str.size(); ++pos ) {
|
||||
|
@ -51,6 +53,9 @@ namespace Catch {
|
|||
addLine( _str.substr( 0, wrapPoint ) );
|
||||
while( _str[++wrapPoint] == ' ' );
|
||||
}
|
||||
else if( isWrapPoint( _str[wrapPoint] ) ) {
|
||||
addLine( _str.substr( 0, wrapPoint ) );
|
||||
}
|
||||
else {
|
||||
addLine( _str.substr( 0, --wrapPoint ) + '-' );
|
||||
}
|
||||
|
@ -61,7 +66,7 @@ namespace Catch {
|
|||
std::string withoutTab = _str.substr( 0, nextTab ) + _str.substr( nextTab+1 );
|
||||
return wrapInternal( withoutTab );
|
||||
}
|
||||
else if( _str[pos] == ' ' ) {
|
||||
else if( isWrapPoint( _str[pos] ) ) {
|
||||
wrapPoint = pos;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
|
||||
|
||||
#include "catch_commandline.hpp"
|
||||
#include "catch_line_wrap.h"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Catch {
|
||||
inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCase& testCase ) {
|
||||
|
@ -20,34 +23,54 @@ namespace Catch {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
inline void List( const ConfigData& config ) {
|
||||
|
||||
if( config.listSpec & List::Reports ) {
|
||||
std::cout << "Available reports:\n";
|
||||
IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
|
||||
IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
|
||||
for(; it != itEnd; ++it ) {
|
||||
// !TBD: consider listAs()
|
||||
std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
if( config.listSpec & List::Tests ) {
|
||||
inline void listTests( const ConfigData& config ) {
|
||||
if( config.filters.empty() )
|
||||
std::cout << "All available test cases:\n";
|
||||
else
|
||||
std::cout << "Matching test cases:\n";
|
||||
std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
|
||||
std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
|
||||
std::size_t matchedTests = 0;
|
||||
std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
|
||||
std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
|
||||
|
||||
// First pass - get max tags
|
||||
std::size_t maxTagLen = 0;
|
||||
std::size_t maxNameLen = 0;
|
||||
for(; it != itEnd; ++it ) {
|
||||
maxTagLen = (std::max)( it->getTestCaseInfo().tagsAsString.size(), maxTagLen );
|
||||
maxNameLen = (std::max)( it->getTestCaseInfo().name.size(), maxNameLen );
|
||||
}
|
||||
|
||||
// Try to fit everything in. If not shrink tag column first, down to 30
|
||||
// then shrink name column until it all fits (strings will be wrapped within column)
|
||||
while( maxTagLen + maxNameLen > CATCH_CONFIG_CONSOLE_WIDTH-5 ) {
|
||||
if( maxTagLen > 30 )
|
||||
--maxTagLen;
|
||||
else
|
||||
--maxNameLen;
|
||||
}
|
||||
|
||||
std::size_t matchedTests = 0;
|
||||
for( it = allTests.begin(); it != itEnd; ++it ) {
|
||||
if( matchesFilters( config.filters, *it ) ) {
|
||||
matchedTests++;
|
||||
// !TBD: consider listAs()
|
||||
std::cout << " " << it->getTestCaseInfo().name << "\n";
|
||||
if( ( config.listSpec & List::TestNames ) != List::TestNames )
|
||||
std::cout << " '" << it->getTestCaseInfo().description << "'\n";
|
||||
LineWrapper nameWrapper;
|
||||
nameWrapper.setRight( maxNameLen ).setIndent( 2 ).wrap( it->getTestCaseInfo().name );
|
||||
|
||||
LineWrapper tagsWrapper;
|
||||
tagsWrapper.setRight( maxTagLen ).wrap( it->getTestCaseInfo().tagsAsString );
|
||||
|
||||
for( std::size_t i = 0; i < std::max( nameWrapper.size(), tagsWrapper.size() ); ++i ) {
|
||||
std::string nameCol;
|
||||
if( i < nameWrapper.size() )
|
||||
nameCol = nameWrapper[i];
|
||||
else
|
||||
nameCol = " ...";
|
||||
std::cout << nameCol << " " << std::string( maxNameLen - nameCol.size(), ' ' );
|
||||
if( i < tagsWrapper.size() )
|
||||
std::cout << tagsWrapper[i];
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if( config.filters.empty() )
|
||||
|
@ -56,11 +79,24 @@ namespace Catch {
|
|||
std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
|
||||
}
|
||||
|
||||
if( ( config.listSpec & List::All ) == 0 ) {
|
||||
std::ostringstream oss;
|
||||
oss << "Unknown list type";
|
||||
throw std::domain_error( oss.str() );
|
||||
inline void listReporters( const ConfigData& /*config*/ ) {
|
||||
std::cout << "Available reports:\n";
|
||||
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
|
||||
IReporterRegistry::FactoryMap::const_iterator it = factories.begin(), itEnd = factories.end();
|
||||
for(; it != itEnd; ++it ) {
|
||||
// !TBD: consider listAs()
|
||||
std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
inline void list( const ConfigData& config ) {
|
||||
if( config.listSpec & List::Tests )
|
||||
listTests( config );
|
||||
else if( config.listSpec & List::Reports )
|
||||
listReporters( config );
|
||||
else
|
||||
throw std::logic_error( "Unknown list type" );
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace Catch {
|
|||
std::string className;
|
||||
std::string description;
|
||||
std::set<std::string> tags;
|
||||
std::string tagsAsString;
|
||||
SourceLineInfo lineInfo;
|
||||
bool isHidden;
|
||||
};
|
||||
|
|
|
@ -44,13 +44,19 @@ namespace Catch {
|
|||
tags( _tags ),
|
||||
lineInfo( _lineInfo ),
|
||||
isHidden( _isHidden )
|
||||
{}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it )
|
||||
oss << "[" << *it << "]";
|
||||
tagsAsString = oss.str();
|
||||
}
|
||||
|
||||
TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
|
||||
: name( other.name ),
|
||||
className( other.className ),
|
||||
description( other.description ),
|
||||
tags( other.tags ),
|
||||
tagsAsString( other.tagsAsString ),
|
||||
lineInfo( other.lineInfo ),
|
||||
isHidden( other.isHidden )
|
||||
{}
|
||||
|
|
|
@ -432,31 +432,40 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
|
|||
std::string testString = "one two three four";
|
||||
|
||||
SECTION( "No wrapping", "" ) {
|
||||
CHECK( Catch::LineWrapper( 80 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper( 18 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper().setRight( 80 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper().setRight( 18 ).wrap( testString ).toString() == testString );
|
||||
}
|
||||
SECTION( "Wrapped once", "" ) {
|
||||
CHECK( Catch::LineWrapper( 17 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper( 16 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper( 15 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper( 14 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper( 13 ).wrap( testString ).toString() == "one two\nthree four" );
|
||||
CHECK( Catch::LineWrapper().setRight( 17 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 16 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 15 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 14 ).wrap( testString ).toString() == "one two three\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 13 ).wrap( testString ).toString() == "one two\nthree four" );
|
||||
}
|
||||
SECTION( "Wrapped twice", "" ) {
|
||||
CHECK( Catch::LineWrapper( 9 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper( 8 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 9 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 8 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
}
|
||||
SECTION( "Wrapped three times", "" ) {
|
||||
CHECK( Catch::LineWrapper( 7 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper( 5 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 7 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 5 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
|
||||
}
|
||||
SECTION( "Short wrap", "" ) {
|
||||
CHECK( Catch::LineWrapper( 4 ).wrap( "abcdef" ).toString() == "abc-\ndef" );
|
||||
CHECK( Catch::LineWrapper( 4 ).wrap( "abcdefg" ).toString() == "abc-\ndefg" );
|
||||
CHECK( Catch::LineWrapper( 4 ).wrap("abcdefgh" ).toString() == "abc-\ndef-\ngh" );
|
||||
CHECK( Catch::LineWrapper().setRight( 4 ).wrap( "abcdef" ).toString() == "abc-\ndef" );
|
||||
CHECK( Catch::LineWrapper().setRight( 4 ).wrap( "abcdefg" ).toString() == "abc-\ndefg" );
|
||||
CHECK( Catch::LineWrapper().setRight( 4 ).wrap("abcdefgh" ).toString() == "abc-\ndef-\ngh" );
|
||||
|
||||
CHECK( Catch::LineWrapper( 4 ).wrap( testString ).toString() == "one\ntwo\nthr-\nee\nfour" );
|
||||
CHECK( Catch::LineWrapper( 3 ).wrap( testString ).toString() == "one\ntwo\nth-\nree\nfo-\nur" );
|
||||
CHECK( Catch::LineWrapper().setRight( 4 ).wrap( testString ).toString() == "one\ntwo\nthr-\nee\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 3 ).wrap( testString ).toString() == "one\ntwo\nth-\nree\nfo-\nur" );
|
||||
}
|
||||
SECTION( "As container", "" ) {
|
||||
Catch::LineWrapper wrapper;
|
||||
wrapper.setRight( 7 ).wrap( testString );
|
||||
CHECK( wrapper.size() == 4 );
|
||||
CHECK( wrapper[0] == "one" );
|
||||
CHECK( wrapper[1] == "two" );
|
||||
CHECK( wrapper[2] == "three" );
|
||||
CHECK( wrapper[3] == "four" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,22 +475,22 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
|
|||
std::string testString = "one two\nthree four";
|
||||
|
||||
SECTION( "No wrapping" , "" ) {
|
||||
CHECK( Catch::LineWrapper( 80 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper( 18 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper( 10 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper().setRight( 80 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper().setRight( 18 ).wrap( testString ).toString() == testString );
|
||||
CHECK( Catch::LineWrapper().setRight( 10 ).wrap( testString ).toString() == testString );
|
||||
}
|
||||
SECTION( "Trailing newline" , "" ) {
|
||||
CHECK( Catch::LineWrapper( 10 ).wrap( "abcdef\n" ).toString() == "abcdef\n" );
|
||||
CHECK( Catch::LineWrapper( 6 ).wrap( "abcdef" ).toString() == "abcdef" );
|
||||
CHECK( Catch::LineWrapper( 6 ).wrap( "abcdef\n" ).toString() == "abcdef\n" );
|
||||
CHECK( Catch::LineWrapper().setRight( 10 ).wrap( "abcdef\n" ).toString() == "abcdef\n" );
|
||||
CHECK( Catch::LineWrapper().setRight( 6 ).wrap( "abcdef" ).toString() == "abcdef" );
|
||||
CHECK( Catch::LineWrapper().setRight( 6 ).wrap( "abcdef\n" ).toString() == "abcdef\n" );
|
||||
}
|
||||
SECTION( "Wrapped once", "" ) {
|
||||
CHECK( Catch::LineWrapper( 9 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper( 8 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper( 7 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 9 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 8 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 7 ).wrap( testString ).toString() == "one two\nthree\nfour" );
|
||||
}
|
||||
SECTION( "Wrapped twice", "" ) {
|
||||
CHECK( Catch::LineWrapper( 6 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
|
||||
CHECK( Catch::LineWrapper().setRight( 6 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue