MT Core (C++)
Core library for replacing C++ standard in project usage
Loading...
Searching...
No Matches
MTTest

MTTest is a simple unit testing framework. It came out of the need of mtstd. MTStd supports Cheerp which does not support unions or variants. However, most C++ unit testing frameworks use unions and/or variants, so we were unable to run tests inside a Cheerp build. To handle this use case, we wrote a very small (and very simple) unit test framework. The initial implementation was done in a day.

We adjusted mtcore to use the mttest framework to make it easier to port unit tests between the two systems. We've also extended it a little bit since then.

The goal of MTTest is to solve for our immediate needs and use cases, rather than to create a fully-featured testing framework for general use. If it solves your use cases, feel free to use it. The actual single header mttest.hpp is licensed separately from the rest of the repository underneath the BSD-3 clause license.

At some point we may try to make it a more complete testing solution. However, until then the focus will be on adressing our immediate testing needs and use cases.

General Usage

You will need one cpp file to define the macro MTTEST_DEFINE_MAIN prior to including mttest.hpp. This will setup the main method. Only one cpp file needs to define MTTEST_DEFINE_MAIN, the rest only need to include mttest.hpp.

#define MTTEST_DEFINE_MAIN
#include "mttest.hpp"

To declare a test, use the macro TEST_CASE which takes in a test suite name and a test case name. It is then followed by a code block with the test case itself. Example:

TEST_CASE(MySuite, MyTest) {
CHECK(true);
}
#define TEST_CASE(SUITE, NAME)
Defines a new test case.
Definition mttest.hpp:345
#define CHECK(...)
Does a check.
Definition mttest.hpp:506

Note that the suite and test case names must be valid C++ variable names.

Assertions are provided by the following macros:

Macro Name Arguments Description
CHECK cond Checks if cond is true, fails the test if cond is false
CHECK_MESSAGE cond, message Checks if cond is true, fails the test and prints the message if cond is false
CHECK_EQ left, right Checks if left is equal to right with operator==
CHECK_NE left, right Checks if left is not equal to right with operator!=
CHECK_LT left, right Checks if left is equal to right with operator<
CHECK_LE left, right Checks if left is equal to right with operator<=
CHECK_GT left, right Checks if left is equal to right with operator>
CHECK_GE left, right Checks if left is equal to right with operator>=
CHECK_EQ_APPROX left, right, epsilon Checks if left is within epsilon distance of right. Uses operator<=, operator>=, operator+, and operator- to do the check

CLI Usage

Currently, the CLI usage is in the following form:

test_exe_name [-v] (test_suites...)

The test_suites is a list of test suites to run (no test case running currently). If not missing, it will run everything. The -v flag is for verbose mode, which will print every test case.

C++ Exceptions

MTTest will simply check the built-in __cpp_exceptions macro to see if C++ exceptions are enabled. If they are enabled, it will wrap each check macro (CHECK, CHECK_EQ, etc.) in a try/catch block which will try to print the error that happened, or if it's unable to print it will print that an unknown error happened.

Supported exception types for printing detailed errors are std::runtime_error and int.

Using MTTest Without Exceptions

When C++ exceptions are turned off at the compiler level, the try/catch blocks are converted into anonymouse blocks of code. This is to prevent any potential scoping issues with temporary variables.

Accessing the test context

Each test case has a variable called mttest__context_ctx which holds the test context. Check macros will search for this name directly. This means if you want to use a test macro inside a lambda, you will either need to capture-all by reference or you'll need to capture mttest__context_ctx directly.

If you need to pass the context to another function for any reason, the receiving function must take the test context parameter by the name mttest__context_ctx, and it needs to be taken by reference. The type of the context is mttest::TestContext.

Auto-Registration

Auto registration is done by accessing the global variable test_suites before main() is called. This does mean that test registration ordering is determined by the rules governing execution before main, which basically means we make no guarantee of the order things run in.

For further details, you may always look at the code. It's not that long, and it's pretty simple (at least compared to most test frameworks I've seen).