Test Definition Macros

Include mu/tiny/test.hpp for all macros on this page.

Test Group and Lifecycle

TEST_GROUP(group)

TEST_GROUP declares a test group. Expands to a struct definition; add setup() and teardown() inside it.

TEST_GROUP(MyGroup)
{
    MyObject* obj;

    void setup() override    { obj = new MyObject; }
    void teardown() override { delete obj; }
};

All tests in the group share a fresh instance of the struct (constructed before setup(), destroyed after teardown()).

TEST(group, name)

TEST defines a test belonging to group. The { ... } block that follows is the test body.

TEST(MyGroup, DoesTheThing)
{
    CHECK(obj->do_thing());
}

Skipping and Expected Failures

SKIPPED_TEST(group, name)

SKIPPED_TEST marks a test as skipped. It is registered but skipped during normal runs. Use -rs to run skipped tests anyway.

SKIPPED_TEST(MyGroup, NotImplementedYet)
{
    // will not run unless -rs is passed
    CHECK(false);
}

Skipped tests appear in the summary count as “skipped”.

XFAIL_TEST(group, name)

XFAIL_TEST declares a test that is expected to fail. The test runner treats a failure as a pass and a pass as a failure. Useful for documenting known bugs that cannot yet be fixed.

XFAIL_TEST(MyGroup, KnownBug)
{
    CHECK_EQUAL(expected, buggy_function()); // currently produces wrong result
}

Metadata

TEST_PROPERTY(name, value)

TEST_PROPERTY attaches a key/value metadata pair to the currently running test. Emitted in JUnit XML output as <property> elements. Useful for CI tagging (e.g. requirement IDs).

TEST(MyGroup, Requirement42)
{
    TEST_PROPERTY("requirement", "REQ-42");
    CHECK(meets_requirement_42());
}

Ordered Tests

Normally mu::tiny runs tests in an unspecified order (registration order, possibly shuffled with -s [seed]). OrderedShell lets you assign a numeric level to selected tests so they run in level order, independent of the registration order of all other tests.

TEST_ORDERED(group, name, level)

TEST_ORDERED declares a test that runs at the given level. Lower levels run first. Tests at the same level run in registration order relative to each other (FirstEvent and SecondEvent both run at level 20 below).

// Demonstrates TEST_ORDERED: tests that run in level order across the suite.
//
// Use case: a stateful system (here, a simple in-memory event log) that must
// be initialized before use and flushed on shutdown. Ordered tests let each
// phase be a separate, named test rather than one monolithic test body.

#include "mu/tiny/test/Ordered.hpp"

#include "mu/tiny/test.hpp"

namespace {

struct EventLog
{
  const char* entries[8]{};
  int count{ 0 };
  bool initialized{ false };
  bool flushed{ false };

  void init()
  {
    initialized = true;
    count = 0;
  }

  void append(const char* msg)
  {
    if (count < 8) {
      entries[count++] = msg;
    }
  }

  void flush()
  {
    count = 0;
    flushed = true;
  }
};

EventLog g_log;

} // namespace

TEST_GROUP(OrderedDemo)
{};

// Regular test — unordered tests run before the ordered block.
TEST(OrderedDemo, StartsUninitialized)
{
  CHECK(!g_log.initialized);
}

// Level 10: initialize.
TEST_ORDERED(OrderedDemo, Init, 10)
{
  g_log.init();
  CHECK(g_log.initialized);
  CHECK_EQUAL(0, g_log.count);
}

// Level 20: record two events. Tests at the same level run in
// registration order (FirstEvent before SecondEvent).
TEST_ORDERED(OrderedDemo, FirstEvent, 20)
{
  g_log.append("startup");
  CHECK_EQUAL(1, g_log.count);
}

TEST_ORDERED(OrderedDemo, SecondEvent, 20)
{
  g_log.append("ready");
  CHECK_EQUAL(2, g_log.count);
}

// Level 30: verify accumulated state from both level-20 tests.
TEST_ORDERED(OrderedDemo, VerifyLog, 30)
{
  CHECK_EQUAL(2, g_log.count);
  STRCMP_EQUAL("startup", g_log.entries[0]);
  STRCMP_EQUAL("ready", g_log.entries[1]);
}

// Level 40: shutdown.
TEST_ORDERED(OrderedDemo, Shutdown, 40)
{
  g_log.flush();
  CHECK_EQUAL(0, g_log.count);
  CHECK(g_log.flushed);
}

The leading TEST(OrderedDemo, StartsUninitialized) is a regular test: it runs before the ordered block. Ordered tests run as a block after all unordered tests by default.

Listing Ordered Tests

Pass -lo to print each ordered test’s location as group.name.file.line:

$ ./my_tests -lo
OrderedDemo.Init.examples/tests/OrderedTest.test.cpp.53
OrderedDemo.FirstEvent.examples/tests/OrderedTest.test.cpp.62
OrderedDemo.SecondEvent.examples/tests/OrderedTest.test.cpp.68
OrderedDemo.VerifyLog.examples/tests/OrderedTest.test.cpp.75
OrderedDemo.Shutdown.examples/tests/OrderedTest.test.cpp.83

When to Use Ordered Tests

Ordered tests are appropriate when:

  • You are integration-testing a stateful system (e.g. a database, a file system) where setup steps must precede query steps.

  • The test itself mutates persistent state that subsequent tests depend on.

Avoid them when:

  • Tests can be made independent through setup()/teardown() — independent tests are more robust and can be run in isolation.

  • You want the -s [seed] (shuffle) flag to help detect ordering dependencies — ordered tests are excluded from the shuffle.

C Wrapper Macros

These bridge C test files into the C++ test runner. See Testing C Code for full details.

Macro

Purpose

TEST_GROUP_C_WRAPPER(group)

Declares a C++ TEST_GROUP that calls C setup/teardown

TEST_GROUP_C_SETUP_WRAPPER(group)

Wires C setup into the C++ group’s setup()

TEST_GROUP_C_TEARDOWN_WRAPPER(group)

Wires C teardown into the C++ group’s teardown()

TEST_C_WRAPPER(group, name)

Wires a C test function into a C++ TEST

SKIPPED_TEST_C_WRAPPER(group, name)

Same as above but skipped

XFAIL_TEST_C_WRAPPER(group, name)

Same as above but expected to fail

TEST_ORDERED_C_WRAPPER(group, name, level)

Wires a C test function into a TEST_ORDERED

Examples