diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 30cd34b9..b418020d 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -153,6 +153,15 @@ namespace Catch { return m_filterSets; } + std::vector const& userTestCaseHooks() const { + return m_userHooks; + } + + void addUserHook(ITestCaseHook* hook) + { + m_userHooks.push_back(hook); + } + bool showHelp() const { return m_data.showHelp; } // IConfig interface @@ -163,13 +172,13 @@ namespace Catch { virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - private: ConfigData m_data; Stream m_stream; mutable std::ostream m_os; std::vector m_filterSets; + std::vector m_userHooks; }; diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index 79cfa97b..e6266dcb 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -10,11 +10,14 @@ #include #include +#include #include "catch_ptr.hpp" namespace Catch { + struct TestCaseInfo; + struct Verbosity { enum Level { NoOutput = 0, Quiet, @@ -32,6 +35,14 @@ namespace Catch { Never }; }; + struct ITestCaseHook + { + virtual ~ITestCaseHook() {} + + virtual void sectionStarting(TestCaseInfo const & testCaseInfo) = 0; + virtual void sectionEnding(TestCaseInfo const & testCaseInfo) = 0; + }; + struct IConfig : IShared { virtual ~IConfig(); @@ -44,6 +55,8 @@ namespace Catch { virtual bool warnAboutMissingAssertions() const = 0; virtual int abortAfter() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; + + virtual std::vector< ITestCaseHook* > const & userTestCaseHooks() const = 0; }; } diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 4b34f1e9..64768ece 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -256,6 +256,26 @@ namespace Catch { return action; } + void runTestCaseStartingHook(TestCaseInfo const& testCaseInfo) + { + std::vector const & validations = m_config->userTestCaseHooks(); + + for(std::vector::const_iterator it = validations.begin(), end = validations.end(); it != end; ++it) + { + (*it)->sectionStarting(testCaseInfo); + } + } + + void runTestCaseEndingHook(TestCaseInfo const& testCaseInfo) + { + std::vector const & validations = m_config->userTestCaseHooks(); + + for(std::vector::const_reverse_iterator it = validations.rbegin(), end = validations.rend(); it != end; ++it) + { + (*it)->sectionEnding(testCaseInfo); + } + } + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); @@ -266,6 +286,8 @@ namespace Catch { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); TestCaseTracker::Guard guard( *m_testCaseTracker ); + runTestCaseStartingHook(testCaseInfo); + Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { @@ -277,6 +299,8 @@ namespace Catch { m_activeTestCase->invoke(); } duration = timer.getElapsedSeconds(); + + runTestCaseEndingHook(testCaseInfo); } catch( TestFailureException& ) { // This just means the test was aborted due to failure diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 052a761f..ffb4d52a 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.0 build 33 (master branch) - * Generated: 2014-03-24 18:11:50.426554 + * CATCH v1.0 build 34 (master branch) + * Generated: 2014-03-25 14:43:34.962000 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -1497,9 +1497,12 @@ namespace Catch { #include #include +#include namespace Catch { + struct TestCaseInfo; + struct Verbosity { enum Level { NoOutput = 0, Quiet, @@ -1517,6 +1520,14 @@ namespace Catch { Never }; }; + struct ITestCaseHook + { + virtual ~ITestCaseHook() {} + + virtual void sectionStarting(TestCaseInfo const & testCaseInfo) = 0; + virtual void sectionEnding(TestCaseInfo const & testCaseInfo) = 0; + }; + struct IConfig : IShared { virtual ~IConfig(); @@ -1529,6 +1540,8 @@ namespace Catch { virtual bool warnAboutMissingAssertions() const = 0; virtual int abortAfter() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; + + virtual std::vector< ITestCaseHook* > const & userTestCaseHooks() const = 0; }; } @@ -2993,6 +3006,15 @@ namespace Catch { return m_filterSets; } + std::vector const& userTestCaseHooks() const { + return m_userHooks; + } + + void addUserHook(ITestCaseHook* hook) + { + m_userHooks.push_back(hook); + } + bool showHelp() const { return m_data.showHelp; } // IConfig interface @@ -3009,6 +3031,7 @@ namespace Catch { Stream m_stream; mutable std::ostream m_os; std::vector m_filterSets; + std::vector m_userHooks; }; } // end namespace Catch @@ -5024,6 +5047,26 @@ namespace Catch { return action; } + void runTestCaseStartingHook(TestCaseInfo const& testCaseInfo) + { + std::vector const & validations = m_config->userTestCaseHooks(); + + for(std::vector::const_iterator it = validations.begin(), end = validations.end(); it != end; ++it) + { + (*it)->sectionStarting(testCaseInfo); + } + } + + void runTestCaseEndingHook(TestCaseInfo const& testCaseInfo) + { + std::vector const & validations = m_config->userTestCaseHooks(); + + for(std::vector::const_reverse_iterator it = validations.rbegin(), end = validations.rend(); it != end; ++it) + { + (*it)->sectionEnding(testCaseInfo); + } + } + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); @@ -5034,6 +5077,8 @@ namespace Catch { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); TestCaseTracker::Guard guard( *m_testCaseTracker ); + runTestCaseStartingHook(testCaseInfo); + Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { @@ -5045,6 +5090,8 @@ namespace Catch { m_activeTestCase->invoke(); } duration = timer.getElapsedSeconds(); + + runTestCaseEndingHook(testCaseInfo); } catch( TestFailureException& ) { // This just means the test was aborted due to failure @@ -6598,7 +6645,7 @@ namespace Catch { namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 1, 0, 33, "master" ); + Version libraryVersion( 1, 0, 34, "master" ); } // #included from: catch_message.hpp