Skip to content

Commit 7fe4e88

Browse files
committed
Major refactor and cleanup of API
1 parent db49109 commit 7fe4e88

27 files changed

+373
-393
lines changed

README.md

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,46 @@
44
[![Github Releases](https://img.shields.io/github/downloads/toroidal-code/cppspec/latest/total.svg)]() 
55
[![Documentation Status](https://readthedocs.org/projects/cppspec/badge/?version=latest)](http://cppspec.readthedocs.org/en/latest/?badge=latest)
66

7-
C++Spec is a behavior-driven development library for C++ with an RSpec-inspired DSL.
7+
A behavior-driven development testing library for C++ with an RSpec-inspired DSL.
88

99
## Installation ##
1010

11-
C++Spec is available as a single collated header-file that can be placed in any include path in your project. After that, all features are available via `#include "cppspec.hpp"`.
11+
C++Spec is available as a [single collated header-file]( that can be placed in any include path in your project. After that, all features are available via `#include "cppspec.hpp"`.
1212

1313
## Documentation ##
1414

15-
See [http://cppspec.readthedocs.org/]() for all documentation.
16-
17-
## Testing ##
15+
See [http://cppspec.readthedocs.org/](http://cppspec.readthedocs.org/) for full documentation and a tutorial.
1816

1917
## Requirements ##
2018

2119
C++Spec requires a compiler with support for C++11 and polymorphic lambda expressions from C++14. This includes GCC >= 4.9, MSVCC >= 14.0, or clang >= 3.4. For other compilers check [this chart](http://en.cppreference.com/w/cpp/compiler_support).
2220

2321
__Note:__ Only the tests require being compiled with C++14 support (`-std=c++14`). No other part of an existing project's build must be modified.
2422

23+
## Introduction ##
24+
25+
If you've ever used RSpec or Jasmine, chances are you'll be familiar with C++Spec's syntax. For example, this is a C++Spec version of the first snippet on RSpec's [README](https://github.com/rspec/rspec-core/blob/master/README.md#basic-structure).
26+
27+
```c++
28+
describe order_spec("Order", $ {
29+
it("sums the prices of its line items", _ {
30+
Order order();
31+
32+
order.add_entry(LineItem().set_item(Item()
33+
.set_price(Money(1.11, Money::USD))
34+
));
35+
36+
order.add_entry(LineItem().set_item(Item()
37+
.set_price(Money(1.11, Money::USD))
38+
.set_quantity(2)
39+
));
40+
41+
expect(order.total()).to_equal(Money(5.55, Money::USD));
42+
});
43+
});
44+
45+
```
46+
2547
## FAQ ##
2648
2749
## Attribution ##

examples/sample/example_spec.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@ describe bool_spec("Some Tests", $ {
3232

3333
explain("0 is", _ {
3434
it("between -1 and 1 (exclusive)", _ {
35-
expect(0).to_be_between(-1, 1, Matchers::RangeMode::exclusive);
35+
expect(0).to_be_between(-1, 1).exclusive();
3636
});
3737
it("between -0 and 0 (inclusive)", _ {
38-
expect(0).to_be_between(-0,0, Matchers::RangeMode::inclusive);
38+
expect(0).to_be_between(-0,0).inclusive();
3939
});
4040
it("not between -0 and 0 (exclusive)", _ {
41-
expect(0).not_().to_be_between(-0,0, Matchers::RangeMode::exclusive);
41+
expect(0).not_().to_be_between(-0,0).exclusive();
4242
});
43-
it("not between 1 and -1", _ {
44-
expect(0).not_().to_be_between(1,-1);
43+
it("not between 1 and -1 (inclusive)", _ {
44+
expect(0).not_().to_be_between(1,-1).inclusive();
4545
});
4646
it("between -1.0 and 1.0 (exclusive)", _ {
47-
expect(0).to_be_between(-1.0, 1.0, Matchers::RangeMode::exclusive);
47+
expect(0).to_be_between(-1.0, 1.0).exclusive();
4848
});
4949
});
5050

@@ -162,7 +162,7 @@ describe_a <std::vector<int>> vector_spec({1,2,3,4}, $ {
162162
int _count = 0;
163163
describe let_spec("let", $ {
164164
let(count, [&]{ return ++_count ;});
165-
165+
166166
it("memoizes the value", _ {
167167
expect(count).to_equal(1);
168168
expect(count).to_equal(1);

include/class_description.hpp

100644100755
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class ClassDescription : public Description {
2020
bool first;
2121

2222
public:
23-
T subject; // subject field exposed for usage in `expect([self.]subject)`
23+
T subject; // subject field public for usage in `expect([self.]subject)`
2424

2525
// Constructor
2626
// if there's no explicit subject given, then use
@@ -50,7 +50,7 @@ class ClassDescription : public Description {
5050

5151
template <typename U>
5252
ClassDescription(std::initializer_list<U> init_list, block_t body)
53-
: Description(), body(body), subject(T(init_list)) {
53+
: body(body), subject(T(init_list)) {
5454
this->descr = Pretty::to_word_type(subject);
5555
};
5656

@@ -150,8 +150,7 @@ bool Description::context(std::initializer_list<U> init_list,
150150
template <class T>
151151
bool ClassDescription<T>::it(std::string name,
152152
std::function<void(ItCd<T>&)> body) {
153-
ItCd<T> it(this->subject, name, body);
154-
it.set_parent(this);
153+
ItCd<T> it(*this, this->subject, name, body);
155154
bool result = it.run();
156155
exec_after_eaches();
157156
exec_before_eaches();
@@ -181,8 +180,7 @@ bool ClassDescription<T>::it(std::string name,
181180
*/
182181
template <class T>
183182
bool ClassDescription<T>::it(std::function<void(ItCd<T>&)> body) {
184-
ItCd<T> it(this->subject, body);
185-
it.set_parent(this);
183+
ItCd<T> it(*this, this->subject, body);
186184
bool result = it.run();
187185
exec_after_eaches();
188186
exec_before_eaches();
@@ -200,8 +198,7 @@ bool ClassDescription<T>::run() {
200198
template <class T>
201199
Expectations::Expectation<T> ItCd<T>::is_expected() {
202200
auto cd = static_cast<ClassDescription<T>*>(this->get_parent());
203-
Expectations::Expectation<T> expectation(cd->subject);
204-
expectation.set_parent(this);
201+
Expectations::Expectation<T> expectation(*this, cd->subject);
205202
return expectation;
206203
}
207204

include/cppspec.hpp

100644100755
File mode changed.

include/description.hpp

100644100755
Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ class Description : public Runnable {
2323
std::deque<rule_block_t> after_eaches;
2424
std::unordered_map<std::string, Runnable *> lets;
2525

26-
explicit Description(){};
27-
explicit Description(std::string descr) : descr(descr){};
26+
Description(){};
27+
Description(std::string descr) : descr(descr){};
28+
Description(Child &parent, std::string descr, block_t body)
29+
: Runnable(parent), body(body), descr(descr){};
2830

2931
public:
3032
// Constructor
@@ -40,21 +42,22 @@ class Description : public Runnable {
4042
template <class T>
4143
bool context(T subject, std::function<void(ClassDescription<T> &)> body);
4244

43-
template <class T>
44-
bool context(T &subject, std::function<void(ClassDescription<T> &)> body);
45+
// template <class T>
46+
// bool context(T &subject, std::function<void(ClassDescription<T> &)> body);
4547

4648
template <class T, typename U>
4749
bool context(std::initializer_list<U> init_list,
4850
std::function<void(ClassDescription<T> &)> body);
4951

50-
template <class T>
51-
ClassDescription<T> subject(T subject);
52-
53-
template <class T>
54-
ClassDescription<T> subject(T &subject);
55-
56-
template <class T>
57-
ClassDescription<std::vector<T>> subject(std::initializer_list<T> init_list);
52+
// template <class T>
53+
// ClassDescription<T> subject(T subject);
54+
//
55+
// template <class T>
56+
// ClassDescription<T> subject(T &subject);
57+
//
58+
// template <class T>
59+
// ClassDescription<std::vector<T>> subject(std::initializer_list<T>
60+
// init_list);
5861

5962
void before_each(rule_block_t block);
6063
void before_all(rule_block_t block);
@@ -73,52 +76,43 @@ typedef Description Context;
7376

7477
bool Description::context(std::string name,
7578
std::function<void(Description &)> body) {
76-
Context context(name, body);
77-
context.set_parent(this);
79+
Context context(*this, name, body);
7880
context.before_eaches = this->before_eaches;
7981
context.after_eaches = this->after_eaches;
8082
return context.run();
8183
}
8284

8385
bool Description::it(std::string name, std::function<void(ItD &)> body) {
84-
ItD it(name, body);
85-
it.set_parent(this);
86+
ItD it(*this, name, body);
8687
bool result = it.run();
8788
exec_after_eaches();
8889
exec_before_eaches();
8990
return result;
9091
}
9192

9293
bool Description::it(std::function<void(ItD &)> body) {
93-
ItD it(body);
94-
it.set_parent(this);
94+
ItD it(*this, body);
9595
bool result = it.run();
9696
exec_after_eaches();
9797
exec_before_eaches();
9898
return result;
9999
}
100100

101-
template <class U>
102-
ClassDescription<U> Description::subject(U subject) {
103-
ClassDescription<U> cd(this);
104-
cd->example = subject;
105-
return cd;
106-
}
107-
108-
template <class U>
109-
ClassDescription<U> Description::subject(U &subject) {
110-
ClassDescription<U> cd(this);
111-
cd->example = subject;
112-
return cd;
113-
}
114-
115-
template <class U>
116-
ClassDescription<std::vector<U>> Description::subject(
117-
std::initializer_list<U> init_list) {
118-
ClassDescription<U> cd(this);
119-
cd->example = std::vector<U>(init_list);
120-
return cd;
121-
}
101+
// template <class U>
102+
// ClassDescription<U> Description::subject(U subject) {
103+
// return ClassDescription<U>(*this, subject);
104+
//}
105+
//
106+
// template <class U>
107+
// ClassDescription<U> Description::subject(U &subject) {
108+
// return ClassDescription<U>(*this, subject);
109+
//}
110+
//
111+
// template <class U>
112+
// ClassDescription<std::vector<U>> Description::subject(
113+
// std::initializer_list<U> init_list) {
114+
// return ClassDescription<std::vector<U>>(*this, std::vector<U>(init_list));
115+
//}
122116

123117
void Description::before_each(rule_block_t b) {
124118
before_eaches.push_back(b);
@@ -127,9 +121,8 @@ void Description::before_each(rule_block_t b) {
127121
// the environment by executing the before_each, so that when an 'it'
128122
// declaration's lambda captures that env, it has the correct values for the
129123
// variables. Truthfully, 'before_each' is a misnomer, as they are not
130-
// getting
131-
// executed directly before the lambda's execution as one might expect, but
132-
// instead before the *next* lambda is declared.
124+
// getting executed directly before the lambda's execution as one might
125+
// expect, but instead before the *next* lambda is declared.
133126
b();
134127
}
135128

@@ -191,8 +184,7 @@ Expectations::Expectation<T> ItExpBase::expect(Let<T> let) {
191184
auto parent = static_cast<Description *>(this->get_parent());
192185
Let<T> *actual_let = static_cast<Let<T> *>(parent->find_let(let.get_name()));
193186
T res = actual_let->get_result();
194-
Expectations::Expectation<T> expectation(res);
195-
expectation.set_parent(this);
187+
Expectations::Expectation<T> expectation(*this, res);
196188
return expectation;
197189
}
198190

0 commit comments

Comments
 (0)