ZeroErr
Loading...
Searching...
No Matches
unittest.h
Go to the documentation of this file.
1#pragma once
2
4
5#include <chrono>
6#include <functional>
7#include <string>
8#include <vector>
9
11
12#define ZEROERR_CREATE_TEST_FUNC(function, name, ...) \
13 ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH \
14 static void function(zeroerr::TestContext*); \
15 static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
16 zeroerr::TestCase(name, __FILE__, __LINE__, function, {__VA_ARGS__})); \
17 ZEROERR_SUPPRESS_COMMON_WARNINGS_POP; \
18 static void function(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
19
20#define TEST_CASE(...) \
21 ZEROERR_EXPAND(ZEROERR_CREATE_TEST_FUNC(ZEROERR_NAMEGEN(_zeroerr_testcase), __VA_ARGS__))
22
23#define ZEROERR_CREATE_SUB_CASE(name, ...) \
24 zeroerr::SubCase(name, __FILE__, __LINE__, _ZEROERR_TEST_CONTEXT, {__VA_ARGS__}) \
25 << [=](ZEROERR_UNUSED(zeroerr::TestContext * _ZEROERR_TEST_CONTEXT)) mutable
26
27#define SUB_CASE(...) \
28 ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH \
29 ZEROERR_EXPAND(ZEROERR_CREATE_SUB_CASE(__VA_ARGS__)) \
30 ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
31
32#define ZEROERR_CREATE_TEST_CLASS(fixture, classname, funcname, name, ...) \
33 class classname : public fixture { \
34 public: \
35 void funcname(zeroerr::TestContext*); \
36 }; \
37 static void ZEROERR_CAT(call_, funcname)(zeroerr::TestContext * _ZEROERR_TEST_CONTEXT) { \
38 classname instance; \
39 instance.funcname(_ZEROERR_TEST_CONTEXT); \
40 } \
41 static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
42 zeroerr::TestCase(name, __FILE__, __LINE__, ZEROERR_CAT(call_, funcname), \
43 {__VA_ARGS__})); \
44 inline void classname::funcname(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
45
46#define TEST_CASE_FIXTURE(fixture, ...) \
47 ZEROERR_EXPAND(ZEROERR_CREATE_TEST_CLASS(fixture, ZEROERR_NAMEGEN(_zeroerr_class), \
48 ZEROERR_NAMEGEN(_zeroerr_test_method), __VA_ARGS__))
49
50
51#define ZEROERR_HAVE_SAME_OUTPUT _ZEROERR_TEST_CONTEXT->save_output();
52
53#ifndef ZEROERR_DISABLE_BDD
54#define SCENARIO(...) TEST_CASE("Scenario: " __VA_ARGS__)
55#define GIVEN(...) SUB_CASE("given: " __VA_ARGS__)
56#define WHEN(...) SUB_CASE("when: " __VA_ARGS__)
57#define THEN(...) SUB_CASE("then: " __VA_ARGS__)
58#endif
59
60namespace zeroerr {
61
62class IReporter;
63struct TestCase;
64class Decorator;
65
79public:
80 unsigned passed = 0;
81 unsigned warning = 0;
82 unsigned failed = 0;
83 unsigned skipped = 0;
84 unsigned passed_as = 0;
85 unsigned warning_as = 0;
86 unsigned failed_as = 0;
87 unsigned skipped_as = 0;
88
89 std::chrono::duration<double> duration = std::chrono::duration<double>::zero();
90
92
98 int add(TestContext& local);
99
103 void reset();
104
108 void save_output();
109
115 ~TestContext() = default;
116};
117
132struct UnitTest {
139 UnitTest& parseArgs(int argc, const char** argv);
140
145 int run();
146
153 bool run_filter(const TestCase& tc);
154
155 bool silent = false;
156 bool run_bench = false;
157 bool run_fuzz = false;
158 bool list_test_cases = false;
159 bool no_color = false;
160 bool log_to_report = false;
162 std::string reporter_name = "console";
163 std::string binary;
165};
166
176struct TestCase {
177 std::string name;
178 std::string file;
179 unsigned line;
180 std::function<void(TestContext*)> func;
181 std::vector<TestCase*> subcases;
182 std::vector<Decorator*> decorators;
188 bool operator<(const TestCase& rhs) const;
189
196 TestCase(std::string name, std::string file, unsigned line, std::vector<Decorator*> decorators)
198
207 TestCase(std::string name, std::string file, unsigned line,
208 std::function<void(TestContext*)> func, std::vector<Decorator*> decorators)
210};
211
212
217 SubCase(std::string name, std::string file, unsigned line, TestContext* context,
218 std::vector<Decorator*> decorators);
219 ~SubCase() = default;
221 void operator<<(std::function<void(TestContext*)> op);
222};
223
224
225template <typename T>
227 void add(T&& obj) { objects.push_back(std::forward<T>(obj)); }
228 std::vector<T> objects;
229};
230
231
244public:
245 virtual ~IReporter() = default;
246
247 virtual std::string getName() const = 0;
248
249 // There are a list of events
250 virtual void testStart() = 0;
251 virtual void testCaseStart(const TestCase& tc, std::stringbuf& sb) = 0;
252 virtual void testCaseEnd(const TestCase& tc, std::stringbuf& sb, const TestContext& ctx,
253 int type) = 0;
254 virtual void subCaseStart(const TestCase& tc, std::stringbuf& sb) = 0;
255 virtual void subCaseEnd(const TestCase& tc, std::stringbuf& sb, const TestContext& ctx,
256 int type) = 0;
257 virtual void testEnd(const TestContext& tc) = 0;
258
264 static IReporter* create(const std::string& name, UnitTest& ut);
265
267
268protected:
270};
271
275enum TestType { test_case = 1, sub_case = 1 << 1, bench = 1 << 2, fuzz_test = 1 << 3 };
276
277namespace detail {
278
283struct regTest {
284 explicit regTest(const TestCase& tc, TestType type = test_case);
285};
286
292 explicit regReporter(IReporter*);
293};
294} // namespace detail
295
296
313public:
314 CombinationalTest(std::function<void()> func) : func(func) {}
315 std::function<void()> func;
316
317 template <typename T>
318 void operator()(T& arg) {
319 arg.reset();
320 for (size_t i = 0; i < arg.size(); ++i, ++arg) {
321 func();
322 }
323 }
324
325 template <typename T, typename... Args>
326 void operator()(T& arg, Args&... args) {
327 arg.reset();
328 for (size_t i = 0; i < arg.size(); ++i, ++arg) {
329 operator()(args...);
330 }
331 }
332};
333
334
338template <typename T>
339class TestArgs {
340public:
341 TestArgs(std::initializer_list<T> args) : args(args) {}
342 std::vector<T> args;
343
344 operator T() const { return args[index]; }
346 index++;
347 return *this;
348 }
349 size_t size() const { return args.size(); }
350 void reset() { index = 0; }
351
352private:
353 int index = 0;
354};
355
356
358public:
359 // Called when the test registered, return true can block the test registering
360 virtual bool onStartup(const TestCase&) { return false; }
361
362 // Called when the test executing, return true can block the test execution
363 virtual bool onExecution(const TestCase&) { return false; }
364
365 // Called on each assertion, return true can skip the assertion
366 virtual bool onAssertion() { return false; }
367
368 // Called when the test finished, return true means the test containing changes
369 virtual bool onFinish(const TestCase&, TestContext&) { return false; }
370};
371
372Decorator* skip(bool isSkip = true);
373Decorator* timeout(float timeout = 0.1f); // in seconds
374Decorator* may_fail(bool isMayFail = true);
375Decorator* should_fail(bool isShouldFail = true);
376
377} // namespace zeroerr
378
CombinationalTest is a class that is used to cross test a few lists of arguments. One example.
Definition unittest.h:312
std::function< void()> func
Definition unittest.h:315
void operator()(T &arg, Args &... args)
Definition unittest.h:326
void operator()(T &arg)
Definition unittest.h:318
CombinationalTest(std::function< void()> func)
Definition unittest.h:314
Definition unittest.h:357
virtual bool onAssertion()
Definition unittest.h:366
virtual bool onStartup(const TestCase &)
Definition unittest.h:360
virtual bool onExecution(const TestCase &)
Definition unittest.h:363
virtual bool onFinish(const TestCase &, TestContext &)
Definition unittest.h:369
IReporter is an interface that is used to report the test results. You can create a new reporter by i...
Definition unittest.h:243
virtual void subCaseStart(const TestCase &tc, std::stringbuf &sb)=0
static IReporter * create(const std::string &name, UnitTest &ut)
Create the reporter object with the given name.
Definition unittest.cpp:817
virtual ~IReporter()=default
virtual void testStart()=0
virtual void testCaseStart(const TestCase &tc, std::stringbuf &sb)=0
virtual void subCaseEnd(const TestCase &tc, std::stringbuf &sb, const TestContext &ctx, int type)=0
virtual void testEnd(const TestContext &tc)=0
virtual std::string getName() const =0
UnitTest & ut
Definition unittest.h:269
IReporter(UnitTest &ut)
Definition unittest.h:266
virtual void testCaseEnd(const TestCase &tc, std::stringbuf &sb, const TestContext &ctx, int type)=0
TestArgs is a class that is used to store the test arguments.
Definition unittest.h:339
TestArgs & operator++()
Definition unittest.h:345
size_t size() const
Definition unittest.h:349
std::vector< T > args
Definition unittest.h:342
TestArgs(std::initializer_list< T > args)
Definition unittest.h:341
void reset()
Definition unittest.h:350
TestContext is a class that holds the test results and reporter context. There are 8 different matric...
Definition unittest.h:78
void reset()
Reset the matrices to 0.
Definition unittest.cpp:65
unsigned skipped
Definition unittest.h:83
unsigned failed
Definition unittest.h:82
unsigned passed
Definition unittest.h:80
void save_output()
Save the output of the test to the correct_output_path as a golden file.
Definition unittest.cpp:45
std::chrono::duration< double > duration
Definition unittest.h:89
unsigned skipped_as
Definition unittest.h:87
unsigned passed_as
Definition unittest.h:84
unsigned failed_as
Definition unittest.h:86
IReporter & reporter
Definition unittest.h:91
unsigned warning
Definition unittest.h:81
unsigned warning_as
Definition unittest.h:85
TestContext(IReporter &reporter)
Construct a new Test Context object.
Definition unittest.h:114
int add(TestContext &local)
Add the subtest results to the matrices.
Definition unittest.cpp:24
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:272
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:224
Definition benchmark.cpp:17
Decorator * should_fail(bool isShouldFail)
Definition unittest.cpp:900
TestType
TestType is a enum describe the type of the test case.
Definition unittest.h:275
@ bench
Definition unittest.h:275
@ test_case
Definition unittest.h:275
@ fuzz_test
Definition unittest.h:275
@ sub_case
Definition unittest.h:275
Decorator * timeout(float timeout)
Definition unittest.cpp:850
Decorator * may_fail(bool isMayFail)
Definition unittest.cpp:894
Decorator * skip(bool isSkip)
Definition unittest.cpp:828
Definition unittest.cpp:105
SubCase is a class that holds the subcase information.
Definition unittest.h:216
TestContext * context
Definition unittest.h:220
void operator<<(std::function< void(TestContext *)> op)
Definition unittest.cpp:82
~SubCase()=default
TestCase is a class that holds the test case information. There are several fields that are used to s...
Definition unittest.h:176
bool operator<(const TestCase &rhs) const
Compare the test cases.
Definition unittest.cpp:308
std::function< void(TestContext *)> func
Definition unittest.h:180
std::vector< Decorator * > decorators
Definition unittest.h:182
TestCase(std::string name, std::string file, unsigned line, std::function< void(TestContext *)> func, std::vector< Decorator * > decorators)
Construct a new Test Case object.
Definition unittest.h:207
std::string file
Definition unittest.h:178
unsigned line
Definition unittest.h:179
std::vector< TestCase * > subcases
Definition unittest.h:181
TestCase(std::string name, std::string file, unsigned line, std::vector< Decorator * > decorators)
Construct a new Test Case object.
Definition unittest.h:196
std::string name
Definition unittest.h:177
Definition unittest.h:226
std::vector< T > objects
Definition unittest.h:228
void add(T &&obj)
Definition unittest.h:227
UnitTest is a class that holds the test configuration. There are several options that can be set to c...
Definition unittest.h:132
std::string binary
Definition unittest.h:163
bool list_test_cases
Definition unittest.h:158
bool run_fuzz
Definition unittest.h:157
bool run_bench
Definition unittest.h:156
bool log_to_report
Definition unittest.h:160
bool run_filter(const TestCase &tc)
Run the test with the given filter.
Definition unittest.cpp:226
std::string correct_output_path
Definition unittest.h:161
bool no_color
Definition unittest.h:159
struct Filters * filters
Definition unittest.h:164
UnitTest & parseArgs(int argc, const char **argv)
Parse the arguments to configure the test.
Definition unittest.cpp:110
std::string reporter_name
Definition unittest.h:162
int run()
Run the test.
Definition unittest.cpp:256
bool silent
Definition unittest.h:155
regReporter is a class that is used to register the reporter. It will be used as global variables and...
Definition unittest.h:291
regTest is a class that is used to register the test case. It will be used as global variables and th...
Definition unittest.h:283