FuncDoodle
Loading...
Searching...
No Matches
Test.h
Go to the documentation of this file.
1
18
19#pragma once
20
21#ifdef FUNCDOODLE_BUILD_IMTESTS
22#include "imgui_te_engine.h"
23#include "imgui_te_ui.h"
24#endif
25
26#include <atomic>
27#include <cstring>
28#include <iostream>
29#include <string>
30#include <vector>
31
32#ifdef FUNCDOODLE_BUILD_TESTS
33int FuncDoodle_RunTests();
34#endif
35
36#ifdef _MSC_VER
38#define CURRENT_FUNC __FUNCTION__
39#else
42#define CURRENT_FUNC __func__
43#endif
44
45#ifdef FUNCDOODLE_BUILD_IMTESTS
46int FuncDoodle_RegisterImTests();
47extern ImGuiTestEngine* s_TestEngine;
48#endif
49
50namespace FuncDoodle {
51
59 inline std::string Repeat(std::string_view s, size_t n) {
60 std::string out;
61 out.reserve(s.size() * n);
62 while (n--)
63 out += s;
64 return out;
65 }
66
71 struct TestResult {
72 std::string condition;
73 std::string message;
74 bool passed;
75 };
76
85 public:
93 static TestRegistry instance;
94 return instance;
95 }
96
101 const char* name, int passed, int total, int failed) {
102 m_Results.push_back({name, passed, total, failed});
103 }
104
111 int total_tests = 0;
112 int total_passed = 0;
113 int total_failed = 0;
114
115 for (const auto& r : m_Results) {
116 total_tests += r.total;
117 total_passed += r.passed;
118 total_failed += r.failed;
119 }
120
121 double percentage = total_tests > 0
122 ? (double)total_passed / total_tests * 100.0
123 : 0.0;
124
125 std::string percent_str = std::to_string(percentage);
126 percent_str = percent_str.substr(0, percent_str.find('.') + 2);
127
128 std::cout << "\n";
129 std::cout << "╔" << Repeat("═", 62) << "╗\n";
130 std::cout << "║ TEST SUMMARY "
131 " ║\n";
132 std::cout << "╠" << Repeat("═", 62) << "╣\n";
133
134 std::cout << "║ Total: " << total_tests
135 << std::string(
136 48 - std::to_string(total_tests).length(), ' ')
137 << " ║\n";
138
139 std::cout << "║ \033[32mPassed: " << total_passed << "\033[0m"
140 << std::string(
141 47 - std::to_string(total_passed).length(), ' ')
142 << " ║\n";
143
144 std::cout << "║ \033[31mFailed: " << total_failed << "\033[0m"
145 << std::string(
146 47 - std::to_string(total_failed).length(), ' ')
147 << " ║\n";
148
149 std::string color =
150 (percentage == 100.0)
151 ? "\033[32m"
152 : (percentage >= 80.0 ? "\033[33m" : "\033[31m");
153
154 std::cout << "║ " << color << "Success: " << percent_str
155 << "%\033[0m"
156 << std::string(46 - percent_str.length(), ' ')
157 << " ║\n";
158
159 std::cout << "╚" << Repeat("═", 62) << "╝\n";
160 }
161
162 private:
163 struct ScopeResult {
164 const char* name;
166 };
167
168 std::vector<ScopeResult> m_Results;
169 };
170
177 class TestScope {
178 public:
185 explicit TestScope(const char* name) : m_Name(name) {}
186
192 m_Name.c_str(), m_Passed, m_Total, m_Failed);
193
194 std::cout << "\n";
195 std::cout << "╔" << Repeat("═", 62) << "╗\n";
196 std::cout << "║ \033[1m" << m_Name << "\033[0m"
197 << std::string(60 - m_Name.length(), ' ') << "║\n";
198 std::cout << "╠" << Repeat("═", 62) << "╣\n";
199
200 if (m_Failed == 0) {
201 std::cout << "║ \033[32m[PASS]\033[0m " << m_Passed << "/"
202 << m_Total << " passed"
203 << std::string(45 -
204 std::to_string(m_Passed).length() -
205 std::to_string(m_Total).length(),
206 ' ')
207 << "║\n";
208 } else {
209 std::cout << "║ \033[32m[PASS]\033[0m " << m_Passed << "/"
210 << m_Total << " passed"
211 << std::string(44 -
212 std::to_string(m_Passed).length() -
213 std::to_string(m_Total).length(),
214 ' ')
215 << "║\n";
216
217 std::cout << "║ \033[31m[FAIL]\033[0m " << m_Failed
218 << " failed"
219 << std::string(
220 47 - std::to_string(m_Failed).length(), ' ')
221 << "║\n";
222 }
223
224 std::cout << "╚" << Repeat("═", 62) << "╝\n";
225 }
226
230 void Check(bool cond, const char* condStr, const char* msg = "") {
231 m_Total++;
232 if (cond)
233 m_Passed++;
234 else {
235 m_Failed++;
236 m_Results.push_back({condStr, msg ? msg : "", false});
237 }
238 }
239
240 private:
241 std::string m_Name;
242 int m_Total = 0, m_Passed = 0, m_Failed = 0;
243 std::vector<TestResult> m_Results;
244 };
245
246} // namespace FuncDoodle
247
248// ================= MACROS =================
249
254#define TEST_SCOPE(name) FuncDoodle::TestScope _test_scope(name)
255
260#define CHECK(cond, msg) _test_scope.Check(cond, #cond, msg)
265#define CHECK_EQ(a, b, msg) _test_scope.Check((a) == (b), #a " == " #b, msg)
270#define CHECK_NE(a, b, msg) _test_scope.Check((a) != (b), #a " != " #b, msg)
275#define CHECK_LT(a, b, msg) _test_scope.Check((a) < (b), #a " < " #b, msg)
281#define CHECK_LE(a, b, msg) _test_scope.Check((a) <= (b), #a " <= " #b, msg)
286#define CHECK_GT(a, b, msg) _test_scope.Check((a) > (b), #a " > " #b, msg)
292#define CHECK_GE(a, b, msg) _test_scope.Check((a) >= (b), #a " >= " #b, msg)
297#define CHECK_NULL(ptr, msg) \
298 _test_scope.Check((ptr) == nullptr, #ptr " == nullptr", msg)
299
303#define CHECK_NOT_NULL(ptr, msg) \
304 _test_scope.Check((ptr) != nullptr, #ptr " != nullptr", msg)
Global singleton collecting test scope results.
Definition Test.h:84
static TestRegistry & Instance()
Returns the global test registry singleton.
Definition Test.h:92
std::vector< ScopeResult > m_Results
Definition Test.h:168
void RegisterScope(const char *name, int passed, int total, int failed)
Registers a completed test scope.
Definition Test.h:100
void PrintSummary()
Prints a full summary of all executed tests.
Definition Test.h:110
std::vector< TestResult > m_Results
Definition Test.h:243
int m_Passed
Definition Test.h:242
int m_Failed
Definition Test.h:242
~TestScope()
Finalizes and prints test scope results.
Definition Test.h:190
std::string m_Name
Definition Test.h:241
void Check(bool cond, const char *condStr, const char *msg="")
Evaluates a test condition.
Definition Test.h:230
TestScope(const char *name)
Creates a named test scope.
Definition Test.h:185
int m_Total
Definition Test.h:242
The FuncDoodle C++ namespace.
Definition Common.h:12
std::string Repeat(std::string_view s, size_t n)
Repeats a string N times.
Definition Test.h:59
int total
Definition Test.h:165
const char * name
Definition Test.h:164
int failed
Definition Test.h:165
int passed
Definition Test.h:165
Represents a single failed or recorded test assertion.
Definition Test.h:71
std::string message
Optional failure message.
Definition Test.h:73
bool passed
Whether the test passed.
Definition Test.h:74
std::string condition
Stringified test condition.
Definition Test.h:72