C++Spec 1.0.0
BDD testing for C++
Loading...
Searching...
No Matches
matcher_base.hpp
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <source_location>
13#include <string>
14
16#include "it_base.hpp"
17#include "pretty_matchers.hpp"
18
19namespace CppSpec {
20
21template <class T>
22class Expectation; // Forward declaration of Expectation
23
24namespace Matchers {
25
36template <typename Actual, typename Expected>
37class MatcherBase : public Pretty {
38 std::string custom_failure_message;
39
40 protected:
41 Expected expected_; // The expected object contained by the matcher
42
43 // A reference to the Expectation (i.e. `expect(2)`)
44 Expectation<Actual>& expectation_;
45
46 public:
47 // Copy constructor
48 MatcherBase(MatcherBase<Actual, Expected> const& copy) = default;
49
50 // Constructor when matcher has no 'object' to match for
51 explicit MatcherBase(Expectation<Actual>& expectation)
52 // We want the parent of the matcher to be the `it` block, not the Expectation.
53 : expectation_(expectation) {}
54
55 // Constructor when the matcher has an object to match for. This is the most
56 // commonly used constructor
57 MatcherBase(Expectation<Actual>& expectation, Expected expected) : expected_(expected), expectation_(expectation) {}
58
59 virtual ~MatcherBase() = default;
60
61 /*--------- Helper functions -------------*/
62
63 virtual std::string failure_message();
64 virtual std::string failure_message_when_negated();
65 virtual std::string description();
66 virtual std::string verb() { return "match"; }
67
68 // Get the 'actual' object from the Expectation
69 constexpr Actual& actual() { return expectation_.get_target(); }
70
71 // Get the 'expected' object from the Matcher
72 Expected& expected() { return expected_; }
73
74 // Get the Expectation itself
75 Expectation<Actual>& expectation() { return expectation_; }
76
77 // Set the message to give on match failure
78 virtual MatcherBase& set_message(std::string message);
79
80 [[nodiscard]] std::source_location get_location() const { return expectation_.get_location(); }
81
82 /*--------- Primary functions -------------*/
83
84 // Run the matcher
86
87 virtual bool match() = 0;
88 virtual bool negated_match() { return !match(); }
89
90 // typedef Expected
91 using expected_t = Expected;
92};
93
100template <typename A, typename E>
101MatcherBase<A, E>& MatcherBase<A, E>::set_message(std::string message) {
102 this->custom_failure_message = std::move(message);
103 return *this;
104}
105
111template <typename A, typename E>
113 if (not custom_failure_message.empty()) {
114 return this->custom_failure_message;
115 }
116 return std::format("expected {} to {}", Pretty::to_word(actual()), description());
117}
118
124template <typename A, typename E>
126 if (not custom_failure_message.empty()) {
127 return this->custom_failure_message;
128 }
129 return std::format("expected {} to not {}", Pretty::to_word(actual()), description());
130}
131
137template <typename A, typename E>
139 // std::string pretty_expected = this->to_sentence(expected_);
140 // ss << "match " <<
141 // this->name_to_sentence(Util::demangle(typeid(*this).name()))
142 // << "(" << pretty_expected.substr(1, pretty_expected.length()) << ")";
143 return std::format("{} {}", verb(), Pretty::to_sentence(expected_));
144}
145
153template <typename A, typename E>
155 Result result = expectation_.positive() ? PositiveExpectationHandler::handle_matcher(*this)
157
158 result.set_type(Util::demangle(typeid(*this).name()));
159
160 // If our items didn't match, we obviously failed.
161 // Only report the failure if we aren't actively ignoring it.
162 if (result.is_failure() && result.get_message().empty()) {
163 result.set_message(
164 "Failure message is empty. Does your matcher define the "
165 "appropriate failure_message[_when_negated] method to "
166 "return a string?");
167 }
168
169 if (expectation_.ignored()) {
170 result.set_status(Result::Status::Skipped);
171 }
172
173 ItBase* parent = expectation_.get_it();
174 if (parent != nullptr) {
175 // If we need a description for our test, generate it
176 // unless we're ignoring the output.
177 if (parent->needs_description() && !expectation_.ignored()) {
178 parent->set_description(
179 (expectation_.positive() ? PositiveExpectationHandler::verb() : NegativeExpectationHandler::verb()) + " " +
180 this->description());
181 }
182 parent->add_result(result);
183 }
184 return result;
185}
186
187} // namespace Matchers
188} // namespace CppSpec
Wraps the target of an expectation.
Definition expectation.hpp:47
virtual A & get_target() &=0
Get the target of the expectation.
Base class for it expressions.
Definition it_base.hpp:32
bool needs_description() noexcept
Get whether the object needs a description string.
Definition it_base.hpp:58
ItBase & set_description(std::string_view description) noexcept
Set the description string.
Definition it_base.hpp:70
virtual std::string description()
Get the description of the Matcher.
Definition matcher_base.hpp:138
Result run()
Run the Matcher object.
Definition matcher_base.hpp:154
virtual std::string failure_message_when_negated()
Get message to give on match failure when negated.
Definition matcher_base.hpp:125
virtual std::string failure_message()
Get message to give on match failure.
Definition matcher_base.hpp:112
virtual MatcherBase & set_message(std::string message)
Set a custom failure message.
Definition matcher_base.hpp:101
Definition result.hpp:13
Definition have_error.hpp:9
Contains the primary handlers for running Matchers.
static Result handle_matcher(Matcher &matcher)
runs a negative expectation
Definition handler.hpp:65
static Result handle_matcher(Matcher &matcher)
runs a positive expectation
Definition handler.hpp:42
A helper base class that assists in pretty-printing various objects.
Definition pretty_matchers.hpp:27
static std::string to_word(const T &item)
Formats an object as a string when operator<< is available.
Definition pretty_matchers.hpp:122
static std::string to_sentence(const T &item)
Take a single object and format it as a sentance.
Definition pretty_matchers.hpp:106
std::string demangle(const char *name)
Definition util.hpp:38