From 2104ca2aa49712dbfac022d5afe681305b8acb3f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 13 Jul 2015 15:03:04 +0100 Subject: [PATCH] Exception message testing now supports wildcards - extracted WildcardPattern from TestSpec::NamePattern --- include/internal/catch_impl.hpp | 1 + include/internal/catch_result_builder.hpp | 5 +- include/internal/catch_test_spec.hpp | 48 +++--------- include/internal/catch_wildcard_pattern.hpp | 75 +++++++++++++++++++ .../Baselines/console.std.approved.txt | 6 +- .../Baselines/console.sw.approved.txt | 53 ++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 7 +- .../SelfTest/Baselines/xml.sw.approved.txt | 72 +++++++++++++++++- projects/SelfTest/ExceptionTests.cpp | 16 +++- .../CatchSelfTest.xcodeproj/project.pbxproj | 2 + 10 files changed, 234 insertions(+), 51 deletions(-) create mode 100644 include/internal/catch_wildcard_pattern.hpp diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 24a8c3f8..62fdcaea 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -77,6 +77,7 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index cc083bce..ae86d768 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -14,7 +14,7 @@ #include "catch_interfaces_runner.h" #include "catch_interfaces_capture.h" #include "catch_interfaces_registry_hub.h" - +#include "catch_wildcard_pattern.hpp" namespace Catch { @@ -78,7 +78,8 @@ namespace Catch { if( expectedMessage != "" ) { std::string actualMessage = Catch::translateActiveException(); - if( expectedMessage != actualMessage ) { + WildcardPattern pattern( expectedMessage, WildcardPattern::CaseInsensitive ); + if( !pattern.matches( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; data.reconstructedExpression = actualMessage; } diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index b5f70635..292ffce4 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -13,63 +13,32 @@ #pragma clang diagnostic ignored "-Wpadded" #endif +#include "catch_wildcard_pattern.hpp" #include "catch_test_case_info.h" #include #include namespace Catch { - + class TestSpec { struct Pattern : SharedImpl<> { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { - if( startsWith( m_name, "*" ) ) { - 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( m_wildcard | WildcardAtEnd ); - } - } + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), WildcardPattern::CaseInsensitive ) + {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { - switch( m_wildcard ) { - 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 + return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: - std::string m_name; - WildcardPosition m_wildcard; + WildcardPattern m_wildcardPattern; }; + class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} @@ -80,6 +49,7 @@ namespace Catch { private: std::string m_tag; }; + class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp new file mode 100644 index 00000000..f42dc5d0 --- /dev/null +++ b/include/internal/catch_wildcard_pattern.hpp @@ -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( 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 diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index de86a473..63530052 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -398,7 +398,7 @@ due to unexpected exception with message: 3.14 ------------------------------------------------------------------------------- -Exception messages can be tested for +Mismatching exception messages failing the test ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... @@ -797,6 +797,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 156 | 116 passed | 39 failed | 1 failed as expected -assertions: 767 | 674 passed | 80 failed | 13 failed as expected +test cases: 157 | 117 passed | 39 failed | 1 failed as expected +assertions: 774 | 681 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 6e191f56..1919c1c2 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1279,10 +1279,59 @@ PASSED: ------------------------------------------------------------------------------- Exception messages can be tested for + exact match ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + different case +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + wildcarded +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected*" ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "*exception" ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "*except*" ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" ) + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) @@ -7959,6 +8008,6 @@ with expansion: true =============================================================================== -test cases: 156 | 100 passed | 55 failed | 1 failed as expected -assertions: 787 | 674 passed | 100 failed | 13 failed as expected +test cases: 157 | 101 passed | 55 failed | 1 failed as expected +assertions: 794 | 681 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 36e31fe8..95d4f9a2 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -251,7 +251,10 @@ ExceptionTests.cpp: - + + + + ExceptionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 01144a0d..0d06a704 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1597,6 +1597,74 @@ +
+ + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + +
+
+ + + thisThrows(), "expecteD Exception" + + + thisThrows(), "expecteD Exception" + + + +
+
+ + + thisThrows(), "expected*" + + + thisThrows(), "expected*" + + + + + thisThrows(), "*exception" + + + thisThrows(), "*exception" + + + + + thisThrows(), "*except*" + + + thisThrows(), "*except*" + + + + + thisThrows(), "*exCept*" + + + thisThrows(), "*exCept*" + + + +
+ +
+ + + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + thisThrows(), "expected exception" @@ -8239,7 +8307,7 @@ there" - + - + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index eb24160b..f3b7f41d 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -153,7 +153,21 @@ TEST_CASE( "NotImplemented exception", "" ) 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(), "should fail" ); } diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 047fa70e..47e8c66a 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -108,6 +108,7 @@ 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = ""; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = ""; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = ""; }; 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = ""; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = ""; }; 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = ""; }; @@ -470,6 +471,7 @@ 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */, 2656C227192A78410040DB02 /* catch_reenable_warnings.h */, 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */, + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */, ); name = Infrastructure; sourceTree = "";