diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index ee19de85..c0dbe348 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -40,6 +40,10 @@ namespace Catch { ? ShowDurations::Always : ShowDurations::Never; } + inline void setShowDurationsThreshold( ConfigData& config, double _showDurationsThreshold ) { + config.showDurations = ShowDurations::Threshold; + config.showDurationsThreshold = _showDurationsThreshold; + } inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { std::ifstream f( _filename.c_str() ); if( !f.is_open() ) @@ -142,6 +146,12 @@ namespace Catch { .longOpt( "durations" ) .hint( "yes/no" ); + cli.bind( &setShowDurationsThreshold ) + .describe( "show test durations only if exceeding this threshold" ) + .shortOpt( "q") + .longOpt( "durations-threshold" ) + .hint( "seconds" ); + cli.bind( &loadTestNamesFromFile ) .describe( "load test names to run from a file" ) .shortOpt( "f") diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 30cd34b9..4fb00e33 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -38,7 +38,8 @@ namespace Catch { abortAfter( -1 ), verbosity( Verbosity::Normal ), warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ) + showDurations( ShowDurations::DefaultForReporter ), + showDurationsThreshold( 0.0 ) {} bool listTests; @@ -56,6 +57,7 @@ namespace Catch { Verbosity::Level verbosity; WarnAbout::What warnings; ShowDurations::OrNot showDurations; + double showDurationsThreshold; std::string reporterName; std::string outputFilename; @@ -162,7 +164,7 @@ namespace Catch { virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - + virtual double showDurationsThreshold() const { return m_data.showDurationsThreshold; } private: ConfigData m_data; diff --git a/include/internal/catch_console_colour.hpp b/include/internal/catch_console_colour.hpp index 3fc2e38b..5bddd39f 100644 --- a/include/internal/catch_console_colour.hpp +++ b/include/internal/catch_console_colour.hpp @@ -47,6 +47,8 @@ namespace Catch { ReconstructedExpression = Yellow, SecondaryText = LightGrey, + DurationText = Yellow, + Headers = White }; diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index 79cfa97b..5d0a9e4a 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -29,7 +29,8 @@ namespace Catch { struct ShowDurations { enum OrNot { DefaultForReporter, Always, - Never + Never, + Threshold }; }; struct IConfig : IShared { @@ -44,6 +45,7 @@ namespace Catch { virtual bool warnAboutMissingAssertions() const = 0; virtual int abortAfter() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; + virtual double showDurationsThreshold() const = 0; }; } diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index eafaaa3a..8421ce47 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -167,20 +167,18 @@ namespace Catch struct TestRunStats { TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, + double _durationInSeconds, bool _aborting ) : runInfo( _runInfo ), totals( _totals ), + durationInSeconds( _durationInSeconds ), aborting( _aborting ) {} - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} virtual ~TestRunStats(); TestRunInfo runInfo; Totals totals; + double durationInSeconds; bool aborting; }; diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 4b34f1e9..6d306d89 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -71,10 +71,11 @@ namespace Catch { m_context.setConfig( m_config ); m_context.setResultCapture( this ); m_reporter->testRunStarting( m_runInfo ); + m_timer.start(); } virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, m_timer.getElapsedSeconds(), aborting() ) ); m_context.setRunner( m_prevRunner ); m_context.setConfig( NULL ); m_context.setResultCapture( m_prevResultCapture ); @@ -329,6 +330,8 @@ namespace Catch { Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; + + Timer m_timer; }; } // end namespace Catch diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index 60ada648..97ffb626 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -15,6 +15,19 @@ namespace Catch { + static bool shouldPrintDuration( + Ptr const& config, + double durationInSeconds + ) { + switch( config->showDurations() ) { + case ShowDurations::Always: return true; + case ShowDurations::Threshold: return (durationInSeconds >= config->showDurationsThreshold()); + case ShowDurations::DefaultForReporter: + case ShowDurations::Never: + default: return false; + } + } + struct ConsoleReporter : StreamingReporterBase { ConsoleReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), @@ -73,14 +86,19 @@ namespace Catch { stream << "\nNo assertions in test case"; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; } + if( m_headerPrinted ) { - if( m_config->showDurations() == ShowDurations::Always ) + if( shouldPrintDuration(m_config, _sectionStats.durationInSeconds) ) { + Colour colour( Colour::DurationText ); stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } m_headerPrinted = false; } else { - if( m_config->showDurations() == ShowDurations::Always ) - stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + if( shouldPrintDuration(m_config, _sectionStats.durationInSeconds) ) { + Colour colour( Colour::DurationText ); + stream << " '" << _sectionStats.sectionInfo.name << "' completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } } StreamingReporterBase::sectionEnded( _sectionStats ); } @@ -102,7 +120,15 @@ namespace Catch { if( m_atLeastOneTestCasePrinted ) printTotalsDivider(); printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; + stream << "\n"; + + if( shouldPrintDuration(m_config, _testRunStats.durationInSeconds) ) { + Colour colour( Colour::DurationText ); + stream << "All test runs completed in " << _testRunStats.durationInSeconds << "s\n"; + } + + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); }