Skip to content

Instantly share code, notes, and snippets.

@basp1
Created September 20, 2024 11:29
Show Gist options
  • Save basp1/03ba289feae91fbe0fbb0ab0a73925cf to your computer and use it in GitHub Desktop.
Save basp1/03ba289feae91fbe0fbb0ab0a73925cf to your computer and use it in GitHub Desktop.
Simple unit-testing
#include <zero_test.h>
#include <vector>
namespace example::test {
ZERO_DEFINE_TEST_SUITE(test_example);
ZERO_DEFINE_TEST(test_example, name1) {
std::vector<int> v;
v.reserve(10);
v.push_back(1);
v.push_back(2);
ZERO_ASSERT_EQ(static_cast<size_t>(10), v.capacity());
ZERO_ASSERT_EQ(static_cast<size_t>(2), v.size());
ZERO_ASSERT(v[0] < v[1]);
}
ZERO_DEFINE_TEST(test_example, name2) {
const std::vector v{1, 2, 3};
ZERO_ASSERT_EQ(1, v[0]);
ZERO_ASSERT_EQ(2, v[1]);
ZERO_ASSERT_EQ(3, v[2]);
ZERO_ASSERT(v.size() <= v.capacity());
}
}
int main(int argc, char **argv) {
bool ok = zero_test::zero_test::run_all();
return ok ? 0 : -1;
}
#pragma once
#include <iostream>
#include <vector>
namespace zero_test {
class zero_test_case {
public:
virtual ~zero_test_case() = default;
int passed = 0;
int failed = 0;
int total = 0;
const char *name;
const bool dummy;
public:
explicit zero_test_case(const char *name, bool dummy = false) : name(name), dummy(dummy) {}
void assert_true(bool cond) {
total += 1;
if (dummy) {
std::cout << '?';
return;
}
if (cond) {
passed += 1;
std::cout << '.';
} else {
failed += 1;
std::cout << '!';
}
}
void assert_true(bool cond, const char *filename, int line) {
total += 1;
if (dummy) {
std::cout << '?';
return;
}
if (cond) {
passed += 1;
std::cout << '.';
} else {
failed += 1;
std::cout << '!' << std::endl;
std::cout << " ====> " << filename << ':' << line << std::endl;
}
}
void assert_false(bool cond) {
assert_true(!cond);
}
void assert_false(bool cond, const char *filename, int line) {
assert_true(!cond, filename, line);
}
template<typename T>
void assert_equal(T a, T b) {
assert_true(a == b);
}
template<typename T>
void assert_equal(T a, T b, const char *filename, int line) {
assert_true(a == b, filename, line);
}
virtual void run() = 0;
};
class zero_test_suite {
public:
virtual ~zero_test_suite() = default;
int total_asserts = 0;
int passed_asserts = 0;
int failed_asserts = 0;
int passed_cases = 0;
int failed_cases = 0;
std::vector<zero_test_case *> cases;
const char *name;
public:
zero_test_suite() : name(nullptr) {}
explicit zero_test_suite(const char *name) : name(name) {}
void add(zero_test_case *test) {
cases.push_back(test);
}
virtual void run() {
total_asserts = passed_asserts = failed_asserts = passed_cases = failed_cases = 0;
if (nullptr != name) {
std::cout << name << ": " << std::endl;
}
for (auto &test: cases) {
try {
test->run();
} catch (...) {
if (!test->dummy) {
std::cout << "E";
std::cout << std::endl << " ====> Exception in \"" << test->name << "\"" << std::endl;
test->failed += 1;
}
}
std::cout << ' ';
total_asserts += test->total;
passed_asserts += test->passed;
failed_asserts += test->failed;
if (test->failed > 0) {
failed_cases++;
} else {
passed_cases++;
}
}
std::cout << std::endl;
}
};
inline class zero_test {
public:
static inline std::vector<zero_test_suite *> suites;
public:
zero_test() = default;
static void add(zero_test_suite *test) {
suites.push_back(test);
}
static bool run_all() {
int passed_suites = 0;
int failed_suites = 0;
int passed_cases = 0;
int failed_cases = 0;
int total_asserts = 0;
int passed_asserts = 0;
int failed_asserts = 0;
for (auto &suite: suites) {
suite->run();
total_asserts += suite->total_asserts;
passed_asserts += suite->passed_asserts;
failed_asserts += suite->failed_asserts;
passed_cases += suite->passed_cases;
failed_cases += suite->failed_cases;
if (suite->failed_cases > 0) {
failed_suites++;
} else {
passed_suites++;
}
}
std::cout << std::endl;
std::cout << "Suites: " << passed_suites << '/' << (passed_suites + failed_suites) << std::endl;
std::cout << "Cases: " << passed_cases << '/' << (passed_cases + failed_cases) << std::endl;
std::cout << "Asserts: " << passed_asserts << '/' << total_asserts << std::endl;
if (failed_asserts > 0) {
printf("\n %c[0;31m ====> FAILED <====%c[0m\n", 27, 27);
return false;
}
printf("\n %c[0;32m PASSED %c[0m\n", 27, 27);
return true;
}
} zero_test_instance;
}
#define ZERO_TEST_SHORTNAME zero_test::zero_test
#define ZERO_TEST_INSTANCE_SHORTNAME zero_test::zero_test_instance
#define ZERO_TEST_SUITE_SHORTNAME zero_test::zero_test_suite
#define ZERO_TEST_CASE_SHORTNAME zero_test::zero_test_case
#define ZERO_ASSERT(A) assert_true(A, __FILE__, __LINE__)
#define ZERO_ASSERT_EQ(A, B) assert_equal(A, B, __FILE__, __LINE__)
#define ZERO_ASSERT_APPROX(A, B) assert_true(std::abs((A) - (B)) < 1e-8, __FILE__, __LINE__)
#define ZERO_DEFINE_TEST_SUITE(NAME) struct NAME : public ZERO_TEST_SUITE_SHORTNAME { \
NAME() : ZERO_TEST_SUITE_SHORTNAME(#NAME) { ZERO_TEST_INSTANCE_SHORTNAME.add(this); } \
} NAME##_instance;
#define ZERO_DEFINE_TEST(SUITE, NAME) struct SUITE ## _ ## NAME : public ZERO_TEST_CASE_SHORTNAME { \
SUITE ## _ ## NAME() : ZERO_TEST_CASE_SHORTNAME(#SUITE "_" #NAME) { SUITE ## _instance . add(this); } \
virtual void run(); \
} SUITE ## _ ## NAME ## _instance; \
void SUITE ## _ ## NAME :: run()
#define ZERO_DEFINE_TEST_MOCK(SUITE, NAME) struct SUITE ## _ ## NAME : public ZERO_TEST_CASE_SHORTNAME { \
SUITE ## _ ## NAME() : ZERO_TEST_CASE_SHORTNAME(#NAME, true) { SUITE ## _instance . add(this); } \
virtual void run(); \
} SUITE ## _ ## NAME ## _instance; \
void SUITE ## _ ## NAME :: run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment