Version 1 (modified by sam, 8 years ago) (diff)

tutorial

LolUnit tutorial

This tutorial is a quick introduction to LolUnit.

LolUnit is still in its early development stages. Feel free to send comments, suggestions or questions to sam@hocevar.net.

Getting started

Only one line is required to start using LolUnit:

#include <lol/unit.h>

Fixtures

A fixture is a container class for tests that allows optional setup and teardown methods. To declare and automatically register a fixture, use the LOLUNIT_FIXTURE macro:

LOLUNIT_FIXTURE(MyFirstFixture)
{
};

A test is a method within a fixture that runs a series of checks. To declare and automatically register a test within a fixture, use the LOLUNIT_TEST macro:

LOLUNIT_FIXTURE(MyFirstFixture)
{
    LOLUNIT_TEST(MyFirstTest)
    {
    }
};

Add checks

Several macros are provided to perform various checks:

  • LOLUNIT_ASSERT(condition) will cause the current test to fail if condition is not met.
  • LOLUNIT_ASSERT_EQUAL(a, b) will cause the current test to fail if a and b are not equal.
  • LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, t) will cause the current test to fail if the floating point values a and b are not equal, with a tolerance of t.

This is how to populate our fixture:

LOLUNIT_FIXTURE(MyFirstFixture)
{
    LOLUNIT_TEST(Addition)
    {
        LOLUNIT_ASSERT_EQUAL(1 + 1, 2);
        LOLUNIT_ASSERT(2 + 2 < 5); /* Check that our value for 2 is not too large */
    }

    LOLUNIT_TEST(Division)
    {
        double a = 1.0 / 2;
        double b = 1.0 / 3;
        double c = 1.0 / 6;
        LOLUNIT_ASSERT_DOUBLES_EQUAL(a - b, c, 1e-10);
    }
};

Run the test

Fixtures and their tests are automatically registered in a list global to the program. A TextTestRunner object can then be used to run all tests:

int main(void)
{
    lol::TextTestRunner runner;
    return !runner.run();
}

And this is the output:

..

OK (2 tests)

Test failures

Let's add yet another test to MyFirstFixture:

    LOLUNIT_TEST(ExpectedFailure)
    {
        double a = 0.1;
        double b = 0.2;
        LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, 1e-10);
    }

And running it:

..F

!!!FAILURES!!!
Test Results:
Run:  3  Failures: 1  Errors: 0

1) test: MyFirstFixture::ExpectedFailure (F) line: 23 tutorial.cpp
double equality assertion failed
- Expected: a = 0.1
- Actual  : b = 0.2
- Delta   : 1e-10 = 1e-010

Comparison with CppUnit

LolUnit is very similar to CppUnit, except it requires fewer user input. This is what we would have done with CppUnit:

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestCase.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TextTestRunner.h>

class MyFirstFixture : public CppUnit::TestCase
{
    CPPUNIT_TEST_SUITE(MyFirstFixture);
        CPPUNIT_TEST(Addition);
        CPPUNIT_TEST(Division);
        CPPUNIT_TEST(ExpectedFailure);
    CPPUNIT_TEST_SUITE_END();

    void Addition()
    {
        CPPUNIT_ASSERT_EQUAL(1 + 1, 2);
        CPPUNIT_ASSERT(2 + 2 < 5); /* Check that our value for 2 is not too large */
    }

    void Division()
    {
        double a = 1.0 / 2;
        double b = 1.0 / 3;
        double c = 1.0 / 6;
        CPPUNIT_ASSERT_DOUBLES_EQUAL(a - b, c, 1e-10);
    }

    void ExpectedFailure()
    {
        double a = 0.1;
        double b = 0.2;
        CPPUNIT_ASSERT_DOUBLES_EQUAL(a, b, 1e-10);
    }
};
CPPUNIT_TEST_SUITE_REGISTRATION(MyFirstFixture);

int main(void)
{
    CppUnit::TextTestRunner runner;
    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
    return !runner.run();
}

One major problem I have with this system is that Addition needs to be declared and defined at two different places. Similarly, MyFirstFixture needs to be declared, then given as an argument to CPPUNIT_TEST_SUITE, and finally as an argument to CPPUNIT_TEST_SUITE_REGISTRATION. There is no reason the user should have to duplicate this information.