Skip to content

Commit c3b09ae

Browse files
committed
More documentation
1 parent ec17d66 commit c3b09ae

File tree

8 files changed

+370
-144
lines changed

8 files changed

+370
-144
lines changed

include/expectations/expectation.hpp

Lines changed: 152 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
#include <vector>
55
#include "runnable.hpp"
66
#include "matchers/basematcher.hpp"
7+
#include "matchers/be.hpp"
78
#include "matchers/be_between.hpp"
9+
#include "matchers/be_within.hpp"
810
#include "matchers/include.hpp"
911
#include "matchers/equal.hpp"
10-
#include "matchers/be_within.hpp"
1112

1213
namespace Expectations {
1314

@@ -17,10 +18,10 @@ namespace Expectations {
1718
* expect(something)
1819
* expect([] -> auto { return something })
1920
*
20-
* // used with `to` matchers
21+
* // used with a matcher
2122
* expect(actual).to_equal(target)
2223
*
23-
* // used with `not` and matchers
24+
* // used with `not` and a matcher
2425
* expect(actual).not_().to_equal(target)
2526
* @endcode
2627
*
@@ -31,32 +32,64 @@ template <class A>
3132
class Expectation : public Child {
3233
A target;
3334
std::function<A(void)> block;
34-
bool has_block = false;
35-
bool is_positive = true;
35+
bool has_block = false; // Is the target a lambda?
36+
bool is_positive = true; // Have we been negated?
3637

3738
template <typename E>
3839
bool setup_and_run(Matchers::BaseMatcher<A, E> &matcher, std::string msg);
3940

4041
public:
42+
/**
43+
* @brief Create an Expectation using a value.
44+
*
45+
* @param value The target to test, an explicit value.
46+
*
47+
* @return The constructed Expectation.
48+
*/
4149
Expectation(A &value) : target(value) {}
4250

51+
/**
52+
* @brief Create an Expectation using a function.
53+
*
54+
* This does not simply contain the return value of the given
55+
* lambda, but instead wraps the thunk, delaying execution until it is time
56+
* to perform the match.
57+
*
58+
* @param block A function that returns some value to test against.
59+
*
60+
* @return The constructed Expectation.
61+
*/
4362
Expectation(std::function<A(void)> block) : block(block), has_block(true) {}
4463

64+
/**
65+
* @brief Create an Expectation using an initializer list.
66+
*
67+
* @param init_list The initializer list to match against.
68+
*
69+
* @return The constructed Expectation.
70+
*/
4571
template <typename U>
4672
Expectation(std::initializer_list<U> init_list)
4773
: target(std::vector<U>(init_list)) {}
4874

49-
A &get_target();
50-
bool get_sign();
75+
/** @brief Get the target of the expectation. */
76+
A &get_target() { return target; }
77+
78+
/** @brief Get whether the expectation is normal or negated. */
79+
bool get_sign() { return is_positive; }
5180

5281
Expectation &not_();
53-
Expectation &to();
82+
83+
bool to_be(std::function<bool(A)>, std::string msg = "");
84+
bool to_be_null(std::string msg = "");
85+
bool to_be_true(std::string msg = "");
86+
bool to_be_false(std::string msg = "");
5487

5588
template <typename U>
5689
bool to_include(std::initializer_list<U> expected, std::string msg = "");
5790

58-
template <typename U>
59-
bool to_include(U expected, std::string msg = "");
91+
template <typename E>
92+
bool to_include(E expected, std::string msg = "");
6093

6194
template <typename E>
6295
bool to_be_between(E min, E max, Matchers::RangeMode mode,
@@ -72,18 +105,8 @@ class Expectation : public Child {
72105
bool to_be_within(E expected, std::string msg = "");
73106
};
74107

75-
template <typename A>
76-
A &Expectation<A>::get_target() {
77-
return target;
78-
}
79-
80-
template <typename A>
81-
bool Expectation<A>::get_sign() {
82-
return is_positive;
83-
}
84-
85108
/**
86-
* @brief Inverts the current matcher
109+
* @brief Invert the current matcher.
87110
*/
88111
template <typename A>
89112
Expectation<A> &Expectation<A>::not_() {
@@ -106,6 +129,69 @@ bool Expectation<A>::setup_and_run(Matchers::BaseMatcher<A, E> &matcher,
106129
return matcher(msg);
107130
}
108131

132+
/**
133+
* @brief Match using the Matchers::Be matcher.
134+
*
135+
* @param test The function to use to test the output of the
136+
* expectation expression.
137+
* @param msg Optional message to give on failure.
138+
*
139+
* @return Whether the expectation succeeds or fails.
140+
*/ template <typename A>
141+
bool Expectation<A>::to_be(std::function<bool(A)> test, std::string msg) {
142+
Matchers::Be<A> matcher(*this, test);
143+
return setup_and_run(matcher, msg);
144+
}
145+
146+
/**
147+
* @brief Match using the Matchers::BeNullptr matcher.
148+
*
149+
* @param msg Optional message to give on failure.
150+
*
151+
* @return
152+
*/
153+
template <typename A>
154+
bool Expectation<A>::to_be_null(std::string msg) {
155+
Matchers::BeNullptr<A> matcher(*this);
156+
return setup_and_run(matcher, msg);
157+
}
158+
159+
/**
160+
* @brief Match using the Matchers::Be matcher, testing for truthy-ness.
161+
*
162+
* @param msg Optional message to give on failure.
163+
*
164+
* @return
165+
*/
166+
template <typename A>
167+
bool Expectation<A>::to_be_true(std::string msg) {
168+
Matchers::Be<A> matcher(*this, [](A t) { return static_cast<bool>(t); });
169+
return setup_and_run(matcher, msg);
170+
}
171+
172+
/**
173+
* @brief Match using the Matchers::Be matcher, testing for falsy-ness.
174+
*
175+
* @param msg Optional message to give on failure.
176+
*
177+
* @return
178+
*/
179+
template <typename A>
180+
bool Expectation<A>::to_be_false(std::string msg) {
181+
Matchers::Be<A> matcher(*this, [](A t) { return not static_cast<bool>(t); });
182+
return setup_and_run(matcher, msg);
183+
}
184+
185+
/**
186+
* @brief Match using the Matchers::BeBetween matcher.
187+
*
188+
* @param min
189+
* @param max
190+
* @param mode
191+
* @param msg Optional message to give on failure.
192+
*
193+
* @return
194+
*/
109195
template <typename A>
110196
template <typename E>
111197
bool Expectation<A>::to_be_between(E min, E max, Matchers::RangeMode mode,
@@ -114,12 +200,30 @@ bool Expectation<A>::to_be_between(E min, E max, Matchers::RangeMode mode,
114200
return setup_and_run(matcher, msg);
115201
}
116202

203+
/**
204+
* @brief Match using the Matchers::BeBetween matcher, with an explicit
205+
* range mode.
206+
*
207+
* @param min
208+
* @param max
209+
* @param msg Optional message to give on failure.
210+
*
211+
* @return
212+
*/
117213
template <typename A>
118214
template <typename E>
119215
bool Expectation<A>::to_be_between(E min, E max, std::string msg) {
120216
return this->to_be_between(min, max, Matchers::RangeMode::inclusive, msg);
121217
}
122218

219+
/**
220+
* @brief Match using the Matchers::Include matcher, given an initializer list.
221+
*
222+
* @param expected
223+
* @param msg Optional message to give on failure.
224+
*
225+
* @return
226+
*/
123227
template <typename A>
124228
template <typename U>
125229
bool Expectation<A>::to_include(std::initializer_list<U> expected,
@@ -128,20 +232,44 @@ bool Expectation<A>::to_include(std::initializer_list<U> expected,
128232
return setup_and_run(matcher, msg);
129233
}
130234

235+
/**
236+
* @brief Match using the Matchers::Include matcher.
237+
*
238+
* @param expected
239+
* @param msg Optional message to give on failure.
240+
*
241+
* @return
242+
*/
131243
template <typename A>
132-
template <typename U>
133-
bool Expectation<A>::to_include(U expected, std::string msg) {
134-
Matchers::Include<A, U, U> matcher(*this, expected);
244+
template <typename E>
245+
bool Expectation<A>::to_include(E expected, std::string msg) {
246+
Matchers::Include<A, E, E> matcher(*this, expected);
135247
return setup_and_run(matcher, msg);
136248
}
137249

250+
/**
251+
* @brief Match using the Matchers::Equal matcher.
252+
*
253+
* @param expected
254+
* @param msg Optional message to give on failure.
255+
*
256+
* @return
257+
*/
138258
template <typename A>
139259
template <typename E>
140260
bool Expectation<A>::to_equal(E expected, std::string msg) {
141261
Matchers::Equal<A, E> matcher(*this, expected);
142262
return setup_and_run(matcher, msg);
143263
}
144264

265+
/**
266+
* @brief Match using the Matchers::BeWithin matcher.
267+
*
268+
* @param expected
269+
* @param msg Optional message to give on failure.
270+
*
271+
* @return
272+
*/
145273
template <typename A>
146274
template <typename E>
147275
bool Expectation<A>::to_be_within(E expected, std::string msg) {

include/it.hpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ class ItD : public ItExpBase {
2828
ItD(std::string descr, std::function<void(ItD &)> body)
2929
: ItExpBase(descr), body(body) {}
3030

31-
ItD(std::function<void(ItD &)> body) : body(body) {
32-
this->set_needs_descr(true);
33-
}
31+
ItD(std::function<void(ItD &)> body) : body(body) {}
3432

3533
bool run();
3634
};
@@ -45,9 +43,7 @@ class ItCd : public ItExpBase {
4543
ItCd(std::string descr, std::function<void(ItCd<T> &)> body)
4644
: ItExpBase(descr), body(body) {}
4745

48-
ItCd(std::function<void(ItCd<T> &)> body) : body(body) {
49-
this->set_needs_descr(true);
50-
}
46+
ItCd(std::function<void(ItCd<T> &)> body) : body(body) {}
5147

5248
Expectations::Expectation<T> is_expected();
5349
bool run();
@@ -86,16 +82,15 @@ Expectations::Expectation<std::vector<T>> ItExpBase::expect(
8682

8783
template <class T>
8884
Expectations::Expectation<T> ItCd<T>::is_expected() {
89-
ClassDescription<T> *cd =
90-
static_cast<ClassDescription<T> *>(this->get_parent());
85+
auto cd = static_cast<ClassDescription<T> *>(this->get_parent());
9186
Expectations::Expectation<T> expectation(cd->get_subject());
9287
expectation.set_parent(this);
9388
return expectation;
9489
}
9590

9691
bool ItD::run() {
9792
if (!this->needs_descr()) {
98-
std::cout << padding() << descr << std::endl;
93+
std::cout << padding() << get_descr() << std::endl;
9994
}
10095
body(*this);
10196
return this->get_status();
@@ -104,7 +99,7 @@ bool ItD::run() {
10499
template <class T>
105100
bool ItCd<T>::run() {
106101
if (!this->needs_descr()) {
107-
std::cout << padding() << descr << std::endl;
102+
std::cout << padding() << get_descr() << std::endl;
108103
}
109104
body(*this);
110105
return this->get_status();

include/it_base.hpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,46 @@
44
#include <string>
55
#include "runnable.hpp"
66

7+
/**
8+
* @brief Most base class for `it` expressions.
9+
*
10+
* This class is needed to prevent a circular dependency between it.hpp and
11+
* basematcher.hpp. Matchers need to know whether or not an `it` has an explicit
12+
* description string or whether the description should be generated. `it`s need
13+
* to be able to refer to Expectations, and Expectations need to know about
14+
* Matchers and execute them. This class is the least common denominator of the
15+
* `it` classes, and thus is used to resolve the dependency cycle.
16+
*/
717
class ItBase : public Runnable {
8-
protected:
918
std::string descr = "";
10-
bool does_need_descr = false;
1119

1220
public:
21+
/**
22+
* @brief Create an ItBase without an explicit description
23+
* @return the constructed ItBase
24+
*/
1325
ItBase(){};
14-
ItBase(std::string descr) : descr(descr){};
26+
27+
/**
28+
* @brief Create an ItBase with an explicit description.
29+
* @param descr the description of the `it` statement
30+
* @return the constructed ItBase
31+
*/
32+
explicit ItBase(std::string descr) : descr(descr){};
1533

1634
bool run() { return false; };
1735

18-
void set_needs_descr(bool nd) { does_need_descr = nd; }
19-
bool needs_descr() { return does_need_descr; }
36+
/**
37+
* @brief Get whether the object needs a description string
38+
* @return whether this object needs a description to be generated or not
39+
*/
40+
bool needs_descr() { return descr.empty(); }
41+
42+
/**
43+
* @brief Get the description string for the `it` statement
44+
* @return the description string
45+
*/
46+
std::string get_descr() { return descr; }
2047
};
2148

2249
#endif /* IT_BASE_H */

include/matchers/basematcher.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ class BaseMatcher : public Child, public Pretty {
3838
// different");
3939
}
4040

41-
virtual ~BaseMatcher(){};
42-
4341
virtual bool matches(Actual actual);
4442
virtual std::string failure_message();
4543
virtual std::string failure_message_when_negated();
@@ -80,7 +78,7 @@ std::string BaseMatcher<A, E>::description() {
8078
template <typename A, typename E>
8179
bool BaseMatcher<A, E>::operator()(std::string message) {
8280
bool matched;
83-
ItBase *par = static_cast<ItBase *>(this->get_parent());
81+
auto par = static_cast<ItBase *>(this->get_parent());
8482

8583
if (par->needs_descr()) {
8684
std::cout << par->padding() << "should "

0 commit comments

Comments
 (0)