Version 2 (modified by 12 years ago) (diff) | ,
---|
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>
No additional compiler or linker flags are required as long as the <unit.h>
file is copied in a place where the compiler can find it.
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 ifcondition
is not met.LOLUNIT_ASSERT_EQUAL(a, b)
will cause the current test to fail ifa
andb
are not equal.LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, t)
will cause the current test to fail if the floating point valuesa
andb
are not equal, with a tolerance oft
.
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.