Exception message testing now supports wildcards

- extracted WildcardPattern from TestSpec::NamePattern
This commit is contained in:
Phil Nash 2015-07-13 15:03:04 +01:00
parent 93a842e2f0
commit 2104ca2aa4
10 changed files with 234 additions and 51 deletions

View File

@ -77,6 +77,7 @@ namespace Catch {
FreeFunctionTestCase::~FreeFunctionTestCase() {} FreeFunctionTestCase::~FreeFunctionTestCase() {}
IGeneratorInfo::~IGeneratorInfo() {} IGeneratorInfo::~IGeneratorInfo() {}
IGeneratorsForTest::~IGeneratorsForTest() {} IGeneratorsForTest::~IGeneratorsForTest() {}
WildcardPattern::~WildcardPattern() {}
TestSpec::Pattern::~Pattern() {} TestSpec::Pattern::~Pattern() {}
TestSpec::NamePattern::~NamePattern() {} TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {} TestSpec::TagPattern::~TagPattern() {}

View File

@ -14,7 +14,7 @@
#include "catch_interfaces_runner.h" #include "catch_interfaces_runner.h"
#include "catch_interfaces_capture.h" #include "catch_interfaces_capture.h"
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
#include "catch_wildcard_pattern.hpp"
namespace Catch { namespace Catch {
@ -78,7 +78,8 @@ namespace Catch {
if( expectedMessage != "" ) { if( expectedMessage != "" ) {
std::string actualMessage = Catch::translateActiveException(); std::string actualMessage = Catch::translateActiveException();
if( expectedMessage != actualMessage ) { WildcardPattern pattern( expectedMessage, WildcardPattern::CaseInsensitive );
if( !pattern.matches( actualMessage ) ) {
data.resultType = ResultWas::ExpressionFailed; data.resultType = ResultWas::ExpressionFailed;
data.reconstructedExpression = actualMessage; data.reconstructedExpression = actualMessage;
} }

View File

@ -13,63 +13,32 @@
#pragma clang diagnostic ignored "-Wpadded" #pragma clang diagnostic ignored "-Wpadded"
#endif #endif
#include "catch_wildcard_pattern.hpp"
#include "catch_test_case_info.h" #include "catch_test_case_info.h"
#include <string> #include <string>
#include <vector> #include <vector>
namespace Catch { namespace Catch {
class TestSpec { class TestSpec {
struct Pattern : SharedImpl<> { struct Pattern : SharedImpl<> {
virtual ~Pattern(); virtual ~Pattern();
virtual bool matches( TestCaseInfo const& testCase ) const = 0; virtual bool matches( TestCaseInfo const& testCase ) const = 0;
}; };
class NamePattern : public Pattern { class NamePattern : public Pattern {
enum WildcardPosition {
NoWildcard = 0,
WildcardAtStart = 1,
WildcardAtEnd = 2,
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
};
public: public:
NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { NamePattern( std::string const& name )
if( startsWith( m_name, "*" ) ) { : m_wildcardPattern( toLower( name ), WildcardPattern::CaseInsensitive )
m_name = m_name.substr( 1 ); {}
m_wildcard = WildcardAtStart;
}
if( endsWith( m_name, "*" ) ) {
m_name = m_name.substr( 0, m_name.size()-1 );
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
}
}
virtual ~NamePattern(); virtual ~NamePattern();
virtual bool matches( TestCaseInfo const& testCase ) const { virtual bool matches( TestCaseInfo const& testCase ) const {
switch( m_wildcard ) { return m_wildcardPattern.matches( toLower( testCase.name ) );
case NoWildcard:
return m_name == toLower( testCase.name );
case WildcardAtStart:
return endsWith( toLower( testCase.name ), m_name );
case WildcardAtEnd:
return startsWith( toLower( testCase.name ), m_name );
case WildcardAtBothEnds:
return contains( toLower( testCase.name ), m_name );
}
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
throw std::logic_error( "Unknown enum" );
#ifdef __clang__
#pragma clang diagnostic pop
#endif
} }
private: private:
std::string m_name; WildcardPattern m_wildcardPattern;
WildcardPosition m_wildcard;
}; };
class TagPattern : public Pattern { class TagPattern : public Pattern {
public: public:
TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
@ -80,6 +49,7 @@ namespace Catch {
private: private:
std::string m_tag; std::string m_tag;
}; };
class ExcludedPattern : public Pattern { class ExcludedPattern : public Pattern {
public: public:
ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}

View File

@ -0,0 +1,75 @@
/*
* Created by Phil on 13/7/2015.
* Copyright 2015 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
#include "catch_common.h"
namespace Catch
{
class WildcardPattern {
enum WildcardPosition {
NoWildcard = 0,
WildcardAtStart = 1,
WildcardAtEnd = 2,
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
};
public:
enum CaseSensitivity {
CaseSensitive,
CaseInsensitive
};
WildcardPattern( std::string const& pattern, CaseSensitivity caseSensitivity )
: m_caseSensitivity( caseSensitivity ),
m_wildcard( NoWildcard ),
m_pattern( adjustCase( pattern ) )
{
if( startsWith( m_pattern, "*" ) ) {
m_pattern = m_pattern.substr( 1 );
m_wildcard = WildcardAtStart;
}
if( endsWith( m_pattern, "*" ) ) {
m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
}
}
virtual ~WildcardPattern();
virtual bool matches( std::string const& str ) const {
switch( m_wildcard ) {
case NoWildcard:
return m_pattern == adjustCase( str );
case WildcardAtStart:
return endsWith( adjustCase( str ), m_pattern );
case WildcardAtEnd:
return startsWith( adjustCase( str ), m_pattern );
case WildcardAtBothEnds:
return contains( adjustCase( str ), m_pattern );
}
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
throw std::logic_error( "Unknown enum" );
#ifdef __clang__
#pragma clang diagnostic pop
#endif
}
private:
std::string adjustCase( std::string const& str ) const {
return m_caseSensitivity == CaseInsensitive ? toLower( str ) : str;
}
CaseSensitivity m_caseSensitivity;
WildcardPosition m_wildcard;
std::string m_pattern;
};
}
#endif // TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED

View File

@ -398,7 +398,7 @@ due to unexpected exception with message:
3.14 3.14
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Exception messages can be tested for Mismatching exception messages failing the test
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
ExceptionTests.cpp:<line number> ExceptionTests.cpp:<line number>
............................................................................... ...............................................................................
@ -797,6 +797,6 @@ with expansion:
"first" == "second" "first" == "second"
=============================================================================== ===============================================================================
test cases: 156 | 116 passed | 39 failed | 1 failed as expected test cases: 157 | 117 passed | 39 failed | 1 failed as expected
assertions: 767 | 674 passed | 80 failed | 13 failed as expected assertions: 774 | 681 passed | 80 failed | 13 failed as expected

View File

@ -1279,10 +1279,59 @@ PASSED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Exception messages can be tested for Exception messages can be tested for
exact match
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
ExceptionTests.cpp:<line number> ExceptionTests.cpp:<line number>
............................................................................... ...............................................................................
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
-------------------------------------------------------------------------------
Exception messages can be tested for
different case
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" )
-------------------------------------------------------------------------------
Exception messages can be tested for
wildcarded
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "expected*" )
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "*exception" )
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "*except*" )
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" )
-------------------------------------------------------------------------------
Mismatching exception messages failing the test
-------------------------------------------------------------------------------
ExceptionTests.cpp:<line number>
...............................................................................
ExceptionTests.cpp:<line number>:
PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
ExceptionTests.cpp:<line number>: ExceptionTests.cpp:<line number>:
PASSED: PASSED:
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
@ -7959,6 +8008,6 @@ with expansion:
true true
=============================================================================== ===============================================================================
test cases: 156 | 100 passed | 55 failed | 1 failed as expected test cases: 157 | 101 passed | 55 failed | 1 failed as expected
assertions: 787 | 674 passed | 100 failed | 13 failed as expected assertions: 794 | 681 passed | 100 failed | 13 failed as expected

View File

@ -1,5 +1,5 @@
<testsuites> <testsuites>
<testsuite name="all tests" errors="12" failures="88" tests="787" hostname="tbd" time="{duration}" timestamp="tbd"> <testsuite name="all tests" errors="12" failures="88" tests="794" 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,7 +251,10 @@ 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}"> <testcase classname="Exception messages can be tested for" name="exact match" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="different case" time="{duration}"/>
<testcase classname="Exception messages can be tested for" name="wildcarded" time="{duration}"/>
<testcase classname="global" name="Mismatching exception messages failing the test" time="{duration}">
<failure message="expected exception" type="REQUIRE_THROWS_WITH"> <failure message="expected exception" type="REQUIRE_THROWS_WITH">
ExceptionTests.cpp:<line number> ExceptionTests.cpp:<line number>
</failure> </failure>

View File

@ -1597,6 +1597,74 @@
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Exception messages can be tested for"> <TestCase name="Exception messages can be tested for">
<Section name="exact match">
<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>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="different case">
<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>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="wildcarded">
<Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original>
thisThrows(), &quot;expected*&quot;
</Original>
<Expanded>
thisThrows(), &quot;expected*&quot;
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original>
thisThrows(), &quot;*exception&quot;
</Original>
<Expanded>
thisThrows(), &quot;*exception&quot;
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original>
thisThrows(), &quot;*except*&quot;
</Original>
<Expanded>
thisThrows(), &quot;*except*&quot;
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original>
thisThrows(), &quot;*exCept*&quot;
</Original>
<Expanded>
thisThrows(), &quot;*exCept*&quot;
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Mismatching exception messages failing the test">
<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="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" > <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
<Original> <Original>
thisThrows(), &quot;expected exception&quot; thisThrows(), &quot;expected exception&quot;
@ -8239,7 +8307,7 @@ there&quot;
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="674" failures="100" expectedFailures="13"/> <OverallResults successes="681" failures="100" expectedFailures="13"/>
</Group> </Group>
<OverallResults successes="674" failures="100" expectedFailures="13"/> <OverallResults successes="681" failures="100" expectedFailures="13"/>
</Catch> </Catch>

View File

@ -153,7 +153,21 @@ TEST_CASE( "NotImplemented exception", "" )
REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) );
} }
TEST_CASE( "Exception messages can be tested for", "[.][failing]" ) { TEST_CASE( "Exception messages can be tested for", "" ) {
SECTION( "exact match" )
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
SECTION( "different case" )
REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" );
SECTION( "wildcarded" ) {
REQUIRE_THROWS_WITH( thisThrows(), "expected*" );
REQUIRE_THROWS_WITH( thisThrows(), "*exception" );
REQUIRE_THROWS_WITH( thisThrows(), "*except*" );
REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" );
}
}
TEST_CASE( "Mismatching exception messages failing the test", "[.][failing]" ) {
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); REQUIRE_THROWS_WITH( thisThrows(), "should fail" );
} }

View File

@ -108,6 +108,7 @@
269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = "<group>"; }; 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = "<group>"; };
26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = "<group>"; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = "<group>"; };
26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = "<group>"; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = "<group>"; };
26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = "<group>"; };
26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = "<group>"; }; 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = "<group>"; };
4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = "<group>"; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = "<group>"; };
4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = "<group>"; }; 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = "<group>"; };
@ -470,6 +471,7 @@
2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */, 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */,
2656C227192A78410040DB02 /* catch_reenable_warnings.h */, 2656C227192A78410040DB02 /* catch_reenable_warnings.h */,
263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */, 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */,
26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */,
); );
name = Infrastructure; name = Infrastructure;
sourceTree = "<group>"; sourceTree = "<group>";