Tutorial§

So, you want to write some unit tests? This tutorial will walk you through the steps needed to write, build, and run a simple test.

Your first test§

Let's get started by taking a look at the test file we used when running tests. We'll discuss each part in detail below:

#include <mettle.hpp>
using namespace mettle;

suite<> first("my first suite", [](auto &_) {
  _.test("my first test", []() {
    expect(true, equal_to(true));
  });
});

Dissecting the test file§

First up, the obvious: we #include <mettle.hpp>, which imports all the code we need to build and run simple tests: test suites, matchers, and a test runner. With that out of the way, we can start defining our tests.

All tests are grouped into suites. Suites are created as global variables with the type mettle::suite<>, and take a string name and a callback function (typically a lambda). The callback lets us define our tests for the suite. It takes a single argument, a reference to a mettle::suite_builder<mettle::expectation_failure>, but since that's pretty long, we conventionally just say auto & and use a generic lambda instead:

suite<> first("my first suite", [](auto &_) {
  /* ... */
});

Note

There are lots of other options you can pass to the suite's constructor, like fixtures or test attributes, but we'll get to those later.

With the suite defined, now we just need to write our tests and add them via the suite builder. Like suites, tests have both a string name and a callback function, but this time the callback is the code to run when the test executes:

_.test(("my first test", []() {
  /* ... */
});

Inside our test function, we need to write some test code:

expect(true, equal_to(true));

This is an expectation. We'll discuss them in more detail later, but in short, they define the things we actually want to test in our tests. This expectation makes sure that true is equal to true. If it's not, the test will alert us to the fact so we can fix it (hopefully before the universe finishes crashing down around us).

Building the test§

Building a test is straightforward. Since mettle provides its own test runner with a main() function, the above source code is all you need for a fully-operational test. Just compile the test like so:

$ clang++ -std=c++14 -o test_first test_first.cpp -lmettle

Remember, mettle is a C++14 library, so you'll likely need to tell the compiler to use C++14 mode (or C++1y mode for slightly older compilers).

Running the test§

Once you've built the test, you just need to run the binary and observe the results. In this case, the results will look like:

$ ./test_first
.

1/1 test passed

The single dot (.) shows that our one and only test passed, which the summary confirms. However, if the unthinkable has happened and our test fails, we'd see something like this instead:

$ ./test_first
!

0/1 tests passed
  my first suite > my first test FAILED
    expected: true
    actual:   false

Here, we see an exclamation point (!) instead of a dot, to indicate a failed test. At the end of the output, the details of the failure are shown. With this information, we can hopefully diagnose the failure and fix the bug.

There are many more options that can be supplied to the test binary to alter its output or how it runs tests. To learn more about those, see Running Tests.