Added _THROWS_WITH macros

- asserts on exception message
This commit is contained in:
Phil Nash 2015-07-13 06:34:41 +01:00
parent 5d5ed5a283
commit 85de743d70
9 changed files with 106 additions and 17 deletions

View File

@ -70,8 +70,9 @@
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
#define CATCH_REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "CATCH_REQUIRE_THROWS_WITH" )
#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
@ -82,6 +83,7 @@
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
#define CATCH_CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CATCH_CHECK_THROWS_WITH" )
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
@ -135,8 +137,9 @@
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
#define REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "REQUIRE_THROWS_WITH" )
#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
@ -145,8 +148,9 @@
#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
#define CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CHECK_THROWS_WITH" )
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )

View File

@ -66,16 +66,16 @@
} while( Catch::alwaysFalse() ) } while( Catch::alwaysFalse() )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ #define INTERNAL_CATCH_THROWS( expr, resultDisposition, expectedMessage, macroName ) \
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, expectedMessage ); \
if( __catchResult.allowThrows() ) \ if( __catchResult.allowThrows() ) \
try { \ try { \
expr; \ expr; \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \ } \
catch( ... ) { \ catch( ... ) { \
__catchResult.captureResult( Catch::ResultWas::Ok ); \ __catchResult.captureExpectedException( expectedMessage ); \
} \ } \
else \ else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \ __catchResult.captureResult( Catch::ResultWas::Ok ); \

View File

@ -38,7 +38,8 @@ namespace Catch {
ResultBuilder( char const* macroName, ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo, SourceLineInfo const& lineInfo,
char const* capturedExpression, char const* capturedExpression,
ResultDisposition::Flags resultDisposition ); ResultDisposition::Flags resultDisposition,
char const* secondArg = "" );
template<typename T> template<typename T>
ExpressionLhs<T const&> operator <= ( T const& operand ); ExpressionLhs<T const&> operator <= ( T const& operand );
@ -67,6 +68,8 @@ namespace Catch {
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
void captureResult( ResultWas::OfType resultType ); void captureResult( ResultWas::OfType resultType );
void captureExpression(); void captureExpression();
void captureExpectedException( std::string const& expectedMessage );
void handleResult( AssertionResult const& result );
void react(); void react();
bool shouldDebugBreak() const; bool shouldDebugBreak() const;
bool allowThrows() const; bool allowThrows() const;

View File

@ -18,11 +18,17 @@
namespace Catch { namespace Catch {
std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
return secondArg.empty()
? capturedExpression
: capturedExpression + ", \"" + secondArg + "\"";
}
ResultBuilder::ResultBuilder( char const* macroName, ResultBuilder::ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo, SourceLineInfo const& lineInfo,
char const* capturedExpression, char const* capturedExpression,
ResultDisposition::Flags resultDisposition ) ResultDisposition::Flags resultDisposition,
: m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), char const* secondArg )
: m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
m_shouldDebugBreak( false ), m_shouldDebugBreak( false ),
m_shouldThrow( false ) m_shouldThrow( false )
{} {}
@ -64,8 +70,29 @@ namespace Catch {
captureExpression(); captureExpression();
} }
void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
assert( m_exprComponents.testFalse == false );
AssertionResultData data = m_data;
data.resultType = ResultWas::Ok;
data.reconstructedExpression = m_assertionInfo.capturedExpression;
if( expectedMessage != "" ) {
std::string actualMessage = Catch::translateActiveException();
if( expectedMessage != actualMessage ) {
data.resultType = ResultWas::ExpressionFailed;
data.reconstructedExpression = actualMessage;
}
}
AssertionResult result( m_assertionInfo, data );
handleResult( result );
}
void ResultBuilder::captureExpression() { void ResultBuilder::captureExpression() {
AssertionResult result = build(); AssertionResult result = build();
handleResult( result );
}
void ResultBuilder::handleResult( AssertionResult const& result )
{
getResultCapture().assertionEnded( result ); getResultCapture().assertionEnded( result );
if( !result.isOk() ) { if( !result.isOk() ) {

View File

@ -397,6 +397,17 @@ ExceptionTests.cpp:<line number>: FAILED:
due to unexpected exception with message: due to unexpected exception with message:
3.14 3.14
-------------------------------------------------------------------------------
Exception messages can be tested for
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
with expansion:
expected exception
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
INFO and WARN do not abort tests INFO and WARN do not abort tests
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -786,6 +797,6 @@ with expansion:
"first" == "second" "first" == "second"
=============================================================================== ===============================================================================
test cases: 155 | 116 passed | 38 failed | 1 failed as expected test cases: 156 | 116 passed | 39 failed | 1 failed as expected
assertions: 765 | 673 passed | 79 failed | 13 failed as expected assertions: 767 | 674 passed | 80 failed | 13 failed as expected

View File

@ -1277,6 +1277,21 @@ ExceptionTests.cpp:<line number>:
PASSED: PASSED:
REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ) REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) )
-------------------------------------------------------------------------------
Exception messages can be tested for
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
ExceptionTests.cpp:<line number>: FAILED:
REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
with expansion:
expected exception
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Generators over two ranges Generators over two ranges
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -7944,6 +7959,6 @@ with expansion:
true true
=============================================================================== ===============================================================================
test cases: 155 | 100 passed | 54 failed | 1 failed as expected test cases: 156 | 100 passed | 55 failed | 1 failed as expected
assertions: 785 | 673 passed | 99 failed | 13 failed as expected assertions: 787 | 674 passed | 100 failed | 13 failed as expected

View File

@ -1,5 +1,5 @@
<testsuites> <testsuites>
<testsuite name="all tests" errors="12" failures="87" tests="785" hostname="tbd" time="{duration}" timestamp="tbd"> <testsuite name="all tests" errors="12" failures="88" tests="787" hostname="tbd" time="{duration}" timestamp="tbd">
<testcase classname="global" name="toString(enum)" time="{duration}"/> <testcase classname="global" name="toString(enum)" time="{duration}"/>
<testcase classname="global" name="toString(enum w/operator&lt;&lt;)" time="{duration}"/> <testcase classname="global" name="toString(enum w/operator&lt;&lt;)" time="{duration}"/>
<testcase classname="global" name="toString(enum class)" time="{duration}"/> <testcase classname="global" name="toString(enum class)" time="{duration}"/>
@ -251,6 +251,11 @@ ExceptionTests.cpp:<line number>
</error> </error>
</testcase> </testcase>
<testcase classname="global" name="NotImplemented exception" time="{duration}"/> <testcase classname="global" name="NotImplemented exception" time="{duration}"/>
<testcase classname="global" name="Exception messages can be tested for" time="{duration}">
<failure message="expected exception" type="REQUIRE_THROWS_WITH">
ExceptionTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="Generators over two ranges" time="{duration}"/> <testcase classname="global" name="Generators over two ranges" time="{duration}"/>
<testcase classname="global" name="Generator over a range of pairs" time="{duration}"/> <testcase classname="global" name="Generator over a range of pairs" time="{duration}"/>
<testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/> <testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/>

View File

@ -1596,6 +1596,25 @@
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Exception messages can be tested for">
<Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original>
thisThrows(), &quot;expected exception&quot;
</Original>
<Expanded>
thisThrows(), &quot;expected exception&quot;
</Expanded>
</Expression>
<Expression success="false" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original>
thisThrows(), &quot;should fail&quot;
</Original>
<Expanded>
expected exception
</Expanded>
</Expression>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Generators over two ranges"> <TestCase name="Generators over two ranges">
<Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" > <Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" >
<Original> <Original>
@ -8220,7 +8239,7 @@ there&quot;
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="673" failures="99" expectedFailures="13"/> <OverallResults successes="674" failures="100" expectedFailures="13"/>
</Group> </Group>
<OverallResults successes="673" failures="99" expectedFailures="13"/> <OverallResults successes="674" failures="100" expectedFailures="13"/>
</Catch> </Catch>

View File

@ -152,3 +152,8 @@ TEST_CASE( "NotImplemented exception", "" )
{ {
REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) );
} }
TEST_CASE( "Exception messages can be tested for", "[.][failing]" ) {
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
REQUIRE_THROWS_WITH( thisThrows(), "should fail" );
}