mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Added cutoff option to command line
Aborts testing after a certain number of assertion failures
This commit is contained in:
		| @@ -52,7 +52,8 @@ inline bool isTrue( bool value ){ return value; } | ||||
| #define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \ | ||||
|     if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr )  ) \ | ||||
|     { \ | ||||
|         if( internal_catch_action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \ | ||||
|         if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \ | ||||
|         if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ | ||||
|         if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \ | ||||
|         if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \ | ||||
|     } | ||||
|   | ||||
| @@ -161,6 +161,19 @@ namespace Catch { | ||||
|                     throw std::domain_error( cmd.name() + " does not accept arguments" ); | ||||
|                 config.setShowHelp( true ); | ||||
|             } | ||||
|  | ||||
|             if( Command cmd = parser.find( "-c", "--cutoff" ) ) { | ||||
|                 if( cmd.argsCount() > 1 ) | ||||
|                     throw std::domain_error( cmd.name() + " only accepts 0-1 arguments" ); | ||||
|                 int threshold = 1; | ||||
|                 if( cmd.argsCount() == 1 ) | ||||
|                 { | ||||
|                     std::stringstream ss; | ||||
|                     ss << cmd[0]; | ||||
|                     ss >> threshold; | ||||
|                 } | ||||
|                 config.setCutoff( threshold ); | ||||
|             } | ||||
|         } | ||||
|         catch( std::exception& ex ) { | ||||
|             config.setError( ex.what() ); | ||||
|   | ||||
| @@ -50,7 +50,8 @@ namespace Catch { | ||||
|             m_showHelp( false ), | ||||
|             m_streambuf( NULL ), | ||||
|             m_os( std::cout.rdbuf() ), | ||||
|             m_includeWhichResults( Include::FailedOnly ) | ||||
|             m_includeWhichResults( Include::FailedOnly ), | ||||
|             m_cutoff( -1 ) | ||||
|         {} | ||||
|          | ||||
|         ~Config() { | ||||
| @@ -165,6 +166,14 @@ namespace Catch { | ||||
|             return m_includeWhichResults == Include::SuccessfulResults; | ||||
|         } | ||||
|          | ||||
|         int getCutoff() const { | ||||
|             return m_cutoff; | ||||
|         } | ||||
|          | ||||
|         void setCutoff( int cutoff ) { | ||||
|             m_cutoff = cutoff; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         Ptr<IReporter> m_reporter; | ||||
|         std::string m_filename; | ||||
| @@ -177,6 +186,7 @@ namespace Catch { | ||||
|         mutable std::ostream m_os; | ||||
|         Include::WhichResults m_includeWhichResults; | ||||
|         std::string m_name; | ||||
|         int m_cutoff; | ||||
|     }; | ||||
|      | ||||
|     struct NewConfig { | ||||
|   | ||||
| @@ -38,7 +38,8 @@ namespace Catch | ||||
|         virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;         | ||||
|         virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;         | ||||
|         virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;         | ||||
|         virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;         | ||||
|         virtual void Aborted() = 0; | ||||
|         virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0; | ||||
|         virtual void Result( const ResultInfo& result ) = 0; | ||||
|     }; | ||||
|      | ||||
|   | ||||
| @@ -30,9 +30,9 @@ struct ResultWas { enum OfType { | ||||
|  | ||||
| struct ResultAction { enum Value { | ||||
|     None, | ||||
|     Failed = 1,     // Failure - but no debug break if Debug bit not set | ||||
|     DebugFailed = 3 // Indicates that the debugger should break, if possible | ||||
|      | ||||
|     Failed = 1, // Failure - but no debug break if Debug bit not set | ||||
|     Debug = 2,  // If this bit is set, invoke the debugger | ||||
|     Abort = 4   // Test run should abort     | ||||
| }; }; | ||||
|      | ||||
| } | ||||
|   | ||||
| @@ -78,7 +78,13 @@ namespace Catch { | ||||
|             const std::vector<TestCaseInfo>& allTests = getCurrentContext().getTestCaseRegistry().getAllTests(); | ||||
|             for( std::size_t i=0; i < allTests.size(); ++i ) { | ||||
|                 if( runHiddenTests || !allTests[i].isHidden() ) | ||||
|                    runTest( allTests[i] ); | ||||
|                 { | ||||
|                     if( aborting() ) { | ||||
|                         m_reporter->Aborted(); | ||||
|                         break; | ||||
|                     } | ||||
|                     runTest( allTests[i] ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
| @@ -89,6 +95,10 @@ namespace Catch { | ||||
|             std::size_t testsRun = 0; | ||||
|             for( std::size_t i=0; i < allTests.size(); ++i ) { | ||||
|                 if( testSpec.matches( allTests[i].getName() ) ) { | ||||
|                     if( aborting() ) { | ||||
|                         m_reporter->Aborted(); | ||||
|                         break; | ||||
|                     } | ||||
|                     runTest( allTests[i] ); | ||||
|                     testsRun++; | ||||
|                 } | ||||
| @@ -108,14 +118,14 @@ namespace Catch { | ||||
|  | ||||
|             do { | ||||
|                 do { | ||||
|                     m_reporter->StartGroup( "test case run" ); | ||||
| //                    m_reporter->StartGroup( "test case run" ); | ||||
|                     m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() ); | ||||
|                     runCurrentTest( redirectedCout, redirectedCerr ); | ||||
|                     m_reporter->EndGroup( "test case run", m_totals.delta( prevTotals ) ); | ||||
| //                    m_reporter->EndGroup( "test case run", m_totals.delta( prevTotals ) ); | ||||
|                 } | ||||
|                 while( m_runningTest->hasUntestedSections() ); | ||||
|                 while( m_runningTest->hasUntestedSections() && !aborting() ); | ||||
|             } | ||||
|             while( getCurrentContext().advanceGeneratorsForCurrentTest() ); | ||||
|             while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); | ||||
|  | ||||
|             delete m_runningTest; | ||||
|             m_runningTest = NULL; | ||||
| @@ -168,7 +178,7 @@ namespace Catch { | ||||
|             else | ||||
|                 m_reporter->Result( result ); | ||||
|         } | ||||
|  | ||||
|          | ||||
|         virtual bool sectionStarted ( | ||||
|             const std::string& name,  | ||||
|             const std::string& description, | ||||
| @@ -218,18 +228,27 @@ namespace Catch { | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|  | ||||
|         bool aborting() const { | ||||
|             return m_totals.assertions.failed == m_config.getCutoff(); | ||||
|         } | ||||
|          | ||||
|         ResultAction::Value actOnCurrentResult() { | ||||
|             testEnded( m_currentResult ); | ||||
|             m_lastResult = m_currentResult; | ||||
|              | ||||
|             m_currentResult = ResultInfoBuilder(); | ||||
|             if( m_lastResult.ok() ) | ||||
|                 return ResultAction::None; | ||||
|             else if( shouldDebugBreak() ) | ||||
|                 return ResultAction::DebugFailed; | ||||
|             else | ||||
|                 return ResultAction::Failed; | ||||
|  | ||||
|             ResultAction::Value action = ResultAction::None; | ||||
|              | ||||
|             if( !m_lastResult.ok() ) { | ||||
|                 action = ResultAction::Failed; | ||||
|                 if( shouldDebugBreak() ) | ||||
|                     action = (ResultAction::Value)( action | ResultAction::Debug ); | ||||
|                 if( aborting() ) | ||||
|                     action = (ResultAction::Value)( action | ResultAction::Abort ); | ||||
|             } | ||||
|             return action; | ||||
|         } | ||||
|  | ||||
|         void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash