libwreport 3.42
testrunner.h
1#ifndef WREPORT_TESTSRUNNER_H
2#define WREPORT_TESTSRUNNER_H
3
4#include <functional>
5#include <memory>
6#include <string>
7#include <vector>
8
9namespace wreport::term {
10struct Terminal;
11}
12
13namespace wreport::tests {
14
15struct TestFailed;
16struct TestStack;
17struct TestCase;
18struct TestMethod;
19
23struct TestMethodResult
24{
26 std::string test_case;
27
29 std::string test_method;
30
32 std::string error_message;
33
35 std::shared_ptr<TestStack> error_stack;
36
38 std::string exception_typeid;
39
41 bool skipped = false;
42
44 std::string skipped_reason;
45
47 unsigned long long elapsed_ns = 0;
48
49 TestMethodResult(const std::string& test_case_,
50 const std::string& test_method_)
51 : test_case(test_case_), test_method(test_method_)
52 {
53 }
54
55 void set_failed(TestFailed& e);
56
57 void set_exception(std::exception& e)
58 {
59 error_message = e.what();
60 if (error_message.empty())
62 "test threw an exception with an empty error message";
63 exception_typeid = typeid(e).name();
64 }
65
66 void set_unknown_exception() { error_message = "unknown exception caught"; }
67
68 void set_setup_exception(std::exception& e)
69 {
70 error_message = "[setup failed: ";
71 error_message += e.what();
72 error_message += "]";
73 }
74
75 void set_teardown_exception(std::exception& e)
76 {
77 error_message = "[teardown failed: ";
78 error_message += e.what();
79 error_message += "]";
80 }
81
82 bool is_success() const { return error_message.empty(); }
83
84 void print_failure_details(FILE* out) const;
85};
86
90struct TestCaseResult
91{
93 std::string test_case;
95 std::vector<TestMethodResult> methods;
97 std::string fail_setup;
100 std::string fail_teardown;
102 bool skipped = false;
103
104 explicit TestCaseResult(const std::string& test_case_)
105 : test_case(test_case_)
106 {
107 }
108
109 void set_setup_failed()
110 {
111 fail_setup = "test case setup method threw an unknown exception";
112 }
113
114 void set_setup_failed(std::exception& e)
115 {
116 fail_setup = "test case setup method threw an exception: ";
117 fail_setup += e.what();
118 }
119
120 void set_teardown_failed()
121 {
122 fail_teardown = "test case teardown method threw an unknown exception";
123 }
124
125 void set_teardown_failed(std::exception& e)
126 {
127 fail_teardown = "test case teardown method threw an exception: ";
128 fail_teardown += e.what();
129 }
130
131 void add_test_method(TestMethodResult&& e)
132 {
133 methods.emplace_back(std::move(e));
134 }
135
136 bool is_success() const
137 {
138 if (!fail_setup.empty() || !fail_teardown.empty())
139 return false;
140 for (const auto& m : methods)
141 if (!m.is_success())
142 return false;
143 return true;
144 }
145
146 unsigned long long elapsed_ns() const;
147};
148
156{
157 virtual ~TestController() {}
158
165 virtual bool test_case_begin(const TestCase&, const TestCaseResult&)
166 {
167 return true;
168 }
169
173 virtual void test_case_end(const TestCase&, const TestCaseResult&) {}
174
181 virtual bool test_method_begin(const TestMethod&, const TestMethodResult&)
182 {
183 return true;
184 }
185
189 virtual void test_method_end(const TestMethod&, const TestMethodResult&) {}
190};
191
197{
199 std::string allowlist = std::string();
200
202 std::string blocklist = std::string();
203
204 bool test_method_should_run(const std::string& fullname) const;
205};
206
213struct SimpleTestController : public FilteringTestController
214{
216
217 SimpleTestController(wreport::term::Terminal& output);
218
219 bool test_case_begin(const TestCase& test_case,
220 const TestCaseResult& test_case_result) override;
221 void test_case_end(const TestCase& test_case,
222 const TestCaseResult& test_case_result) override;
223 bool test_method_begin(const TestMethod& test_method,
224 const TestMethodResult& test_method_result) override;
225 void test_method_end(const TestMethod& test_method,
226 const TestMethodResult& test_method_result) override;
227};
228
235struct VerboseTestController : public FilteringTestController
236{
238
239 VerboseTestController(wreport::term::Terminal& output);
240
241 bool test_case_begin(const TestCase& test_case,
242 const TestCaseResult& test_case_result) override;
243 void test_case_end(const TestCase& test_case,
244 const TestCaseResult& test_case_result) override;
245 bool test_method_begin(const TestMethod& test_method,
246 const TestMethodResult& test_method_result) override;
247 void test_method_end(const TestMethod& test_method,
248 const TestMethodResult& test_method_result) override;
249};
250
258{
260 std::vector<TestCase*> entries = std::vector<TestCase*>();
261
268 void register_test_case(TestCase& test_case);
269
277 std::function<void(const TestCase&, const TestMethod&)>);
278
282 std::vector<TestCaseResult> run_tests(TestController& controller);
283
285 static TestRegistry& get();
286};
287
288struct TestResultStats
289{
290 const std::vector<TestCaseResult>& results;
291 unsigned methods_ok = 0;
292 unsigned methods_failed = 0;
293 unsigned methods_skipped = 0;
294 unsigned test_cases_ok = 0;
295 unsigned test_cases_failed = 0;
296 bool success = false;
297 bool skipped = false;
298
299 TestResultStats(const std::vector<TestCaseResult>& results);
300
301 void print_results(wreport::term::Terminal& out);
302 void print_stats(wreport::term::Terminal& out);
303 void print_summary(wreport::term::Terminal& out);
304};
305
306} // namespace wreport::tests
307#endif
Contrl terminal output.
Definition term.h:14
Utility functions for the unit tests.
Definition tests.h:38
Definition term.h:17
Test controller that filters tests via a blocklist/allowlist system containing glob patterns on testc...
Definition testrunner.h:197
std::string blocklist
Any method matching this glob expression will not be run.
Definition testrunner.h:202
std::string allowlist
Any method not matching this glob expression will not be run.
Definition testrunner.h:199
void test_method_end(const TestMethod &test_method, const TestMethodResult &test_method_result) override
Called after running a test method.
bool test_method_begin(const TestMethod &test_method, const TestMethodResult &test_method_result) override
Called before running a test method.
void test_case_end(const TestCase &test_case, const TestCaseResult &test_case_result) override
Called after running a test case.
bool test_case_begin(const TestCase &test_case, const TestCaseResult &test_case_result) override
Called before running a test case.
Result of running a whole test case.
Definition testrunner.h:91
std::string fail_setup
Set to a non-empty string if the setup method of the test case failed.
Definition testrunner.h:97
std::string fail_teardown
Set to a non-empty string if the teardown method of the test case failed.
Definition testrunner.h:100
std::vector< TestMethodResult > methods
Outcome of all the methods that have been run.
Definition testrunner.h:95
bool skipped
Set to true if this test case has been skipped.
Definition testrunner.h:102
std::string test_case
Name of the test case.
Definition testrunner.h:93
Test case collecting several test methods, and self-registering with the singleton instance of TestRe...
Definition utils/tests.h:703
Abstract interface for the objects that supervise test execution.
Definition testrunner.h:156
virtual bool test_method_begin(const TestMethod &, const TestMethodResult &)
Called before running a test method.
Definition testrunner.h:181
virtual bool test_case_begin(const TestCase &, const TestCaseResult &)
Called before running a test case.
Definition testrunner.h:165
virtual void test_method_end(const TestMethod &, const TestMethodResult &)
Called after running a test method.
Definition testrunner.h:189
virtual void test_case_end(const TestCase &, const TestCaseResult &)
Called after running a test case.
Definition testrunner.h:173
Exception thrown when a test assertion fails, normally by Location::fail_test.
Definition utils/tests.h:104
Result of running a test method.
Definition testrunner.h:24
std::string skipped_reason
If the test has been skipped, this is an optional reason.
Definition testrunner.h:44
std::shared_ptr< TestStack > error_stack
Stack frame of where the error happened.
Definition testrunner.h:35
std::string test_case
Name of the test case.
Definition testrunner.h:26
bool skipped
True if the test has been skipped.
Definition testrunner.h:41
std::string error_message
If non-empty, the test failed with this error.
Definition testrunner.h:32
unsigned long long elapsed_ns
Time in nanoseconds it took the test to run.
Definition testrunner.h:47
std::string exception_typeid
If non-empty, the test threw an exception and this is its type ID.
Definition testrunner.h:38
std::string test_method
Name of the test method.
Definition testrunner.h:29
Test method information.
Definition utils/tests.h:676
Test registry.
Definition testrunner.h:258
void iterate_test_methods(std::function< void(const TestCase &, const TestMethod &)>)
Iterate on all test methods known by this registry.
std::vector< TestCaseResult > run_tests(TestController &controller)
Run all the registered tests using the given controller.
std::vector< TestCase * > entries
All known test cases.
Definition testrunner.h:260
void register_test_case(TestCase &test_case)
Register a new test case.
static TestRegistry & get()
Get the singleton instance of TestRegistry.
Definition utils/tests.h:89
void test_method_end(const TestMethod &test_method, const TestMethodResult &test_method_result) override
Called after running a test method.
bool test_case_begin(const TestCase &test_case, const TestCaseResult &test_case_result) override
Called before running a test case.
void test_case_end(const TestCase &test_case, const TestCaseResult &test_case_result) override
Called after running a test case.
bool test_method_begin(const TestMethod &test_method, const TestMethodResult &test_method_result) override
Called before running a test method.