Skip to content

Commit 1b28971

Browse files
committed
Fancy runner
1 parent fb239fb commit 1b28971

File tree

10 files changed

+129
-36
lines changed

10 files changed

+129
-36
lines changed

Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ EXCLUDE_SYMLINKS = NO
805805
# Note that the wildcards are matched against the file with absolute path, so to
806806
# exclude all test directories for example use the pattern */test/*
807807

808-
EXCLUDE_PATTERNS = */test/* */cxx-prettyprint/*
808+
EXCLUDE_PATTERNS = */test/* */cxx-prettyprint/* */optional/*
809809

810810
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
811811
# (namespaces, classes, functions, etc.) that should be excluded from the

examples/sample/example_spec.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe bool_spec("Some Tests", $ {
5353
expect({1,2,3}).to_include({1});
5454
});
5555
it("includes [1,2,3]", _ {
56-
expect({1,2,3}).to_include({1,2,3});
56+
expect({1,2,3}).to_include({1,2,8});
5757
});
5858
it("does not include 4", _ {
5959
expect({1,2,3}).not_().to_include({4});
@@ -109,7 +109,7 @@ describe abs_spec("abs", $ {
109109
});
110110

111111
before_all([]{ std::srand(std::time(0)); });
112-
112+
113113
int n = 0;
114114
before_each([&]{ n = std::rand(); });
115115

@@ -189,13 +189,12 @@ describe list_spec("A list spec", $ {
189189

190190
/* Here is the declaration of fabs description defined in an other file (fabs_spec.c in this sample)*/
191191
int main(){
192-
bool r = true;
193-
auto printer = CppSpec::Printer::verbose;
194-
r &= bool_spec.run(printer);
195-
r &= abs_spec.run(printer);
196-
r &= strcmp_spec.run(printer);
197-
r &= vector_spec.run(printer);
198-
r &= let_spec.run(printer);
199-
r &= list_spec.run(printer);
200-
return r ? EXIT_SUCCESS : EXIT_FAILURE;
192+
return CppSpec::Runner()
193+
.add_spec(bool_spec)
194+
.add_spec(abs_spec)
195+
.add_spec(strcmp_spec)
196+
.add_spec(vector_spec)
197+
.add_spec(let_spec)
198+
.add_spec(list_spec)
199+
.exec() ? EXIT_SUCCESS : EXIT_FAILURE;
201200
}

include/child.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace CppSpec {
66

7-
struct BasePrinter;
7+
struct BasePrinter; // Forward declaration to allow reference
88

99
/**
1010
* @brief Base class for all objects in the execution tree.

include/class_description.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,5 +254,5 @@ Result ItCd<T>::run(BasePrinter &printer) {
254254
return this->get_status() ? Result::success : Result::failure;
255255
}
256256

257-
} // ::CppSpec
258-
#endif // CPPSPEC_CLASS_DESCRIPTION_HPP
257+
} // ::CppSpec
258+
#endif // CPPSPEC_CLASS_DESCRIPTION_HPP

include/cppspec.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* @file
33
* @brief The core header file for Cppspec
44
*/
5-
6-
#include "printer.hpp"
5+
#ifndef CPPSPEC_HPP
6+
#define CPPSPEC_HPP
7+
#include "runner.hpp"
78

89
#define _ [=](auto &self) mutable
910
#define $ [](auto &self)
@@ -18,11 +19,13 @@
1819
#define before_each self.before_each
1920
#define after_all self.after_all
2021
#define after_each self.after_each
21-
#define let(name, body) \
22+
#define let(name, body) \
2223
auto name = self.make_let(#name, body); \
23-
self.let(#name, name);
24+
self.add_let(#name, name);
2425

2526
typedef CppSpec::Description describe;
2627

2728
template <class T>
2829
using describe_a = CppSpec::ClassDescription<T>;
30+
31+
#endif // CPPSPEC_HPP

include/description.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class Description : public Runnable {
7070

7171
template <typename T>
7272
auto make_let(std::string name, T body) -> Let<decltype(body())>;
73-
void let(std::string name, Runnable &body);
73+
void add_let(std::string name, Runnable &body);
7474
virtual Result run(BasePrinter &printer) override;
7575
void reset_lets();
7676
Runnable *find_let(std::string);
@@ -158,7 +158,7 @@ auto Description::make_let(std::string name, T body) -> Let<decltype(body())> {
158158
return Let<decltype(body())>(*this, name, body);
159159
}
160160

161-
void Description::let(std::string name, Runnable &body) {
161+
void Description::add_let(std::string name, Runnable &body) {
162162
lets.insert({name, &body});
163163
}
164164

include/printer.hpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef CPP_SPEC_PRINTER_HPP
2-
#define CPP_SPEC_PRINTER_HPP
1+
#ifndef CPPSPEC_PRINTER_HPP
2+
#define CPPSPEC_PRINTER_HPP
33
// the following are UBUNTU/LINUX ONLY terminal color codes.
44
#define RESET "\033[0m"
55
#define BLACK "\033[30m" /* Black */
@@ -26,6 +26,9 @@ namespace CppSpec {
2626
class PrettyPrinter : public BasePrinter {
2727
int test_counter = 1;
2828
std::stringstream buffer;
29+
std::shared_ptr<std::list<std::string>> failures =
30+
std::make_shared<std::list<std::string>>(); // empty list by default
31+
2932
bool first = true;
3033

3134
public:
@@ -34,9 +37,12 @@ class PrettyPrinter : public BasePrinter {
3437
test_counter(copy.test_counter),
3538
first(copy.first) {
3639
buffer << copy.buffer.str();
37-
}
40+
};
3841

3942
PrettyPrinter(Mode mode) : BasePrinter(mode){};
43+
PrettyPrinter(Mode mode, std::shared_ptr<std::list<std::string>> failures)
44+
: BasePrinter(mode), failures(failures){};
45+
4046
// template <class C>
4147
// void print(ClassDescription<C> &runnable);
4248
void print(Description &runnable) override;
@@ -99,24 +105,42 @@ void PrettyPrinter::print_failure(std::string message) {
99105
// Diff diff = differ.diff(actual, expected)
100106
// Throwing exceptions in Ruby is totally different from C++. Gonna just
101107
// stdout this thing.
108+
std::ostringstream oss;
102109
switch (mode) {
103110
case Mode::verbose:
104111
std::cout << RED << message << RESET << std::endl;
112+
// failures->push_back(message);
105113
case Mode::terse:
106-
buffer << std::endl
107-
<< RED << "Test number " << test_counter << " failed:" << std::endl
108-
<< message << RESET;
114+
// failure_buffer << std::endl << RED
115+
116+
oss << "Test number " << test_counter << " failed:" << std::endl
117+
<< message;
118+
//<< RESET;
119+
failures->push_back(oss.str());
109120
default:
110121
break;
111122
}
112123
}
113124

125+
/**
126+
* Gets called at the end of printing an entire spec (!this->has_parent())
127+
*/
114128
void PrettyPrinter::flush() {
115129
std::string str = buffer.str();
116130
std::stringstream ss;
117131
switch (mode) {
118132
case Mode::terse:
119-
if (not str.empty()) std::cout << std::endl << str << std::endl;
133+
if (failures.unique()) { // this means that it's *our* list of failures
134+
// not a runner's
135+
std::cout << std::endl; // If that's true; print a newline
136+
if (not failures->empty()) { // If we have any failures to print
137+
std::cout << RED // make them red
138+
<< Util::join(*failures, "\n\n") // print them
139+
<< RESET << std::endl; // and print a newline
140+
failures->clear(); // finally, clear the failures list.
141+
}
142+
test_counter = 1; // and reset the test counter
143+
}
120144
break;
121145
case Mode::TAP:
122146
if (str[0] == '\n') {
@@ -126,12 +150,12 @@ void PrettyPrinter::flush() {
126150
ss << "1.." << test_counter - 1 << std::endl << str;
127151
}
128152
std::cout << ss.str() << std::flush;
129-
buffer = std::stringstream();
130153
first = false;
131154
default:
132155
test_counter = 1;
133156
break;
134157
}
158+
buffer = std::stringstream();
135159
}
136160

137161
namespace Printer {
@@ -141,4 +165,4 @@ static PrettyPrinter TAP = PrettyPrinter(PrettyPrinter::Mode::TAP);
141165
}
142166

143167
} // ::CppSpec
144-
#endif // CPP_SPEC_PRINTER_HPP
168+
#endif // CPPSPEC_PRINTER_HPP

include/result.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ namespace CppSpec {
66

77
class Result {
88
const bool value;
9-
std::string message = "";
10-
Result(bool value) : value(value) { };
9+
std::string message;
10+
Result(bool value, std::string message = "")
11+
: value(value), message(message){};
1112

1213
public:
1314
// Default destructor
@@ -51,12 +52,12 @@ inline Result &Result::set_message(std::string message) {
5152

5253
Result Result::success = Result(true);
5354
inline Result Result::success_with(std::string success_message) {
54-
return success.set_message(success_message);
55+
return Result(true, success_message);
5556
}
5657

5758
Result Result::failure = Result(false);
5859
inline Result Result::failure_with(std::string failure_message) {
59-
return failure.set_message(failure_message);
60+
return Result(false, failure_message);
6061
}
6162

6263
std::ostream &operator<<(std::ostream &os, const Result &res) {
@@ -70,5 +71,5 @@ std::ostream &operator<<(std::ostream &os, const Result &res) {
7071
return os << ss.str();
7172
}
7273

73-
} //::CppSpec
74+
} //::CppSpec
7475
#endif // CPPSPEC_RESULT_HPP

include/runner.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#ifndef CPPSPEC_RUNNER_HPP
2+
#define CPPSPEC_RUNNER_HPP
3+
#include <list>
4+
#include "printer.hpp"
5+
6+
namespace CppSpec {
7+
8+
class Runner {
9+
std::list<Description *> specs;
10+
PrettyPrinter &printer = Printer::terse;
11+
12+
public:
13+
Runner() = default;
14+
15+
Runner(PrettyPrinter &printer) : printer(printer){};
16+
17+
template <typename T>
18+
Runner &add_spec(ClassDescription<T> &spec);
19+
Runner &add_spec(Description &spec);
20+
Result run(BasePrinter &printer);
21+
Result exec();
22+
};
23+
24+
template <typename T>
25+
Runner &Runner::add_spec(ClassDescription<T> &spec) {
26+
specs.push_back(&spec);
27+
return *this;
28+
}
29+
30+
Runner &Runner::add_spec(Description &spec) {
31+
specs.push_back(&spec);
32+
return *this;
33+
}
34+
35+
Result Runner::run(BasePrinter &printer) {
36+
bool success = true;
37+
for (auto spec : specs) {
38+
success &= static_cast<bool>(spec->run(printer));
39+
}
40+
return success ? Result::success : Result::failure;
41+
}
42+
43+
Result Runner::exec() {
44+
if (this->printer.mode == BasePrinter::Mode::terse) {
45+
auto failures = std::make_shared<std::list<std::string>>();
46+
PrettyPrinter printer(this->printer.mode, failures);
47+
Result result = this->run(printer);
48+
std::cout << RED << std::endl << Util::join<std::list<std::string>>(*failures, "\n\n") << RESET << std::endl;
49+
return result;
50+
} else {
51+
return this->run(printer);
52+
}
53+
}
54+
}
55+
#endif // CPPSPEC_RUNNER_HPP

include/util.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,17 @@ std::string inspect_object<std::string>(std::string &o) {
235235
return ss.str();
236236
}
237237

238+
template <typename Range>
239+
std::string join(Range &iterable, const std::string &sep) {
240+
std::ostringstream oss;
241+
typename Range::const_iterator it;
242+
for (it = iterable.cbegin(); it != iterable.cend(); it++) {
243+
oss << *it;
244+
if (it != --iterable.cend()) oss << sep;
245+
}
246+
return oss.str();
247+
}
248+
238249
} // ::Util
239250
} // ::CppSpec
240-
#endif // CPPSPEC_UTIL_HPP
251+
#endif // CPPSPEC_UTIL_HPP

0 commit comments

Comments
 (0)