snitch-org / snitch

Lightweight C++20 testing framework.
Boost Software License 1.0
267 stars 10 forks source link

How to match std::exception error text easily? #142

Closed vid512 closed 1 year ago

vid512 commented 1 year ago

I am trying to write something analogous to Catch2 REQUIRE_THROWS_WITH( func(), ContainsString("too big")).

My first instinct was to use REQUIRE_THROWS_MATCHES like this:

#define SNITCH_IMPLEMENTATION
#include "snitch_all.hpp"

#include <exception>

void func() {
    throw std::runtime_error("unimplemented");
}

TEST_CASE("blah") {
    REQUIRE_THROWS_MATCHES( func(), std::runtime_error, snitch::matchers::contains_substring("too big") );
}

But apprently, I need to provide matcher for std::exception object, not just for its what() message?

a.cpp(11): error C2664: 'bool snitch::matchers::contains_substring::match(std::string_view) noexcept const': cannot convert argument 1 from 'const std::runtime_error' to 'std::string_view'
a.cpp(11): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
c:\dev\testbed\cpp-snitch\snitch_all.hpp(3769): note: see declaration of 'snitch::matchers::contains_substring::match'
a.cpp(11): note: while trying to match the argument list '(const std::runtime_error)'
a.cpp(11): error C2664: 'snitch::small_string<1024> snitch::matchers::contains_substring::describe_match(std::string_view,snitch::matchers::match_status) noexcept const': cannot convert argument 1 from 'const std::runtime_error' to 'std::string_view'
a.cpp(11): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
c:\dev\testbed\cpp-snitch\snitch_all.hpp(3774): note: see declaration of 'snitch::matchers::contains_substring::describe_match'
a.cpp(11): note: while trying to match the argument list '(const std::runtime_error, snitch::matchers::match_status)'

Is there any shorthand for this (IMO common) scenario? Or do I need to write my own set of matchers for std::exception message? Or am I missing something obvious?

cschreib commented 1 year ago

You can use the matcher snitch::matchers::with_what_contains{"message"}, which checks against the output of what(). The test macro REQUIRE_THROWS_MATCHES(...) doesn't require an exception object that derives from std::exception (e.g., could be int), so it can't call what() directly; that needs to happen in the matcher.

vid512 commented 1 year ago

Thanks, I've missed with_what_contains matcher. Sorry for not reading docs properly.

cschreib commented 1 year ago

No worries!