C++ Minimalistic Unit Testing Library I was looking for a unit testing library for C++, and I found many. Unfortunately, I decided I didn't want to use any of them. I decided to make my own.

This is the result. I made heavy use of the preprocessor, and followed the convention of leading underscore to mean non-published. Everything is done in all-caps, to try to follow good conventions and to avoid name collisions.

Please note that this code is published under the MIT license.

unittest.h

#pragma once

#include &lt;vector&gt;
#include &lt;iostream&gt;

// Helper Macros
#define _STR_HELP(x) #x
#define _STR(x) _STR_HELP(x)
#define ESCAPE(...) __VA_ARGS__ // TEST_CASE(std::map&lt;int, int&gt;) would fail. Wrap in this Macro to not fail.

#define _FILE_LINE __FILE__ ":" _STR(__LINE__)

// Assertion Macros
#define _GENERATE_MESSAGE(test) _FILE_LINE " Failed " #test "." // Message in almost every assertion

/*
 * Assertions are intended to be used within a TEST_CASE macro. We return EXIT_FAILURE if we fail the assertion,
 * meaning that the TEST_CASE fails. Assertions can also be used straight inside the main function, in which case
 * the main function will exit. They are intended to be used within the TEST_CASE macro, so it's not recommended to do
 * that.
 */
#define _ASSERT(test, message)  if (!(test)) {\
                                    std::cerr &lt;&lt; message &lt;&lt; std::endl;\
                                    return EXIT_FAILURE;\
                                }
// One argument assertion. This generates a message to display.
#define _ASSERT_1(test) _ASSERT(test, _GENERATE_MESSAGE(test))
// Two argument assertion, which appends the user-defined message to the generated one.
#define _ASSERT_2(test, additional) _ASSERT(test, _GENERATE_MESSAGE(test) " " additional)

// Helper macro to get the correct assertion (out of _ASSERT_1 or _ASSERT_2)
#define _GET_ASSERTION(_1, _2, NAME, ...) NAME

// Public Macro for actually calling the ASSERT
#define ASSERT(...) _GET_ASSERTION(__VA_ARGS__, _ASSERT_2, _ASSERT_1)(__VA_ARGS__)
// More advanced macro than ASSERT; it tells the values of each of the arguments as part of the message.
#define ASSERT_EQ(a, b) {\
                            const auto&amp; _VAL_1 = a;\
                            const auto&amp; _VAL_2 = b;\
                            if (_VAL_1 != _VAL_2) {\
                                std::cerr &lt;&lt; _FILE_LINE " Failed " #a " == " #b ". Actual Values:\n" \
                                    #a ": " &lt;&lt; _VAL_1 &lt;&lt; "\n" \
                                    #b ": " &lt;&lt; _VAL_2 &lt;&lt; std::endl;\
                                return EXIT_FAILURE;\
                            }\
                        }

/*
 * Convenience struct for storing test cases and all related data into a vector.
 */
struct _TEST_CASE
{
    const char *name;
    int (*function)();
    bool result;
};
std::vector&lt;_TEST_CASE&gt; _TEST_CASES; // All test cases are added to this global vector.

// Test Execution Macros
#define TEST_CASE(name, code) _TEST_CASES.push_back({ name, [](){ code; return EXIT_SUCCESS; }, false });

#define RUN_TESTS() std::cout &lt;&lt; std::endl; \
                    for (_TEST_CASE&amp; testCase : _TEST_CASES) {\
                        testCase.result = EXIT_SUCCESS == (*testCase.function)();\
                        if (!testCase.result) {\
                            std::cerr &lt;&lt; "Failed test case " &lt;&lt; testCase.name &lt;&lt; "\n";\
                        }\
                    }\
                    std::cout &lt;&lt; "Results: ";\
                    for (_TEST_CASE testCase : _TEST_CASES) {\
                        std::cout &lt;&lt; (testCase.result ? '.' : 'F');\
                    }\
                    std::cout &lt;&lt; std::endl &lt;&lt; std::endl;
I decided I didn't want to use any of them. I decided to make my own.

That's a mistake.


and followed the convention of leading underscore to mean non-published.

A leading underscore followed by an uppercase letter is reserved identifier reserved for the implementation.

Please note that this code is published under the MIT license.

Also note that this code is not published under the creative commons license. See the bottom of the page. Everything published on any stack-exchange site is available under creative commons.
Design
There are a lot of missing features that I would expect in unit test framework.

Ability to run tests in isolation
Ability to run groups of tests.
Ability to set up state for tests
Ability to tear down state and reset the environment.
Some facility for mocking other classes.