Skip to main content

µTest++ Testing Framework v4.0.0 released

· 3 min read

Version 4.0.0 is a new major release, removing reliance on static objects.

The µTest++ Testing Framework project is a C++ source code library that provides a lightweight testing framework specifically designed for embedded systems.

Prerequisites

When installed via xpm, this project requires the xPack Prerequisites.

However, like any source code library, this project can also be integrated into another project in the traditional manner, either by copying the relevant files into the target project or by linking the entire project as a Git submodule.

Installation

The most straightforward method to incorporate the @micro-os-plus/micro-test-plus package into a project is to declare it as a dependency using xpm.

xpm install @micro-os-plus/micro-test-plus@4.0.0 -verbose

Comprehensive instructions are available in the Install Guide.

Source code

Major changes

The major change introduced by v4.0.0 is removing reliance on static objects.

Previous versions internally used static instances of the runner and reporter, with test suites and test cases directly referring to them by a fixed name.

Therefore, the API was based on standalone functions:

int
main(int argc, char* argv[])
{
mt::initialize(argc, argv, "Minimal");

mt::test_case ("Check truth", [] {
mt::expect (true);
});

return mt::exit_code ();
}

The new version uses user-created runners, passing references to test suites and test cases via callable parameters.

Therefore, the new API uses methods of various objects (runner, suite, subtest):

int
main(int argc, char* argv[])
{
mt::runner tr{ "Minimal" };

auto& ts = tr.initialise(argc, argv);

ts.test ("Check truth", [] (auto& t) {
t.expect (true);
});

return tr.exit_code ();
}

This approach offers several advantages over the previous static design. Passing the runner, suite, and test-case objects explicitly as references makes the data flow visible and unambiguous, eliminates hidden global state, and allows the compiler to enforce ownership and lifetime rules. It also removes the dependency on static-initialisation order, which is undefined across translation units in C++ and a frequent source of subtle bugs in embedded environments where the C++ runtime start-up sequence may be non-standard.

Bug fixes

  • [#18]: Fix the numbering of test suites

Enhancements

  • [#12]: Support nested test cases
  • [#14]: Rework to remove reliance on static objects
  • [#17]: Add --output-file option to specify where to write the test results
  • [#20]: Rename the 'human' reporter
  • [#21]: Add location information to runner.abort()
  • [#22]: Use a vector of string_view for argument lists
  • [#23]: Add test code to compare TAP files
  • [#24]: Use colour only if stdout is a TTY
  • [#25]: Add --output-file support to the human reporter
  • [#26]: Replace variable templates with concepts

Known issues

  • None.

Continuous Integration tests

Prior to publication, a suite of tests was executed. The results can be reviewed at: