Skip to content

Commit bd48b6a

Browse files
committed
Refactor Printer into Base and derived Formatters
1 parent 1b28971 commit bd48b6a

26 files changed

+503
-338
lines changed

examples/sample/example_spec.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ describe bool_spec("Some Tests", $ {
5454
});
5555
it("includes [1,2,3]", _ {
5656
expect({1,2,3}).to_include({1,2,8});
57+
expect({1,2,3}).to_include({1,2,7});
5758
});
5859
it("does not include 4", _ {
5960
expect({1,2,3}).not_().to_include({4});
@@ -183,13 +184,13 @@ describe let_spec("let", $ {
183184

184185
describe list_spec("A list spec", $ {
185186
explain <std::list<int>> ({1,2,3,4}, _ {
186-
it( _ { is_expected().to_include(6); });
187+
it( _ { is_expected().to_include(8); });
187188
});
188189
});
189190

190191
/* Here is the declaration of fabs description defined in an other file (fabs_spec.c in this sample)*/
191192
int main(){
192-
return CppSpec::Runner()
193+
return CppSpec::Runner(CppSpec::Formatters::verbose)
193194
.add_spec(bool_spec)
194195
.add_spec(abs_spec)
195196
.add_spec(strcmp_spec)

include/child.hpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace CppSpec {
66

7-
struct BasePrinter; // Forward declaration to allow reference
7+
namespace Formatters {
8+
class BaseFormatter; // Forward declaration to allow reference
9+
}
810

911
/**
1012
* @brief Base class for all objects in the execution tree.
@@ -21,20 +23,21 @@ class Child {
2123
// (`describe some_spec("a test", $ { ... });`). In order to use
2224
// a shared pointer, each object that is set as the parent must be
2325
// contained in a shared pointer. As tests are created by `describe ...`,
24-
// it is not wrapped by a shared pointer. Attempting to create this shared
25-
// pointer at some later time doesn't work, as it results in trying to delete
26-
// the current object `this` once the pointer goes out of scope.
27-
// Since children are always destroyed before their parents, this isn't a
28-
// problem anyways. In addition, any structures that are children are
29-
// allocated on the stack for speed reasons.
26+
// the root object is not wrapped by a shared pointer. Attempting to create
27+
// this shared pointer at some later time doesn't work, as it results in
28+
// trying to delete the current object `this` once the pointer goes out of
29+
// scope. Since children are always destroyed before their parents, this
30+
// isn't a problem anyways. In addition, any structures that are children
31+
// are allocated on the stack for speed reasons.
3032
Child *parent = nullptr;
3133

3234
// Represents whether the Child is healthy (has not failed).
3335
// A Child is healthy if and only if all of its children are healthy.
3436
// All instances of Child start out healthy.
3537
bool status = true;
3638

37-
BasePrinter *printer = nullptr;
39+
// TODO: Change this to a std::unique_ptr
40+
Formatters::BaseFormatter *formatter = nullptr;
3841

3942
public:
4043
// Default constructor/desctructor
@@ -57,7 +60,7 @@ class Child {
5760
/*--------- Parent helper functions -------------*/
5861

5962
/** @brief Check to see if the Child has a parent. */
60-
bool has_parent() { return parent != nullptr; }
63+
const bool has_parent() { return parent != nullptr; }
6164

6265
/** @brief Get the Child's parent. */
6366
Child *get_parent() { return parent; }
@@ -66,15 +69,17 @@ class Child {
6669
/** @brief Set the Child's parent */
6770
void set_parent(Child *parent) { this->parent = parent; }
6871

69-
/*--------- Printer helper functions -------------*/
70-
const bool has_printer(); // Check to see if the tree has a printer
71-
BasePrinter &get_printer(); // Get the printer from the tree
72-
void set_printer(BasePrinter &printer) { this->printer = &printer; }
72+
/*--------- Formatter helper functions -----------*/
73+
const bool has_formatter(); // Check to see if the tree has a printer
74+
Formatters::BaseFormatter &get_formatter(); // Get the printer from the tree
75+
void set_printer(Formatters::BaseFormatter &formatter) {
76+
this->formatter = &formatter;
77+
}
7378

7479
/*--------- Primary member functions -------------*/
7580

7681
/** @brief Get the status of the object (success/failure) */
77-
bool get_status() { return this->status; }
82+
const bool get_status() { return this->status; }
7883

7984
void failed(); // Report failure to the object.
8085
std::string padding(); // Calculate the padding for printing this object
@@ -95,23 +100,25 @@ void Child::failed() {
95100
}
96101

97102
/**
98-
* @brief Get the padding (indentation) of the current object.
103+
* @brief Generate padding (indentation) fore the current object.
99104
* @return A string of spaces for use in pretty-printing.
100105
*/
101106
std::string Child::padding() {
102107
return has_parent() ? get_parent()->padding() + " " : "";
103108
}
104109

105-
const bool Child::has_printer() {
106-
if (this->printer != nullptr) return true;
107-
if (parent == nullptr) return false; // base case;
108-
return parent->has_printer();
110+
const bool Child::has_formatter() {
111+
if (this->formatter != nullptr) return true;
112+
if (!this->has_parent()) return false; // base case;
113+
return parent->has_formatter();
109114
}
110115

111-
BasePrinter &Child::get_printer() {
112-
if (this->printer != nullptr) return *printer;
113-
if (parent == nullptr) throw "Couldn't get printer!"; // base case;
114-
return parent->get_printer();
116+
Formatters::BaseFormatter &Child::get_formatter() {
117+
if (this->formatter != nullptr) return *formatter;
118+
if (!this->has_parent())
119+
throw "Couldn't get printer!"; // base case. This should never *ever*
120+
// happen.
121+
return parent->get_formatter();
115122
}
116123

117124
} // ::CppSpec

include/class_description.hpp

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@ class ClassDescription : public Description {
7979
Result context(T subject, block_t body);
8080
Result context(T &subject, block_t body);
8181
Result context(block_t body);
82-
Result run(BasePrinter &printer) override;
83-
virtual std::string get_descr() override;
84-
virtual const std::string get_descr() const override;
82+
Result run(Formatters::BaseFormatter &printer) override;
83+
virtual std::string get_descr() override { return descr; }
84+
virtual const std::string get_descr() const override { return descr; }
85+
virtual std::string get_subject_type() override { return type; }
86+
virtual const std::string get_subject_type() const override { return type; }
8587
};
8688

8789
template <class T>
@@ -94,7 +96,7 @@ Result ClassDescription<T>::context(
9496
context.set_parent(this);
9597
context.before_eaches = this->before_eaches;
9698
context.after_eaches = this->after_eaches;
97-
return context.run(this->get_printer());
99+
return context.run(this->get_formatter());
98100
}
99101

100102
template <class T>
@@ -110,7 +112,7 @@ Result ClassDescription<T>::context(
110112
context.set_parent(this);
111113
context.before_eaches = this->before_eaches;
112114
context.after_eaches = this->after_eaches;
113-
return context.run(this->get_printer());
115+
return context.run(this->get_formatter());
114116
}
115117

116118
template <class T>
@@ -121,7 +123,7 @@ Result Description::context(T subject,
121123
context.set_parent(this);
122124
context.before_eaches = this->before_eaches;
123125
context.after_eaches = this->after_eaches;
124-
return context.run(this->get_printer());
126+
return context.run(this->get_formatter());
125127
}
126128

127129
// template <class T>
@@ -137,7 +139,7 @@ Result Description::context(std::initializer_list<U> init_list,
137139
context.set_parent(this);
138140
context.before_eaches = this->before_eaches;
139141
context.after_eaches = this->after_eaches;
140-
return context.run(this->get_printer());
142+
return context.run(this->get_formatter());
141143
}
142144

143145
/**
@@ -165,7 +167,7 @@ template <class T>
165167
Result ClassDescription<T>::it(std::string name,
166168
std::function<void(ItCd<T> &)> body) {
167169
ItCd<T> it(*this, this->subject, name, body);
168-
Result result = it.run(this->get_printer());
170+
Result result = it.run(this->get_formatter());
169171
exec_after_eaches();
170172
exec_before_eaches();
171173
return result;
@@ -195,39 +197,21 @@ Result ClassDescription<T>::it(std::string name,
195197
template <class T>
196198
Result ClassDescription<T>::it(std::function<void(ItCd<T> &)> body) {
197199
ItCd<T> it(*this, this->subject, body);
198-
Result result = it.run(this->get_printer());
200+
Result result = it.run(this->get_formatter());
199201
exec_after_eaches();
200202
exec_before_eaches();
201203
return result;
202204
}
203205

204206
template <class T>
205-
Result ClassDescription<T>::run(BasePrinter &printer) {
206-
if (not this->has_printer()) this->set_printer(printer);
207-
printer.print(*this);
207+
Result ClassDescription<T>::run(Formatters::BaseFormatter &printer) {
208+
if (not this->has_formatter()) this->set_printer(printer);
209+
printer.format(*this);
208210
body(*this);
209211
for (auto a : after_alls) a();
210212
if (this->get_parent() == nullptr) printer.flush();
211213
return this->get_status() ? Result::success : Result::failure;
212214
}
213-
template <class T>
214-
std::string ClassDescription<T>::get_descr() {
215-
if (this->get_printer().mode == BasePrinter::Mode::TAP) {
216-
return descr;
217-
} else {
218-
return descr + type;
219-
}
220-
}
221-
222-
template <class T>
223-
const std::string ClassDescription<T>::get_descr() const {
224-
if (const_cast<ClassDescription<T> *>(this)->get_printer().mode ==
225-
BasePrinter::Mode::TAP) {
226-
return descr;
227-
} else {
228-
return descr + type;
229-
}
230-
}
231215

232216
template <class T>
233217
Expectations::Expectation<T> ItCd<T>::is_expected() {
@@ -237,17 +221,13 @@ Expectations::Expectation<T> ItCd<T>::is_expected() {
237221
}
238222

239223
template <class T>
240-
Result ItCd<T>::run(BasePrinter &printer) {
241-
if (!this->needs_descr() && printer.mode == BasePrinter::Mode::verbose) {
242-
printer.print(*this);
243-
}
224+
Result ItCd<T>::run(Formatters::BaseFormatter &printer) {
225+
// if (!this->needs_descr() && printer.mode == BaseFormatter::Mode::verbose) {
226+
// printer.format(*this);
227+
// }
244228

245229
body(*this);
246-
247-
if (printer.mode == BasePrinter::Mode::TAP ||
248-
printer.mode == BasePrinter::Mode::terse) {
249-
printer.print(*this);
250-
}
230+
printer.format(*this);
251231

252232
auto cd = static_cast<ClassDescription<T> *>(this->get_parent());
253233
cd->reset_lets();

include/cppspec.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55
#ifndef CPPSPEC_HPP
66
#define CPPSPEC_HPP
7+
#include "formatters/tap.hpp"
8+
#include "formatters/verbose.hpp"
9+
#include "formatters/progress.hpp"
710
#include "runner.hpp"
811

912
#define _ [=](auto &self) mutable

include/description.hpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,13 @@ class Description : public Runnable {
7171
template <typename T>
7272
auto make_let(std::string name, T body) -> Let<decltype(body())>;
7373
void add_let(std::string name, Runnable &body);
74-
virtual Result run(BasePrinter &printer) override;
74+
virtual Result run(Formatters::BaseFormatter &printer) override;
7575
void reset_lets();
7676
Runnable *find_let(std::string);
7777
virtual std::string get_descr() { return descr; }
7878
virtual const std::string get_descr() const { return descr; }
79+
virtual std::string get_subject_type() { return ""; }
80+
virtual const std::string get_subject_type() const { return ""; }
7981
};
8082

8183
typedef Description Context;
@@ -85,20 +87,20 @@ Result Description::context(std::string name,
8587
Context context(*this, name, body);
8688
context.before_eaches = this->before_eaches;
8789
context.after_eaches = this->after_eaches;
88-
return context.run(this->get_printer());
90+
return context.run(this->get_formatter());
8991
}
9092

9193
Result Description::it(std::string name, std::function<void(ItD &)> body) {
9294
ItD it(*this, name, body);
93-
Result result = it.run(this->get_printer());
95+
Result result = it.run(this->get_formatter());
9496
exec_after_eaches();
9597
exec_before_eaches();
9698
return result;
9799
}
98100

99101
Result Description::it(std::function<void(ItD &)> body) {
100102
ItD it(*this, body);
101-
Result result = it.run(this->get_printer());
103+
Result result = it.run(this->get_formatter());
102104
exec_after_eaches();
103105
exec_before_eaches();
104106
return result;
@@ -162,9 +164,9 @@ void Description::add_let(std::string name, Runnable &body) {
162164
lets.insert({name, &body});
163165
}
164166

165-
Result Description::run(BasePrinter &printer) {
166-
if (not this->has_printer()) this->set_printer(printer);
167-
printer.print(*this);
167+
Result Description::run(Formatters::BaseFormatter &printer) {
168+
if (not this->has_formatter()) this->set_printer(printer);
169+
printer.format(*this);
168170
body(*this);
169171
for (auto a : after_alls) a();
170172
if (this->get_parent() == nullptr) printer.flush();
@@ -207,17 +209,14 @@ Expectations::Expectation<T> ItExpBase::expect(Let<T> let) {
207209
return expectation;
208210
}
209211

210-
Result ItD::run(BasePrinter &printer) {
211-
if (!this->needs_descr() && printer.mode == BasePrinter::Mode::verbose) {
212-
printer.print(*this);
213-
}
212+
Result ItD::run(Formatters::BaseFormatter &printer) {
213+
// if (!this->needs_descr() && printer.mode == BaseFormatter::Mode::verbose) {
214+
// printer.format(*this);
215+
// }
214216

215217
body(*this);
216218

217-
if (printer.mode == BasePrinter::Mode::TAP ||
218-
printer.mode == BasePrinter::Mode::terse) {
219-
printer.print(*this);
220-
}
219+
printer.format(*this);
221220

222221
auto parent = static_cast<Description *>(this->get_parent());
223222
parent->reset_lets();

0 commit comments

Comments
 (0)