1 #ifndef UNIT_BASE_GROUP
2 #define UNIT_BASE_GROUP
5 * Name : unit_base tools for unit testing
6 * Author : Chris Koeritz
8 * Copyright (c) 2009-$now By Author. This program is free software; you can *
9 * redistribute it and/or modify it under the terms of the GNU General Public *
10 * License as published by the Free Software Foundation; either version 2 of *
11 * the License or (at your option) any later version. This is online at: *
12 * http://www.fsf.org/copyleft/gpl.html *
13 * Please send any updates to: fred@gruntose.com *
16 //! Useful support functions for unit testing, especially within hoople.
18 Provides a simple framework for unit testing the hoople classes.
21 #include <basis/astring.h>
22 #include <basis/contracts.h>
23 #include <basis/enhance_cpp.h>
24 #include <basis/mutex.h>
25 #include <structures/string_table.h>
29 // these macros can be used to put more information into the test name.
30 // using these is preferable to calling the class methods directly, since
31 // those cannot print out the original version of the formal parameters a
32 // and b for the test; the macros show the expressions that failed rather
33 // than just the values.
34 // note that these require the calling object to be derived from unit_base.
35 #define UNIT_BASE_THIS_OBJECT (*this)
36 // the macro for UNIT_BASE_THIS_OBJECT allows tests to use a single unit_base object by
37 // changing the value of UNIT_BASE_THIS_OBJECT to refer to the proper object's name.
38 #define ASSERT_EQUAL(a, b, test_name) { \
39 BASE_FUNCTION(func); \
40 UNIT_BASE_THIS_OBJECT.assert_equal(a, b, function_name, test_name, basis::astring(#a) + " must be equal to " + #b); \
42 #define ASSERT_INEQUAL(a, b, test_name) { \
43 BASE_FUNCTION(func); \
44 UNIT_BASE_THIS_OBJECT.assert_not_equal(a, b, function_name, test_name, basis::astring(#a) + " must be inequal to " + #b); \
46 #define ASSERT_TRUE(a, test_name) { \
47 BASE_FUNCTION(func); \
48 UNIT_BASE_THIS_OBJECT.assert_true(a, function_name, test_name, basis::astring(#a) + " must be true"); \
50 #define ASSERT_FALSE(a, test_name) { \
51 BASE_FUNCTION(func); \
52 UNIT_BASE_THIS_OBJECT.assert_false(a, function_name, test_name, basis::astring(#a) + " must be false"); \
54 // pointer versions for nicer syntax.
55 #define ASSERT_NULL(x, y) ASSERT_FALSE(x, y)
56 #define ASSERT_NON_NULL(x, y) ASSERT_TRUE(x, y)
58 class unit_base : public virtual basis::nameable
64 DEFINE_CLASS_NAME("unit_base");
66 int total_tests() const; //!< the total count of tests that have been run.
67 int passed_tests() const; //!< count of successful tests run.
68 int failed_tests() const; //!< count of number of failed tests.
70 void assert_equal(const basis::hoople_standard &a, const basis::hoople_standard &b,
71 const basis::astring &class_name, const basis::astring &test_name,
72 const basis::astring &diagnostic_info);
73 //!< tests that the objects a and b are equal.
74 void assert_not_equal(const basis::hoople_standard &a, const basis::hoople_standard &b,
75 const basis::astring &class_name, const basis::astring &test_name,
76 const basis::astring &diagnostic_info);
77 //!< tests that objects a and b are NOT equal.
79 void assert_equal(const basis::byte_array &a, const basis::byte_array &b,
80 const basis::astring &class_name, const basis::astring &test_name,
81 const basis::astring &diagnostic_info);
82 //!< tests that the byte_arrays a and b are equal.
83 void assert_not_equal(const basis::byte_array &a, const basis::byte_array &b,
84 const basis::astring &class_name, const basis::astring &test_name,
85 const basis::astring &diagnostic_info);
86 //!< tests that the byte_arrays a and b are not equal.
88 void assert_equal(int a, int b,
89 const basis::astring &class_name, const basis::astring &test_name,
90 const basis::astring &diagnostic_info);
91 //!< tests that integers a and b are equal.
92 void assert_not_equal(int a, int b,
93 const basis::astring &class_name, const basis::astring &test_name,
94 const basis::astring &diagnostic_info);
95 //!< tests that integers a and b are NOT equal.
97 void assert_equal(double a, double b,
98 const basis::astring &class_name, const basis::astring &test_name,
99 const basis::astring &diagnostic_info);
100 //!< tests that doubles a and b are equal.
101 void assert_not_equal(double a, double b,
102 const basis::astring &class_name, const basis::astring &test_name,
103 const basis::astring &diagnostic_info);
104 //!< tests that doubles a and b are NOT equal.
106 void assert_equal(const void *a, const void *b,
107 const basis::astring &class_name, const basis::astring &test_name,
108 const basis::astring &diagnostic_info);
109 //!< tests that void pointers a and b are equal.
110 /*!< note that you can use this to compare any two pointers as long as
111 you cast them to (void *) first. this reports whether the two have the
112 same address in memory, but nothing about their contents. */
113 void assert_not_equal(const void *a, const void *b,
114 const basis::astring &class_name, const basis::astring &test_name,
115 const basis::astring &diagnostic_info);
116 //!< tests that void pointers a and b are NOT equal.
118 void assert_true(bool result,
119 const basis::astring &class_name, const basis::astring &test_name,
120 const basis::astring &diagnostic_info);
121 //!< tests that the "result" is a true boolean.
122 void assert_false(bool result,
123 const basis::astring &class_name, const basis::astring &test_name,
124 const basis::astring &diagnostic_info);
125 //!< tests that the "result" is a false boolean.
127 // these two methods can be used in an ad hoc manner when using the above
128 // assert methods is not helpful. the "test_name" should be provided
129 // like above, but the "diagnostic_info" can be phrased in any way needed
130 // to describe the pass or fail event.
131 void record_pass(const basis::astring &class_name,
132 const basis::astring &test_name,
133 const basis::astring &diagnostic_info);
134 //!< very general recording of a successful test; better to use asserts.
135 void record_fail(const basis::astring &class_name,
136 const basis::astring &test_name,
137 const basis::astring &diagnostic_info);
138 //!< very general recording of a failed test; better to use asserts.
141 //!< generates a report of the total number of tests that succeeded.
142 /*!< the return value of this can be used as the exit value of the overall test. if there
143 are any failures, then a failure result is returned (non-zero). otherwise the successful
144 exit status of zero is returned. */
147 basis::mutex c_lock; //!< protects our objects for concurrent access.
148 int c_total_tests; //!< how many tests have been run?
149 int c_passed_tests; //!< how many of those passed?
150 structures::string_table c_successful; //!< successful test names.
151 structures::string_table c_failed; //!< failing test names.
153 void write_cppunit_xml();
154 //!< outputs a report file in cppunit format so CI engines can see results.
156 void count_successful_test(const basis::astring &class_name, const basis::astring &test_name);
157 //!< records one successful test.
159 void count_failed_test(const basis::astring &class_name, const basis::astring &test_name, const basis::astring &diag);
160 //!< records one failed test.
162 void record_successful_assertion(const basis::astring &class_name, const basis::astring &test_name,
163 const basis::astring &assertion_name);
164 //!< used by happy tests to record their success.
166 void record_failed_object_compare(const basis::hoople_standard &a,
167 const basis::hoople_standard &b, const basis::astring &class_name,
168 const basis::astring &test_name, const basis::astring &assertion_name);
169 void record_failed_int_compare(int a, int b,
170 const basis::astring &class_name, const basis::astring &test_name,
171 const basis::astring &assertion_name);
172 void record_failed_double_compare(double a, double b,
173 const basis::astring &class_name, const basis::astring &test_name,
174 const basis::astring &assertion_name);
175 void record_failed_tf_assertion(bool result, bool expected_result,
176 const basis::astring &class_name, const basis::astring &test_name,
177 const basis::astring &assertion_name);
178 void record_failed_pointer_compare(const void *a, const void *b,
179 const basis::astring &class_name, const basis::astring &test_name,
180 const basis::astring &assertion_name);