Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Maat: The Test Harness

Maat is a lightweight, self-contained, single-header C++ test harness with no dependencies and no boilerplate. Drop in the header, write your tests, run them.

Maat is the Egyptian goddess of truth, justice, and cosmic order. In the Weighing of the Heart the heart of the deceased is weighed against a feather before Osiris, Thoth and Anubis. The scales do not negotiate. The result is binary. Failed tests are eaten by the Ammit monster. |

A test harness should work the same way.

Why Maat Exists

The C++ testing landscape is paradoxical. There are excellent, mature, well-documented frameworks — and yet setting up a test for a small utility function can consume more time than writing the function itself.

Google Test requires a CMake fetch, a linked library, and a registration mechanism before anything is verified. Catch2 and doctest are more self-contained but arrive with their own DSLs, their own main(), and enough machinery that understanding what is actually happening requires reading documentation rather than code. Boost.Test is Boost — which says everything. CppUnit faithfully mirrors JUnit's Java architecture, which is a questionable virtue in a language that isn't Java.

The common thread is that these frameworks were built to scale — to enterprise codebases, CI pipelines, and teams with dedicated QA infrastructure. That scaling comes at a cost that small and mid-sized projects simply shouldn't have to pay.

What was needed was something closer to the metal: assertions that are just macros, tests that are just functions, a runner that is just a loop, and a report that is just output. No framework. No discovery. No opinions. Maat is that. The scales are simple by design — it is the judgment that matters, not the apparatus.

Installation

Copy maat.h into your project and include it:

#include "maat.h"

That's it.

Usage

Assertions

Maat provides two classes of assertion, reflecting terminal and fatal failures. All take a message that ia displayed if the test fails: REQUIRE — hard assertion. On failure the test terminates immediately, as a heart too heavy for the feather ends the ceremony:

REQUIRE(ptr != nullptr, "pointer must not be null");
REQ_EQ(result, expected, "values must match");
REQ_NEQ(result, forbidden, "value must differ");

EXPECT — soft assertion. On failure the verdict is recorded but execution continues to allow additional failures to be recorded before the test is reported failed:

EXPECT(value > 0, "value should be positive");
EXP_EQ(result, expected, "values should match");
EXP_NEQ(result, forbidden, "value should differ");

NOTE — inserts a message into the test report without affecting the result:

NOTE("testing edge case: empty input");

Running tests

RUN_TEST(my_test_function);

Test functions return bool and take no arguments:

bool my_test_function()
{
    REQUIRE(true, "this will pass");
    EXPECT(1 + 1 == 2, "arithmetic holds");
    return true;
}

Returning false from the test function is equivalent to a failed REQUIRE.

Print summary

Call maat::print_summary() at the end of your test run:

maat::print_summary();

Output:

Summary: 7 passed, 1 failed, 8 total.

A complete example

#include "maat.h"
#include <vector>

bool test_vector_basics()
{
    std::vector<int> v;
    REQUIRE(v.empty(), "vector should start empty");
    
    v.push_back(42);
    EXP_EQ(v.size(), 1u, "vector should have one element");
    EXP_EQ(v[0], 42, "element should be 42");
    
    return true;
}

int main()
{
    RUN_TEST(test_vector_basics);    
    maat::print_summary();
}

Output

Tests report live as they run, with the status overwriting the "running" indicator:

[ ok ] 1: test_vector_basics
[FAIL] 2: test_something_else
    - Exp: values should match
    - Req: pointer must not be null

Failed assertions are reported beneath the test name — Req: for hard failures that terminated the test, Exp: for soft failures that were accumulated. Ammit is not selective.

Namespace

All Maat internals live under ::maat. Your test files need not reference the namespace directly — the macros handle everything.

Licence

Licensed under the MIT License.

About

Maat is a lightweight, self-contained, single-header C++ test harness with no dependencies and no boilerplate. Drop in the header, write your tests, run them.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages