ZeroErr
unittest.h
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include <functional>
6 #include <string>
7 #include <vector>
8 
10 
11 #define ZEROERR_CREATE_TEST_FUNC(function, name) \
12  static void function(zeroerr::TestContext*); \
13  static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
14  {name, __FILE__, __LINE__, function}); \
15  static void function(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
16 
17 #define TEST_CASE(name) ZEROERR_CREATE_TEST_FUNC(ZEROERR_NAMEGEN(_zeroerr_testcase), name)
18 
19 #define SUB_CASE(name) \
20  zeroerr::SubCase(name, __FILE__, __LINE__, _ZEROERR_TEST_CONTEXT) \
21  << [=](ZEROERR_UNUSED(zeroerr::TestContext * _ZEROERR_TEST_CONTEXT)) mutable
22 
23 #define ZEROERR_CREATE_TEST_CLASS(fixture, classname, funcname, name) \
24  class classname : public fixture { \
25  public: \
26  void funcname(zeroerr::TestContext*); \
27  }; \
28  static void ZEROERR_CAT(call_, funcname)(zeroerr::TestContext * _ZEROERR_TEST_CONTEXT) { \
29  classname instance; \
30  instance.funcname(_ZEROERR_TEST_CONTEXT); \
31  } \
32  static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
33  {name, __FILE__, __LINE__, ZEROERR_CAT(call_, funcname)}); \
34  inline void classname::funcname(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
35 
36 #define TEST_CASE_FIXTURE(fixture, name) \
37  ZEROERR_CREATE_TEST_CLASS(fixture, ZEROERR_NAMEGEN(_zeroerr_class), \
38  ZEROERR_NAMEGEN(_zeroerr_test_method), name)
39 
40 
41 #define ZEROERR_HAVE_SAME_OUTPUT _ZEROERR_TEST_CONTEXT->save_output();
42 
43 #ifndef ZEROERR_DISABLE_BDD
44 #define SCENARIO(...) TEST_CASE("Scenario: " __VA_ARGS__)
45 #define GIVEN(...) SUB_CASE("given: " __VA_ARGS__)
46 #define WHEN(...) SUB_CASE("when: " __VA_ARGS__)
47 #define THEN(...) SUB_CASE("then: " __VA_ARGS__)
48 #endif
49 
50 namespace zeroerr {
51 
52 class IReporter;
53 struct TestCase;
54 
67 class TestContext {
68 public:
69  unsigned passed = 0, warning = 0, failed = 0, skipped = 0;
70  unsigned passed_as = 0, warning_as = 0, failed_as = 0, skipped_as = 0;
71 
73 
79  int add(TestContext& local);
80 
84  void reset();
85 
89  void save_output();
90 
96  ~TestContext() = default;
97 };
98 
113 struct UnitTest {
120  UnitTest& parseArgs(int argc, const char** argv);
121 
126  int run();
127 
134  bool run_filter(const TestCase& tc);
135 
136  bool silent = false;
137  bool run_bench = false;
138  bool run_fuzz = false;
139  bool list_test_cases = false;
140  bool no_color = false;
141  bool log_to_report = false;
142  std::string correct_output_path;
143  std::string reporter_name = "console";
144  std::string binary;
145  struct Filters* filters;
146 };
147 
157 struct TestCase {
158  std::string name;
159  std::string file;
160  unsigned line;
161  std::function<void(TestContext*)> func;
162  std::vector<TestCase*> subcases;
163 
169  bool operator<(const TestCase& rhs) const;
170 
177  TestCase(std::string name, std::string file, unsigned line)
178  : name(name), file(file), line(line) {}
179 
187  TestCase(std::string name, std::string file, unsigned line,
188  std::function<void(TestContext*)> func)
189  : name(name), file(file), line(line), func(func) {}
190 };
191 
192 
196 struct SubCase : TestCase {
197  SubCase(std::string name, std::string file, unsigned line, TestContext* context);
198  ~SubCase() = default;
200  void operator<<(std::function<void(TestContext*)> op);
201 };
202 
203 
204 template <typename T>
206  void add(T&& obj) { objects.push_back(std::forward<T>(obj)); }
207  std::vector<T> objects;
208 };
209 
210 
222 class IReporter {
223 public:
224  virtual ~IReporter() = default;
225 
226  virtual std::string getName() const = 0;
227 
228  // There are a list of events
229  virtual void testStart() = 0;
230  virtual void testCaseStart(const TestCase& tc, std::stringbuf& sb) = 0;
231  virtual void testCaseEnd(const TestCase& tc, std::stringbuf& sb, const TestContext& ctx,
232  int type) = 0;
233  virtual void subCaseStart(const TestCase& tc, std::stringbuf& sb) = 0;
234  virtual void subCaseEnd(const TestCase& tc, std::stringbuf& sb, const TestContext& ctx,
235  int type) = 0;
236  virtual void testEnd(const TestContext& tc) = 0;
237 
243  static IReporter* create(const std::string& name, UnitTest& ut);
244 
246 
247 protected:
249 };
250 
254 enum TestType { test_case = 1, sub_case = 1 << 1, bench = 1 << 2, fuzz_test = 1 << 3 };
255 
256 namespace detail {
257 
262 struct regTest {
263  explicit regTest(const TestCase& tc, TestType type = test_case);
264 };
265 
270 struct regReporter {
271  explicit regReporter(IReporter*);
272 };
273 } // namespace detail
274 
275 
292 public:
293  CombinationalTest(std::function<void()> func) : func(func) {}
294  std::function<void()> func;
295 
296  template <typename T>
297  void operator()(T& arg) {
298  arg.reset();
299  for (size_t i = 0; i < arg.size(); ++i, ++arg) {
300  func();
301  }
302  }
303 
304  template <typename T, typename... Args>
305  void operator()(T& arg, Args&... args) {
306  arg.reset();
307  for (size_t i = 0; i < arg.size(); ++i, ++arg) {
308  operator()(args...);
309  }
310  }
311 };
312 
313 
317 template <typename T>
318 class TestArgs {
319 public:
320  TestArgs(std::initializer_list<T> args) : args(args) {}
321  std::vector<T> args;
322 
323  operator T() const { return args[index]; }
325  index++;
326  return *this;
327  }
328  size_t size() const { return args.size(); }
329  void reset() { index = 0; }
330 
331 private:
332  int index = 0;
333 };
334 
335 } // namespace zeroerr
336 
CombinationalTest is a class that is used to cross test a few lists of arguments. One example.
Definition: unittest.h:291
std::function< void()> func
Definition: unittest.h:294
void operator()(T &arg, Args &... args)
Definition: unittest.h:305
void operator()(T &arg)
Definition: unittest.h:297
CombinationalTest(std::function< void()> func)
Definition: unittest.h:293
IReporter is an interface that is used to report the test results. You can create a new reporter by i...
Definition: unittest.h:222
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:782
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:248
IReporter(UnitTest &ut)
Definition: unittest.h:245
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:318
size_t size() const
Definition: unittest.h:328
std::vector< T > args
Definition: unittest.h:321
TestArgs(std::initializer_list< T > args)
Definition: unittest.h:320
TestArgs & operator++()
Definition: unittest.h:324
void reset()
Definition: unittest.h:329
TestContext is a class that holds the test results and reporter context. There are 8 different matric...
Definition: unittest.h:67
void reset()
Reset the matrices to 0.
Definition: unittest.cpp:65
unsigned skipped
Definition: unittest.h:69
unsigned failed
Definition: unittest.h:69
unsigned passed
Definition: unittest.h:69
void save_output()
Save the output of the test to the correct_output_path as a golden file.
Definition: unittest.cpp:45
unsigned skipped_as
Definition: unittest.h:70
unsigned passed_as
Definition: unittest.h:70
unsigned failed_as
Definition: unittest.h:70
IReporter & reporter
Definition: unittest.h:72
unsigned warning
Definition: unittest.h:69
unsigned warning_as
Definition: unittest.h:70
TestContext(IReporter &reporter)
Construct a new Test Context object.
Definition: unittest.h:95
int add(TestContext &local)
Add the subtest results to the matrices.
Definition: unittest.cpp:24
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition: config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition: config.h:218
Definition: benchmark.cpp:17
TestType
TestType is a enum describe the type of the test case.
Definition: unittest.h:254
@ bench
Definition: unittest.h:254
@ test_case
Definition: unittest.h:254
@ fuzz_test
Definition: unittest.h:254
@ sub_case
Definition: unittest.h:254
Definition: unittest.cpp:104
SubCase is a class that holds the subcase information.
Definition: unittest.h:196
TestContext * context
Definition: unittest.h:199
void operator<<(std::function< void(TestContext *)> op)
Definition: unittest.cpp:81
~SubCase()=default
SubCase(std::string name, std::string file, unsigned line, TestContext *context)
Definition: unittest.cpp:78
TestCase is a class that holds the test case information. There are several fields that are used to s...
Definition: unittest.h:157
bool operator<(const TestCase &rhs) const
Compare the test cases.
Definition: unittest.cpp:281
std::function< void(TestContext *)> func
Definition: unittest.h:161
std::string file
Definition: unittest.h:159
TestCase(std::string name, std::string file, unsigned line)
Construct a new Test Case object.
Definition: unittest.h:177
unsigned line
Definition: unittest.h:160
std::vector< TestCase * > subcases
Definition: unittest.h:162
TestCase(std::string name, std::string file, unsigned line, std::function< void(TestContext *)> func)
Construct a new Test Case object.
Definition: unittest.h:187
std::string name
Definition: unittest.h:158
Definition: unittest.h:205
std::vector< T > objects
Definition: unittest.h:207
void add(T &&obj)
Definition: unittest.h:206
UnitTest is a class that holds the test configuration. There are several options that can be set to c...
Definition: unittest.h:113
std::string binary
Definition: unittest.h:144
bool list_test_cases
Definition: unittest.h:139
bool run_fuzz
Definition: unittest.h:138
bool run_bench
Definition: unittest.h:137
bool log_to_report
Definition: unittest.h:141
bool run_filter(const TestCase &tc)
Run the test with the given filter.
Definition: unittest.cpp:225
std::string correct_output_path
Definition: unittest.h:142
bool no_color
Definition: unittest.h:140
struct Filters * filters
Definition: unittest.h:145
UnitTest & parseArgs(int argc, const char **argv)
Parse the arguments to configure the test.
Definition: unittest.cpp:109
std::string reporter_name
Definition: unittest.h:143
int run()
Run the test.
Definition: unittest.cpp:238
bool silent
Definition: unittest.h:136
regReporter is a class that is used to register the reporter. It will be used as global variables and...
Definition: unittest.h:270
regReporter(IReporter *)
Definition: unittest.cpp:315
regTest is a class that is used to register the test case. It will be used as global variables and th...
Definition: unittest.h:262
regTest(const TestCase &tc, TestType type=test_case)
Definition: unittest.cpp:308